~/.profile
is only executed by login shells. The program that calls the shell decides whether the shell will be a login shell (by putting a -
as the first character of the zeroth argument on the shell invocation). It is typically not executed when you log in to execute a specific command.
OpenSSH in particular invokes a login shell only if you don't specify a command. So if you do specify a command, ~/.profile
won't be read.
OpenSSH allows setting environment variables on the server side. This must be enabled in the server configuration, with the PermitUserEnvironment
directive. The variables can be set in the file ~/.ssh/environment
. Assuming you use public key authentication, you can also set per-key variables in ~/.ssh/authorized_keys
: add environment="FOO=bar"
at the beginning of the relevant line.
Ssh also supports sending environment variables. In OpenSSH, use the SendEnv
directive in ~/.ssh/config
. However the specific environment variable must be enabled with an AcceptEnv
directive in the server configuration, so this may well not work out for you.
One thing that I think always works (oddly enough) as long as you're using public key authentication is to (ab)use the command=
option in the authorized_keys
file. A key with a command
option is good only for running the specified command; but the command in the authorized_keys
file runs with the environment variable SSH_ORIGINAL_COMMAND
set to the command the user specified. This variable is empty if the user didn't specify a command and therefore expected an interactive shell. So you can use something like this in ~/.ssh/authorized_keys
(of course, it won't apply if you don't use this key to authenticate):
command=". ~/.profile; if [ -n \"$SSH_ORIGINAL_COMMAND\" ]; then eval \"$SSH_ORIGINAL_COMMAND\"; else exec \"$SHELL\"; fi" ssh-rsa …
Another possibility is to write a wrapper scripts on the server. Something like the following in ~/bin/ssh-wrapper
:
#!/bin/sh
. ~/.profile
exec "${0##*/}" "$@"
Then make symbolic links to this script called rsync
, unison
, etc. Pass --rsync-path='bin/rsync'
on the rsync
command line, and so on for other programs. Alternatively, some commands allow you to specify a whole shell snippet to run remotely, which allows you to make the command self-contained: for example, with rsync, you can use --rsync-path='. ~/.profile; rsync'
.
There is another avenue which depends on your login shell being bash or zsh. Bash always reads ~/.bashrc
when it's invoked by rshd or sshd, even if it's not interactive (but not if it's called as sh
). Zsh always reads ~/.zshenv
.
## ~/.bashrc
if [[ $- != *i* ]]; then
# Either .bashrc was sourced explicitly, or this is an rsh/ssh session.
. ~/.profile
fi
## ~/.zshenv
if [[ $(ps -p $PPID -o comm=) = [rs]shd && $- != *l* ]]; then
# Not a login shell, but this is an rsh/ssh session
. ~/.profile
fi
ssh name@host -t echo $PATH
. – Gert Dec 17 '10 at 07:54PS1
from.profile
, set it in.bashrc
instead, and don't export it. See Difference between .bashrc and .bash_profile, Which setup files should be used for setting up environment variables with bash?. – Gilles 'SO- stop being evil' Dec 17 '10 at 20:38