Source .profile and .bashrc on ssh login without tty

ssh

How do I make sure ssh sources .profile and .bashrc on login without tty?

I have a Mac (10.6.8) that I'm using for various UNIX-y tasks like hosting git repositories. I have remote login enabled via the System Preferences "Sharing" pane. When I ssh into the machine, bash sources ~/.profile, which I have set up to source my ~/.bashrc file and set up my MacPorts path. The problem is that when I run ssh without a tty, like this:

ssh myhost echo \$PATH

Or run a git command that essentially uses ssh in the same way:

git clone ssh://myhost/~/code/myrepo.git

My ~/.profile file is never sourced, so my $PATH variable is missing /opt/local (where MacPorts has installed git). I am aware that:

  • I can configure git on my local machine to use /opt/local/bin/git-* on my remote machine
  • I wouldn't have this problem if I was forcing a tty with ssh -t

But I don't want to do either of those. I want my remote machine to source my ~/.profile file regardless of whether or not I'm logging in w/ a tty.

How do I make that dream a reality?

Also: I checked the behavior on a couple Linux machines (Debian and Fedora), and both systems seem to source the ~/.bashrc file on login regardless of whether it is a tty. I was under the impression that BSD and Linux both use the same OpenSSH and bash implementations, so it seems like the difference in behavior might come from differences in /etc config files?

Best Answer

Bash has special provisions in its source code to source ~/.bashrc when it's invoked by rshd or sshd. It's a compilation option, which given your experience seems not to be turned on under OSX.

If you're logging in with a key, you can (ab)use the command= option in the ~/.ssh/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 (empty for interactive sessions). 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 …

Note that I put line breaks above for legibility, but this actually needs to be all on one line.

How can I set environment variables for a remote rsync process? may have other helpful suggestions.