I am attempting to call a handful of local bash scripts that I have written for health checking applications on remote servers.
ssh -q <servername> "bash -s" -- < ./path/to/local/script.bash
The above runs perfectly fine from the command line. However, when I wrap the call in python, I keep getting errors stating:
bash: /path/to/file/script.bash: No such file or directory
As for my python, I am using the subprocess module. Python:
bashcmd="ssh -q %s \"bash -s\" -- < ./%s" % (<server>,<bashfilepath>)
process=subprocess.Popen(bashcmd.split, stdout=subprocess.PIPE)
output, error = process.communicate()
Any help would be appreciated!
Redirection in your first example is done by shell. Standard input for ssh
read from the file ./path/to/local/script.bash
, which ssh
passes to the process on remote machine.
You can not use shell redirections, because you are not running a command from shell. Instead you can use stdin
and stdout
arguments for Popen()
to set the standard input and output for your process. You need to open the file and then pass the handle to stdin
. This is explained in: Using files as stdin and stdout for subprocess.
In python example, you pass ssh -q <server> "bash -s" -- < ./<filepath>
as 1st argument to subprocess.Popen()
, which excepts a list of arguments, or a single string: the path to the executable. You get No such file or directory
error because your string argument is not a path to an executable. Correct format following the standard convention would be subprocess.Popen(["/path/to/executable", "arg1", "arg2", ...])
.
All this put together, your example should look something like:
with open("./path/to/local/script.bash") as process_stdin:
p = subprocess.Popen(["/usr/bin/ssh", "-q", server, "--", "bash", "-s"],
stdin=process_stdin, stdout=subprocess.PIPE)
out, err = p.communicate()
This all is explained in Python documentation for subprocess module.