Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to execute an local script in remote server with parameters

Tags:

linux

bash

ssh

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?

like image 614
Alireza Avatar asked Nov 28 '16 21:11

Alireza


People also ask

How do I run a local script in a remote server?

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.

How do you execute a script parameter?

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.

How do I connect to a remote server and execute certain commands?

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.


2 Answers

With 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

With Any POSIX-Compliant /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
like image 199
Charles Duffy Avatar answered Sep 22 '22 20:09

Charles Duffy


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
like image 32
chepner Avatar answered Sep 23 '22 20:09

chepner