I have written an bash script foo.sh
#!/usr/bin/env bash
echo "starting the script";
I want to execute it in my remote server.
I tried ssh user@remote-addr < test.sh
and it worked.
After that I changed the test.sh file like this
#!/usr/bin/env bash
echo "starting the script";
echo $1;
now I want to pass a local parameter to execute with my script but when I type ssh user@remote-addr < test.sh testparam
it returns an error.
How can I pass parameters with my scripts?
The bash -s command means “execute the following commands in a new bash session.” The -s flag makes it read from standard input, and the < script.sh bit will read a local script file into standard input. The file is read entirely locally, and all gets sent to the remote server without uploading anything.
Arguments can be passed to the script when it is executed, by writing them as a space-delimited list following the script file name. Inside the script, the $1 variable references the first argument in the command line, $2 the second argument and so forth. The variable $0 references to the current script.
The SSH client program can be used for logging into a remote machine or server and for executing commands on a remote machine. When command is specified, it is executed on the remote host/server instead of a login shell.
bash
or ksh
as /bin/sh
If your remote /bin/sh
is provided by bash or ksh, you can safely do the following with an untrusted argument list, such that even malicious names (like $(rm -rf $HOME).txt
) can be passed as arguments safely:
runRemote() {
local args script
script=$1; shift
# generate eval-safe quoted version of current argument list
printf -v args '%q ' "$@"
# pass that through on the command line to bash -s
# note that $args is parsed remotely by /bin/sh, not by bash!
ssh user@remote-addr "bash -s -- $args" < "$script"
}
...thereafter:
runRemote test.sh testparam
/bin/sh
Note that the following still needs to be run in bash
, but will work correctly when the system being ssh
'd into has a /bin/sh
that is POSIX-baseline, so long as the remote machine has bash installed.
To be safe against sufficiently malicious argument data (attempting to take advantage of the non-POSIX compliant quoting used by printf %q
in bash when nonprintable characters are present in the string being escaped) even with a /bin/sh
that is baseline-POSIX (such as dash
or ash
), it gets a bit more interesting:
runRemote() {
local script=$1; shift
local args
printf -v args '%q ' "$@"
ssh user@remote-addr "bash -s" <<EOF
# pass quoted arguments through for parsing by remote bash
set -- $args
# substitute literal script text into heredoc
$(< "$script")
EOF
}
Similarly invoked as:
runRemote test.sh testparam
Use the -s
option, which forces bash
(or any POSIX-compatible shell) to read its command from standard input, rather than from a file named by the first positional argument. All arguments are treated as parameters to the script instead.
ssh user@remote-addr 'bash -s arg' < test.sh
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With