How to automate sftp and remote shell calls?

I am on windows and I have remote linux server. I do not have admin access to neither of them. I have following set of steps/commands

cp C:/ ... /file.war C:/temp/update/file.war
sftp server
write password
cd /tmp
put file.war
exit
ssh server
write password
chmod 755 /tmp/file.war
pbrun -u server_user bash
cd /tomcat_location/webap
rm -r file
rm file.war
cp /tmp/file.war file.war 
ps -ax | grep tomcat
kill -9 tomcat_pid
cd /tomcat_location/commands
./startup.sh

If I would be doing all of that locally. I would easilly write shell/bash script for it. But I am on two different computrers. The password is the same all the time. The pbrun is command to switch users using my own password.

Is there some simple way how to transform this to single script? Which would ask for the password and do all the steps automatically. Or at least to the part where the tomcat is being restarted (sftp, chmod, removing and copig part)? I am not able to install any new software. I have java 8 and perl installed on my local pc.

I tried a few things with perl exec but I do not know how to keep state of its cmd. It would be nice if the result would be as close to the original commands as possible.


First, figure out which commands do something on their own, and which ones need sub-commands being passed as input. For example, sftp is in the latter category – everything below "sftp server" and up to "exit" is not a separate top-level command, but merely input to stdin of the 'sftp' process.

So in your script, there are really just 3 commands to be executed: the cp, the sftp, and the ssh. Everything else is text to be fed to their standard input (stdin).

  • In Bash scripts, you would most commonly use "heredoc" <<EOF to pass multiple lines of text to a program's stdin (although other methods are possible).

  • In Perl scripts you can use open() to start a process – look up what the "-|" and "|-" special MODE values do in perldoc -f open (section "Opening a filehandle into a command").

  • And in Java, from a quick google, when you start a process through Runtime.exec(), the resulting Process object has the confusingly named .getOutputStream() which allows you to write to its stdin.

(And even within the commands run through ssh, technically there's another layer of the same – when you start bash through pbrun, it also takes further commands through stdin, so you could use another << there as well, but it might not be necessary. I would still try to automate this "inside-out", i.e. first turn the pbrun part into a script that's being run on the server.)

The password prompt of both sftp and ssh is an exception, in that it specifically deals with interactive keyboard input even if stdin comes from some other source. To avoid the password prompt, ideally you would set up an authentication method that doesn't involve passwords, namely public-key auth – this is supported by all SSH clients and servers, and does not need any sort of admin privileges on either side (unless someone deliberately disabled it). Look up ssh-keygen and authorized_keys.

(Normally I'd also suggest OpenSSH's built-in "connection multiplexing" feature, i.e. -o ControlPath=... and related options, but you're using Windows and I'm not sure whether this feature is available on the Windows builds of OpenSSH. However, if it does work, then it would also allow you to start a single "background" connection, enter the password once, then run both SFTP and shell over that connection.)

There's also another way to approach this. Your goal isn't to "run the sftp command" – your goal is to upload a file using the SFTP protocol, and you don't need the sftp command for that. You can instead directly use an SSH/SFTP client module for Perl or Java – then you can develop the deployment tool like you're developing the application itself.

(For Java, sshj appears to be a popular one, while JSch is getting slightly out-of-date. Perl has Net::SSH2 which might be difficult to install on Windows.) Most of them will even allow you to use both SFTP and shell commands over the same SSH connection.