Por que alguns comandos não carregam o ambiente do usuário quando executados com o ssh? (enquanto outros fazem)

2

Em uma máquina de destino (OS X El Capitan), tenho brew in /usr/local/bin . Quando tento obter o caminho da bebida, não obtenho resultado:

# ssh [email protected] -p 2222 which brew
#

Solução de problemas:

  1. brew está em /usr/local/bin/ e é executado corretamente por meio de ssh :

    # ssh [email protected] -p 2222 ls -l /usr/local/bin/brew
    -rwxr-xr-x  1 vagrant  admin  656 Mar 20 10:05 /usr/local/bin/brew
    # ssh [email protected] -p 2222 /usr/local/bin/brew --version
    Homebrew 0.9.5 (git revision 3a41; last commit 2016-03-20)
    
  2. Existe /usr/local/bin no caminho:

    # ssh [email protected] -p 2222 echo $PATH
    /usr/local/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/opt/local/bin:/opt/local/sbin
    
  3. which em si não parece ter um problema:

    # ssh [email protected] -p 2222 which bash
    /bin/bash
    
  4. Além disso, quando conectado de forma interativa à máquina, recebo o resultado pretendido:

    # ssh [email protected] -p 2222
    Last login: Sun Mar 20 12:02:55 2016 from 10.0.2.2
    osx-pf:~ vagrant$ which brew
    /usr/local/bin/brew
    
  5. Finalmente which brew funciona quando na expressão de substituição do comando:

    # ssh [email protected] -p 2222 echo $(which brew)
    /usr/local/bin/brew
    
  6. Chamar echo antes de which brew faz com que ele forneça o resultado correto:

    # ssh [email protected] -p 2222 echo test ; which brew
    test
    /usr/local/bin/brew
    
  7. Chamar o shell explicitamente para executar which brew não altera a situação:

    # ssh [email protected] -p 2222 /bin/sh -c "which\ brew"
    # ssh [email protected] -p 2222 /bin/sh -c "which\ which"
    /usr/bin/which
    

    No entanto, com a chamada explícita para /bin/sh , o "truque" de (6) não funciona mais:

    # ssh [email protected] -p 2222 /bin/sh -c "echo\ test\ \;\ which\ brew"
    test
    #
    

Por que executar which brew diretamente como argumento do comando ssh falha?

Por que echo qual comando externo em /bin/echo vê o PATH correto, enquanto which não? E por que executar dois comandos em seqüência faz com que o segundo use o ambiente do primeiro?

É possível assegurar que o ambiente seja carregado sem se referir a soluções documentadas (eu presumo) como em (6)?

    
por techraf 21.03.2016 / 03:05

2 respostas

2
ssh [email protected] -p 2222 echo $PATH

O PATH do seu sistema local será impresso aqui. Você deve citar a variável para evitar que ela seja expandida pelo shell local:

ssh [email protected] -p 2222 'echo $PATH'

O mesmo se aplica a:

ssh [email protected] -p 2222 echo $(which brew)

Quanto a:

ssh [email protected] -p 2222 echo test ; which brew

which brew é executado depois que o comando SSH termina, pelo seu shell local. É por isso que isso não funcionou:

ssh [email protected] -p 2222 /bin/sh -c "echo\ test\ \;\ which\ brew"

Nota lateral: você não precisa fazer tudo o que escapar.

O problema aqui é que você está adicionando brew ao seu PATH em .profile (ou .bash_profile ou algum arquivo semelhante), que é executado quando um login shell começou. O SSH inicia um shell de login somente quando ele é executado de forma interativa, não quando é solicitado que ele execute um comando. De man ssh :

 If command is specified, it is executed on the remote host instead of a login shell

Você pode tentar:

ssh [email protected] -p 2222 bash -lc brew
    
por 21.03.2016 / 06:50
1

Quando você executa comandos diretamente do ssh, você não está "efetuando login", você está apenas executando um comando.

Alguns scripts de shell são executados quando você "efetua login" - ~ / .bashrc, / etc / profile etc.

which usa variáveis de ambiente - especificamente $PATH - que podem ser definidas em um desses scripts. Sem $PATH , which não saberá onde procurar.

Além disso, ssh [email protected] -p 2222 echo $(which brew) não dará o que você espera - $(which brew) é interpretado pelo shell, antes mesmo de chegar ao ssh - comparar: ssh [email protected] -p 2222 echo $(hostname) com ssh [email protected] -p 2222 echo '$(hostname)' (anote aspas simples ao redor da expansão do shell) . O primeiro obterá o nome do host LOCAL e o enviará ao host remoto para que ele seja ecoado. O segundo será enviar o $(hostname) (literalmente) para o shell remoto, para ser expandido lá.

UPDATE: Eu estava um pouco errado sobre isso.

Quando você executa um comando sobre ssh, o ssh funciona se um shell é necessário (por exemplo, trabalhando fora de variáveis, etc. Se não for necessário, o programa binário é executado imediatamente. Caso contrário, bash é executado, que pode configurar variáveis de ambiente etc.

É por isso que (no seu comentário) brew --version falha - você não menciona um caminho. Quando você echo...; brew --version , o ponto-e-vírgula ; é um caractere de shell especial; ssh lida com isso para você, executando bash para você.

    
por 21.03.2016 / 04:10