Saturday, January 29, 2011

(svn+ssh) getting bash to load my PATH over SSH

This problem comes up with me trying to make svnserve (Subversion server) available on a server through SSH. I compiled SVN and installed it in $HOME/bin. Local access to it (not through SSH) works fine.

Connections to svn+ssh fail due to:

bash: svnserve: command not found

Debugging this, I've found that:

ssh user@server "which svnserve"

says:

which: no svnserve in (/usr/bin:/bin)

This is strange, because I've updated the path to $HOME/bin in my .bashrc, and also added it in ~/.ssh/environment. However, it seems like the SSH doesn't read it. Although when I run:

ssh user@server "echo $PATH"

It does print my updated path!

What's going on here? How can I make SSH find my svnserve? Thanks in advance

  • As it happens, .bashrc and .bash_profile are only executed if you're in an interactive shell. When you login through ssh, you are not in an interactive shell, therefore your custom PATH definitions are never run. You can associate a script to non-interactive sheels using BASH_ENV. Check also .ssh/environment which gives you another alternative. The best way to know about this is by doing man ssh.

    Good luck!

    Eli Bendersky : Sorry, but I noted that .ssh/environment didn't work for me. Any tips of what to write there? Also, I was under the impression that .bashrc is included in non-interactive shells. Otherwise, how is my PATH given correctly via ssh? (echo $PATH)?
  • You can try launching the command via a bash using the -l command so it acts as a login shell

    ssh user@server "bash -l -c 'which svnserve'"
    

    As noted in comments I left above, you'll need to escape all $ so variables get expanded on the server and not locally. E.g.:

    ssh user@server "bash -l -c 'echo \$PATH'"
    

    update:

    Regarding you question on why .ssh/environment does not take effect, I believe the default config for SSHd would be to ignore user environments. You need to specifically enable it in /etc/ssh/sshd_config (or similar) and add:

    PermitUserEnvironment yes
    

    update 2:

    If you do not have access to /etc/ssh/sshd_config, a possible (but not ideal) solution would be to use public-key authentication to launch svnserve on login.

    See http://svnbook.red-bean.com/en/1.4/svn.serverconfig.svnserve.html#svn.serverconfig.svnserve.sshtricks

    Note that this will affect your ability to log in normally via SSH. To do so, you need to bypass the public key authentication:

    svn -o PubkeyAuthentication=no user@server
    
    Eli Bendersky : Thanks, this makes sense. Unfortunately it still doesn't resolve my original problem which is running `svnserve` via SSH. for some reason ssh ignores my .ssh/environemnt file and every other attempt I try
    lsc : @Eli answer updated to address .ssh/environment issue
    lsc : Oopps.. just notices that @Dennis has already pointed you that way. Apologies for the repetition.
    Eli Bendersky : @lsc: Thanks. Unfortunately since this is a shared server I have no access to /etc/ssh/sshd_config. But from tests I ran it appears this variable indeed isn't set, because ssh ignores my environment file for sure
    From lsc
  • You can execute an env command:

    ssh servername "env PATH=$REMOTEPATH which svnserve"
    
    Eli Bendersky : after adding a semicolon before `which`, it says: `which: no svnserve in (/usr/bin:/bin)`
    Charles Stewart : @Eli: no semicolon - which is an argument to env
  • Set the variable BASH_ENV to '~/.bashrc'.

    ssh servername "BASH_ENV='~/.bashrc' which svnserve"
    

    From man bash:

    When bash is invoked as an interactive login shell, or as a non-inter‐ active shell with the --login option, it first reads and executes com‐ mands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable.

    and

    When an interactive shell that is not a login shell is started, bash reads and executes commands from /etc/bash.bashrc and ~/.bashrc, if these files exist.

    and

    When bash is started non-interactively, to run a shell script, for example, it looks for the variable BASH_ENV in the environment, expands its value if it appears there, and uses the expanded value as the name of a file to read and execute.

    From man ssh:

    Additionally, ssh reads ~/.ssh/environment, and adds lines of the format “VARNAME=value” to the environment if the file exists and users are allowed to change their environment. For more information, see the PermitUserEnvironment option in sshd_config(5).

    From man sshd_config:

    PermitUserEnvironment
    Specifies whether ~/.ssh/environment and environment= options in ~/.ssh/authorized_keys are processed by sshd(8). The default is “no”. Enabling environment processing may enable users to bypass access restrictions in some configurations using mechanisms such as LD_PRELOAD.

    Eli Bendersky : @Dennis, yes, this is as I would expect. However, in my case I clearly see that .bashrc is NOT being loaded. Moreover, ~/.ssh/environment is ignored. I can conclude that Bluehost (my server provider) configured it this way, which is very unfortunate. P.S. the line with BASH_ENV doesn't work for me
  • I have the same issue with HostMonster, due to a recent change they made. I found a workraound in an old email thread at http://svn.haxx.se/dev/archive-2007-02/0204.shtml:

    On your workstation:

    • edit ~/.subversion/config: locate [tunnels] and add the line ssh=~/svnssh
    • create ~/svnssh as in the link:

      #!/bin/sh
      /usr/bin/ssh $1 /<ur_bluhost_home_path>/sshsvnserve -t

    • chmod +x ~/svnssh

    On your bleuhost account:

    • create ~/sshsvnserve, same content as the link:

      #!/bin/sh
      /<ur_bluehost_home_path>/bin/svnserve $*

    • chmod +x ~/sshsvnserve

    That's it. The config [tunnels] change modifies the command run by svn when handling the svn+ssh namespace and use ur ~/svnssh script instead. The script invokes ssh and passes in the full path to sshsvnserve on ur bluehost account. And sshsvnserve redirects everything to the full path of svnserve, as u install it. Worked for me, no $PATH required.

  • Is there a way to do this using TortoiseSVN on windows :( ?

  • the answer by remus rasanu was good. There was just one caveat that I wanted to point out the ~/svnssh entry in the ~/.subversion/config file has to be an "absolute" path to work.

    I would vote for his answer but serverfault is not allowing a person with repuation of 1 to vote, or post comments. But apparently I can post another answer. go figure....

    From Q Boiler

0 comments:

Post a Comment