Suppose I have two hosts: A and B with users a and b. B is Windows machine with Cygwin installed, if this matters.

B is configured to be accessed from A through SSH without password (it contains A's public RCA key), so I can run commands on it from A in the following way:

ssh b@B [command]

But when I try to run a command, that requires to access an environment variable, the command fails:

[15:54:08] - a@A - ~
$ ssh b@B 'echo $ANT_HOME'

returns empty string.

The same command, if connected directly (not through SSH) is executed correctly:

b@B ~
$ echo $ANT_HOME

The latter is possible because the relevant variables were exported in "bash_profile":

export JAVA_HOME="/cygdrive/c/PROGRA~1/Java/jdk1.7.0_45"
export ANT_HOME="/cygdrive/c/PROGRA~1/apache-ant-1.9.0"

but for some reason this is not applied to the SSH case.

Some additional info that may be useful.

Host B has Windows XP + Cygwin. CYGWIN sshd is run under SYSTEM account. JAVA_HOME and ANT_HOME are defined in "system" environment variables part in Windows.

When I run "$ ssh b@B env" command, it does not print ANT_HOME or JAVA_HOME, but if I include them in sshd_config file, it does. But even then simple command ssh b@B 'echo $ANT_HOME' does not work as I would expect.

Please give me a hint what needs to be done to run the command through SSH.

3 Answers 3


From the man pages of my server:

  1. Reads the file ~/.ssh/environment, if it exists, and users are allowed to change their environment. See the PermitUserEnvironment option in sshd_config(5).

You need to declare the environment variables and allow them in the remote server location /etc/ssh/sshd_config, by enabling the property PermitUserEnvironment as PermitUserEnvironment yes and set your environment variables in ~/.ssh/environment.


When you run a command as an argument to ssh, the command is run directly by sshd; the shell is not involved.

You can verify this using something like the following:

ssh b@B pstree

It is the shell (bash in this case) that pulls in your .bash_profile, and it only does so if the shell is invoked as a login shell, or if the shell was invoked with the --login option (see the bash man page; look for INVOCATION). The environment you get when running a command directly is set by things like sshd and PAM when you log in.

Thus, if you want your .bash_profile, you need to run it under the shell and you need to run the shell as an interactive or login shell, like this:

ssh b@B "bash -l -c 'env'"

That should get you output you desire. The only thing to watch out for is that quoting gets tricky pretty quickly. Note that on Linux, at least,

ssh b@B bash -l -c 'env'

will not get you a login shell (I'm not sure why).

  • This works and you can also pass positional or optargs for a remote script, e.g., ssh foo@cloud "bash -l -c '~/bin/remote_script -p arg1 -q arg2'"
    – Samir
    Jan 27, 2018 at 20:37

If you do not want to mess with the SSH configuration and just start a program then create a script locally that defines the variables and runs the program. Now scp the script and run it over ssh.

 > cat <<EOF >run.sh
X=42 program
 > scp user@host run.sh user@host:path/to/target/ || exit
 > ssh user@host "cd path/to/target/; bash run.sh"

Now program is started under the environment variables X=42 on the other machine. Under Linux this works perfectly, however, for Cygwin the path to bash might be missing. But the point is that you can tunnel environment variables this way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.