I have a local script that I want to run on several remote servers. The command syntax I'm using is:
ssh <remote_server> "bash -s" < ./local_script.sh
This works fine, and even lets me pass parameters to local_script.sh. However, I'd really like to pass an input file to it, as in:
local_script.sh < local_file.txt
Combining these two statements gives:
ssh <remote_server> "bash -s" < ./local_script.sh < local_file.txt
When I run this, I get
bash: line 1: FOO: command not found
bash: line 2: BAR: command not found
bash: line 3: BAZ: command not found
...
where FOO, BAR, BAZ, etc. are the first word on each line of local_file.txt:
FOO FOO_PARAM1
BAR BAR_PARAM1
BAZ BAZ_PARAM2
...
So, it looks like "bash -s"
on the remote server is interpreting local_file.txt as a script file, instead of an input file to local_script.sh. Is there any way to fix this (other than creating a wrapper script)?
Best Answer
While
ssh
provides for two separate output streams (for stdout and stderr), it only feeds one input stream (stdin). So you'd need either to pass the script content and input file via different mechanisms.For instance, one via a variable, one via stdin:
(assuming both your
ssh
client passes theLC_*
variable (SendEnv
inssh_config
) and thesshd
server accepts them (AcceptEnv
insshd_config
))Or simply pass the content of the
local_script.sh
as the remote shell code assuming the login shell of the remote user is the right one for the syntax of that script:Or concatenate the code and input fed to
ssh
's stdin like with:Here using
bash
becausebash
will take care of reading the input one byte at a time so as not to read past that}; exit
line while not all other shells do that.Or if
sed
on the remote host is GNUsed
:(here having the code evaluated by the login shell of the remote user and assuming it's Bourne-like)