How can I pass an environment variable through an ssh command?

43

13

How can I pass a value into an ssh command, such that the environment that is started on the host machine starts with a certain environment variable set to my choosing?

EDIT: The goal is to pass the current kde desktop ( from dcop kwin KWinInterface currentDesktop ) to the new shell created so that I can pass back an nfs locations to my JEdit instance on the original server which is unique for each KDE desktop. ( Using a mechanism like emacsserver/emacsclient)

The reason multiples ssh instances can be in flight at one time is because when I'm setting up my environment, I'm opening a bunch of different ssh instances to different machines.

Ross Rogers

Posted 2009-09-29T22:56:04.033

Reputation: 3 025

Question was closed 2016-04-03T04:45:14.357

Answers

18

The ~/.ssh/environment file can be used to set variables you want available for remote commands. You will have to enable PermitUserEnvironment in the sshd configuration.

Variables set this way are exported to child processes, so you can:

echo "Foo=Bar" > sshenv
echo "Joe=37" >> sshenv
scp sshenv user@server:~/.ssh/environment
ssh user@server myscript

and myscript will know that Foo is Bar and Joe is 37.

John T

Posted 2009-09-29T22:56:04.033

Reputation: 149 037

2This answer doesn't really seem to answer the question. – intuited – 2010-06-17T19:54:13.770

1This will break if two processes are trying to do this with different sets of values concurrently – nafg – 2019-03-28T03:47:49.210

can you please add an example of what the format of ~/.ssh/environment file is? – Alexander Mills – 2019-04-29T22:10:32.823

3the variable needs to change potentially every ssh call – Ross Rogers – 2009-09-29T23:03:29.760

1Might be better to describe what you're trying to do and why. There could be other solutions. The environment file would have to be dynamically generated on each ssh call, which isn't impossible. – EmmEff – 2009-09-29T23:31:18.347

What is going to change? The values of those variables or even their names? – innaM – 2009-09-30T06:19:05.143

darn. I tried this solution, but I don't have access the sshd config file and putting vars in ~/.ssh/environment or ~/.ssh2/environment doesn't work. I guess I'm going to use a kludge where I leave this variable on an nfs disk and then snarf it up with my ~/.tcsh setup file. – Ross Rogers – 2009-09-30T18:46:16.640

59

The SendEnv option is your guy.

~/.ssh/config: (locally)

SendEnv MYVAR

/etc/ssh/sshd_config: (on the remote end)

AcceptEnv MYVAR

Now, whatever the value of $MYVAR locally is, it becomes available in the remote session too.
If you login multiple times, each session will have its own copy of $MYVAR, with possibly different values.

~/.ssh/environment is meant for other purposes. It kind of acts as $ENV file when executing non-shell commands remotely.

user15617

Posted 2009-09-29T22:56:04.033

Reputation:

6can also be passed (more usefully) through the command line as ssh myserver -o SendEnv="MYVAR", so you can make it dynamic in scripts. – Mike Campbell – 2017-02-03T16:27:05.550

32

You can pass values with a command similar to the following:

ssh username@machine VAR=value cmd cmdargs

You can test with:

ssh machine VAR=hello env

On tcsh the following seems to work:

ssh machine "setenv VAR <value>; printenv"

Waltor

Posted 2009-09-29T22:56:04.033

Reputation: 321

2How can i use the session interactively? – luckydonald – 2016-11-04T19:01:15.807

1Note that the first example only works for the first command if you are chaining commands together (with &&). Using bash, export VAR=value; instead of setenv in the third form works for this case. – contrebis – 2017-02-28T14:27:10.520

2This is what I ended up doing! Wherever you go, take your environment with you. Your can do it like that: ssh user@host "$(<env_to_source.sh) command ...". In env to source, I have export var=value ; on separate lines (remember the semicolon). – Tomasz Gandor – 2019-01-11T14:16:12.467

@TomaszGandor: years later, still perfect - allows me to even pass complex stuff like PROMPT_COMMAND up there w/o needing to worry about escaping :-) 1000 thanks. – Red Pill – 2019-06-05T13:38:50.120

1Looks like that works well for bash environments. Too bad I'm in a corporate tcsh environment. – Ross Rogers – 2012-05-21T21:45:29.610

30

There's also a horrible, horrible hack.

If your script is consuming the variable on the remote end (i.e. you can name it whatever you want), you can abuse the locale variables. Any variable of the form LC_* will be passed on verbatim, with no requirement for configuration whatsoever.

For example, we have a series of bastion servers at one of my clients. I hate having to connect to it, just to connect to another server... and another server... every time. I have a script that behaves just like SSH, except that it's clever.

Basically, if LC_BOUNCE_HOSTS is set, it splits it on spaces and peels off the first host. Then it bounces through and runs the same script. On the destination node, this list is eventually empty, so it runs the command. I also have a debug mode (which is great during network troubles), which is set by LC_BOUNCE_DEBUG. Since ssh passes all of these along for me magically, I don't have to do anything other than recognize the end of the host list (which I do with a -- option).

I feel dirty every time I use this, but it works everywhere I've tried it.

Jayson

Posted 2009-09-29T22:56:04.033

Reputation: 401

Good catch !! So wonderful and a little dirty !! – zw963 – 2016-12-14T18:21:16.063

2This is horrible. Bravo. – Pi Delport – 2018-03-06T20:10:04.050

1

This is horribly great, thanks! I've used it for one more terribly nice hack! :)

– lumbric – 2018-05-12T11:14:31.163

This should no longer work at least since OpenSSH version 5.3p1, because new server config only accept specific LC_xxx variables (but not AcceptEnv LC_*) – Johnny Wong – 2019-03-19T10:47:15.753

also whoever that rely on what could be seen as a bug is expecting things to break one day. – Loïc Faure-Lacroix – 2019-07-18T01:50:03.320

2Why would you use something like that instead of OpenSSH's built-in ProxyCommand option? Edit your ~/.ssh/config and add a block like Host *.example.com: ProxyCommand -ssh -W %h:%p bastionhost and let it tunnel your connections for you. – Kirk Strauser – 2012-09-26T21:32:36.077

1For tunnels, it's not so bad. For env vars, two reasons:

One, PermitUserEnvironment requires admin access to configure on the server to pass them directly. Passing them through the command line is also really hard to get the escaping right.

Two, multiple bastions must be bounced through, making this a bit more complex -- especially when it's not clear from the source host which path to take to a certain destination host. It's easier to say: "bounce-ssh bast1 bast2 nodeX -- rm -rf /" than to maintain the routes for an evolving population of hosts in a series of ssh-config files. – Jayson – 2012-09-26T22:59:50.783

1

bla="MyEnvSelection=dcop"
ssh user@host "export $bla && ./runProg"

On bash I tested with:

$ echo '#!/bin/sh' > readEnv.sh
$ echo 'echo "MyEnv: "$MyEnvFromSSH' >> readEnv.sh

$ scp readEnv.sh user@host:~/
$ bla="MyEnvFromSSH=qwert"
$ ssh user@host "export $bla && ./readEnv.sh"

Zeh

Posted 2009-09-29T22:56:04.033

Reputation: 19