{"thread":{"id":"14013","subject":"Getting the path right for git over SSH","startedAt":"2008-06-18T11:22:12Z","lastAt":"2008-06-18T11:22:12Z","messageCount":1,"participants":["Ben Schmidt"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"80216","messageId":"4858EFE4.3050204@yahoo.com.au","threadId":"14013","inReplyTo":null,"subject":"Getting the path right for git over SSH","fromName":"Ben Schmidt","fromEmail":"mail_ben_schmidt@yahoo.com.au","sentAt":"2008-06-18T11:22:12Z","receivedAt":"2008-06-18T11:22:12Z","isPatch":false,"sender":{"key":"mail_ben_schmidt@yahoo.com.au","avatar":null},"body":"Hi,\n\nI wrote the post below on the Apple Mac OS X Server mailing list, though\nnot subscribed to that list, because I found a solution that I thought\nothers might appreciate having documented, as I found it quite a bit of\ntrouble getting it right myself. Though written for Mac OS X, the\nessentials apply to any Unix-like system. As the OP's problem arose when\nusing Git, I thought perhaps some other Git users may appreciate the\nideas as well, so I am forwarding this mail to you. If you think it\nwould be helpful, post it to a mailing list or FAQ somewhere, or\nwhatever else you like, and Google will hopefully find it and help other\nusers with it. The original message and my followup, which isn't\nthreaded, are here:\n\nhttp://lists.apple.com/archives/macos-x-server/2008/May/msg00678.html\nhttp://lists.apple.com/archives/macos-x-server/2008/Jun/msg00251.html\n\nBen.\n\n\n\n> Hi all,\n>\n> I've recently begun administering a Mac OS X Server 10.5.3 Leopard\n> server used, in part, for my company's developers. We use a couple of\n> tools (i.e., git, a version control system) that typically invoke non-\n> interactive, non-login shells to do stuff. However, I discovered that\n> when a user logs in via one of these tools, which in turn invokes SSH,\n> the bash shell that user uses has a very minimal $PATH set. Thus, my\n> question:\n>\n> Is there some place on Mac OS X Server to alter a non-interactive,\n> non- login bash shell's $PATH in a system-wide way? The only solutions\n> I've come across are all per-user solutions (e.g., ~/.bashrc or\n> ~/.profile, ~/.ssh/environment, and so on).\n\nThese kinds of issues have been annoying me, too, and Googling to find a\nsolution led me to your post. After more trouble than I would have\nliked, I discovered and came up with the following. (Don't get\ndisheartened part way through; there is a pretty good climax at the\nend!) (Also, though I am on Mac OS X Client/User 10.4.9, I expect all\nthis applies to Mac OS X Server, and probably to 10.5, too.)\n\n- When ssh is started without a commandline, an interactive login shell\n   is started. This is nice! Everything works!\n\n- When ssh is started with a commandline, a non-interactive non-login\n   shell is started. However...bash does not use $BASH_ENV in this case,\n   so setting it in ~/.ssh/environment (e.g. to /etc/profile) doesn't\n   help. What bash does is source /etc/bashrc and ~/.bashrc--it evidently\n   treats ssh like rsh and does a little more than is documented even for\n   rsh (search for rsh in the bash man page for details). This is pretty\n   much never what I want, as I would like all ssh logins to be 'login\n   shells' and use /etc/profile and ~/.profile, but only those that are\n   interactive to use ~/.bashrc. I came up with this fairly robust\n   per-user solution, which I flooded with comments to help me remember\n   what's used when:\n\n   In /etc/profile\n\n     # System-wide .profile for sh(1)\n     PATH=...\n     export PATH\n     # Source /etc/bashrc for interactive shells.\n     [ -n \"$PS1\" -a -r /etc/bashrc ] && source /etc/bashrc\n     ... stuff for login shells (more environment mostly)\n\n   In /etc/bashrc\n\n     # System-wide .bashrc file for interactive bash(1) shells.\n     ... stuff for interactive shells (aliases and terminal stuff mostly)\n\n   In ~/.profile\n\n     # For login shells (interactive or not).\n     # For interactive non-login shells see ~/.bashrc.\n     # For non-interactive non-login ssh shells see ~/.bashrc.\n     # For other non-interactive non-login shells see $BASH_ENV.\n     # At present this is sourced by ~/.bashrc for the ssh case, so\n     # all ssh sessions act like login sessions.\n     PATH=...\n     export PATH\n     # Source ~/.bashrc for interactive shells.\n     if [ -n \"$PS1\" -a -r ~/.bashrc ]; then source ~/.bashrc ; fi\n     ... stuff for login shells (more environment mostly)\n\n   In ~/.bashrc\n\n     # For interactive non-login shells\n     # and non-interactive non-login ssh shells.\n     # For login shells (interactive or not) see first existent of\n     # ~/.bash_profile, ~/.bash_login and ~/.profile.\n     # For other non-interactive non-login shells see $BASH_ENV.\n     # At present, this is sourced by ~/.profile so runs for all\n     # interactive shells (login or not).\n     # If the shell isn't actually interactive it is an ssh session, and\n     # we want to source /etc/profile and ~/.profile instead. We can't\n     # use a simple test of $PS1 and must test $- because /etc/bashrc\n     # (also sourced when bash detects ssh) sets $PS1. (We empty it\n     # here.)\n     if echo $- | grep -q i ; then : ; else\n       [ -r /etc/profile ] && source /etc/profile\n       PS1=\n       source ~/.profile\n       return\n     fi\n     ... stuff for interactive shells (aliases and terminal stuff mostly)\n\n   This is OK if you're a single user wanting your shell to behave like\n   you want it to, particularly if you're setting up your own account on\n   a remote machine. Note that I have made one functional modification to\n   /etc/profile: only sourcing /etc/bashrc if interactive; on my version\n   of OS X it is sourced for all login shells, interactive or not. I\n   have written ~/.bashrc so it will work OK without that change, though,\n\n   But if you're a sysadmin, you don't want to deal with all this crap\n   for every user, particularly if/when they break it.\n\n- Setting $PATH and/or other environment variables directly via\n   ~/.ssh/environment, rather than trying to get bash to run a script\n   does work, but is another per-user solution.\n\n- Eventually I came up with this system-wide solution. Add\n\n     ForceCommand /usr/local/bin/ssh_session\n\n   to /etc/sshd_config which makes ssh run that command regardless of\n   what the user requested. It sets $SSH_ORIGINAL_COMMAND, though, so we\n   can just use that to do what the user originally asked for, and seems\n   to reliably work when used with eval. We can fall back to login if a\n   command is not requested. This is what my /usr/local/bin/ssh_session\n   script does:\n\n     #!/bin/bash\n     export SSH_SESSION=1\n     if [ -z \"$SSH_ORIGINAL_COMMAND\" ] ; then\n       export SSH_LOGIN=1\n       exec login -fp \"$USER\"\n     else\n       export SSH_LOGIN=\n       [ -r /etc/profile ] && source /etc/profile\n       [ -r ~/.profile ] && source ~/.profile\n       eval exec \"$SSH_ORIGINAL_COMMAND\"\n     fi\n\n   It is of course important to\n\n     chmod +x /usr/local/bin/ssh_session\n\n   I obviously haven't allowed for ~/.bash_profile or ~/.bash_login, but\n   others are likely to want a different solution for these specifics\n   anyway. The important thing is that you can easily see where to add\n   environment variables or other commands for all cases, the login case,\n   and the non-login (command execution) case. I believe the command\n   execution case also applies to subsystems (e.g. sftp).\n\n   There are potentially some difficulties if using X forwarding, due to\n   use of the login command, as documented in the sshd_config man page at\n   the UseLogin directive; but I think these would be minor--they would\n   only occur if you start an interactive ssh session with X forwarding,\n   but more likely than not you would make a different ssh process do\n   this with -Nf or run a specific command rather than an interactive\n   session, I think. And they may not occur at all when -fp is used.\n\n   All that said, this seems to be working well so far for me!\n\nHope this can help some others.\n\nBen Schmidt.\nMelbourne, Australia.\n"}]}