Run shell script using fabric and piping script text to shell's stdin

Peter Lyons picture Peter Lyons · Jul 22, 2012 · Viewed 9k times · Source

Is there a way to execute a multi-line shell script by piping it to the remote shell's standard input in fabric? Or must I always write it to the remote filesystem, then run it, then delete it? I like sending to stdin as it avoids the temporary file. If there's no fabric API (and it seems like there is not based on my research), presumably I can just use the ssh module directly. Basically I wish fabric.api.run was not limited to a 1-line command that gets passed to the shell as a command line argument, but instead would take a full multi-line script and write it to the remote shell's standard input.

To clarify I want the fabric equivalent of this command line:

ssh somehost /bin/sh < /tmp/test.sh

Except in python the script source coude wouldn't come from a file on the local filesystem, it would just be a multiline string in memory. Note that this is a single logical operation and there is no temporary file on the remote side, meaning unexpected failures and crashes don't leave orphan files. If there were such an option in fabric (which is what I'm asking about), there would not need to be a temporary file on either side and this would only require a single ssh operation.

Answer

sabs6488 picture sabs6488 · Oct 21, 2013

You could use Fabric operations. you can use fabric.operations.put(local_path, remote_path, use_sudo=False,mirror_local_mode=False,mode=None)

to copy the script file to the remote path and then execute it.

or,

you could use fabric.operations.open_shell, but that will work only for series of simple commands, for scripting involving logical flow, it is better to use put operation and execute the script just like you do on a local server.