[linux] Passing variables in remote ssh command

I want to be able to run a command from my machine using ssh and pass through the environment variable $BUILD_NUMBER

Here's what I'm trying:

ssh [email protected] '~/tools/myScript.pl $BUILD_NUMBER'

$BUILD_NUMBER is set on the machine making the ssh call and since the variable doesn't exist on the remote host, it doesn't get picked up.

How do I pass the value of $BUILD_NUMBER ?

This question is related to linux bash shell ssh

The answer is


The list of accepted environment variables on SSHD by default includes LC_*. Thus:

LC_MY_BUILDN="1.2.3" ssh -o "SendEnv LC_MY_BUILDN" ssh-host 'echo $LC_MY_BUILDN'
1.2.3

It is also possible to pass environment variables explicitly through ssh. It does require some server-side set-up through, so this this not a universal answer.

In my case, I wanted to pass a backup repository encryption key to a command on the backup storage server without having that key stored there, but note that any environment variable is visible in ps! The solution of passing the key on stdin would work as well, but I found it too cumbersome. In any case, here's how to pass an environment variable through ssh:

On the server, edit the sshd_config file, typically /etc/ssh/sshd_config and add an AcceptEnv directive matching the variables you want to pass. See man sshd_config. In my case, I want to pass variables to borg backup so I chose:

AcceptEnv BORG_*

Now, on the client use the -o SendEnv option to send environment variables. The following command line sets the environment variable BORG_SECRET and then flags it to be sent to the client machine (called backup). It then runs printenv there and filters the output for BORG variables:

$ BORG_SECRET=magic-happens ssh -o SendEnv=BORG_SECRET backup printenv | egrep BORG
BORG_SECRET=magic-happens

As answered previously, you do not need to set the environment variable on the remote host. Instead, you can simply do the meta-expansion on the local host, and pass the value to the remote host.

ssh [email protected] '~/tools/run_pvt.pl $BUILD_NUMBER'

If you really want to set the environment variable on the remote host and use it, you can use the env program

ssh [email protected] "env BUILD_NUMBER=$BUILD_NUMBER ~/tools/run_pvt.pl \$BUILD_NUMBER"

In this case this is a bit of an overkill, and note

  • env BUILD_NUMBER=$BUILD_NUMBER does the meta expansion on the local host
  • the remote BUILD_NUMBER environment variable will be used by
    the remote shell

(This answer might seem needlessly complicated, but it’s easily extensible and robust regarding whitespace and special characters, as far as I know.)

You can feed data right through the standard input of the ssh command and read that from the remote location.

In the following example,

  1. an indexed array is filled (for convenience) with the names of the variables whose values you want to retrieve on the remote side.
  2. For each of those variables, we give to ssh a null-terminated line giving the name and value of the variable.
  3. In the shh command itself, we loop through these lines to initialise the required variables.
# Initialize examples of variables.
# The first one even contains whitespace and a newline.
readonly FOO=$'apjlljs ailsi \n ajlls\t éjij'
readonly BAR=ygnàgyààynygbjrbjrb

# Make a list of what you want to pass through SSH.
# (The “unset” is just in case someone exported
# an associative array with this name.)
unset -v VAR_NAMES
readonly VAR_NAMES=(
    FOO
    BAR
)

for name in "${VAR_NAMES[@]}"
do
    printf '%s %s\0' "$name" "${!name}"
done | ssh [email protected] '
    while read -rd '"''"' name value
    do
        export "$name"="$value"
    done

    # Check
    printf "FOO = [%q]; BAR = [%q]\n" "$FOO" "$BAR"
'

Output:

FOO = [$'apjlljs ailsi \n ajlls\t éjij']; BAR = [ygnàgyààynygbjrbjrb]

If you don’t need to export those, you should be able to use declare instead of export.

A really simplified version (if you don’t need the extensibility, have a single variable to process, etc.) would look like:

$ ssh [email protected] 'read foo' <<< "$foo"

Escape the variable in order to access variables outside of the ssh session: ssh [email protected] "~/tools/myScript.pl \$BUILD_NUMBER"


Variables in single-quotes are not evaluated. Use double quotes:

ssh [email protected] "~/tools/run_pvt.pl $BUILD_NUMBER"

The shell will expand variables in double-quotes, but not in single-quotes. This will change into your desired string before being passed to the ssh command.


Examples related to linux

grep's at sign caught as whitespace How to prevent Google Colab from disconnecting? "E: Unable to locate package python-pip" on Ubuntu 18.04 How to upgrade Python version to 3.7? Install Qt on Ubuntu Get first line of a shell command's output Cannot connect to the Docker daemon at unix:/var/run/docker.sock. Is the docker daemon running? Run bash command on jenkins pipeline How to uninstall an older PHP version from centOS7 How to update-alternatives to Python 3 without breaking apt?

Examples related to bash

Comparing a variable with a string python not working when redirecting from bash script Zipping a file in bash fails How do I prevent Conda from activating the base environment by default? Get first line of a shell command's output Fixing a systemd service 203/EXEC failure (no such file or directory) /bin/sh: apt-get: not found VSCode Change Default Terminal Run bash command on jenkins pipeline How to check if the docker engine and a docker container are running? How to switch Python versions in Terminal?

Examples related to shell

Comparing a variable with a string python not working when redirecting from bash script Get first line of a shell command's output How to run shell script file using nodejs? Run bash command on jenkins pipeline Way to create multiline comments in Bash? How to do multiline shell script in Ansible How to check if a file exists in a shell script How to check if an environment variable exists and get its value? Curl to return http status code along with the response docker entrypoint running bash script gets "permission denied"

Examples related to ssh

Starting ssh-agent on Windows 10 fails: "unable to start ssh-agent service, error :1058" How to solve "sign_and_send_pubkey: signing failed: agent refused operation"? key_load_public: invalid format ssh connection refused on Raspberry Pi Getting permission denied (public key) on gitlab Verify host key with pysftp Can't connect to Postgresql on port 5432 Checkout Jenkins Pipeline Git SCM with credentials? How to open remote files in sublime text 3 how to setup ssh keys for jenkins to publish via ssh