Por que o $ PATH de um comando remoto ssh difere do de um shell interativo?

20

Eu tenho um usuário que não fez modificações no $ PATH em nenhum arquivo de ponto: é exatamente a configuração padrão do sistema. Em um shell de login:

$ ssh example.com
user@example.com:~$ cat /tmp/hello.hs
#!/bin/bash

echo "$SHELL"
echo "$PATH"

user@example.com:~$ /tmp/hello.hs
/bin/bash
/usr/local/bin:/usr/bin:/bin

Exatamente como especificado em /etc/profile. Acho isso inesperado:

$ ssh example.com '/tmp/hello.sh'
/bin/bash       
/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games

Como eu disse, não há modificação de $ PATH ~/.bashrcnem em /etc/bash.bashrc. Também ~/.ssh/environmentnão. O ssh(1)declara que a variável de ambiente PATHé

Defina como PATH padrão, conforme especificado ao compilar ssh.

mas esta discussão de StackOverflow e esta lista de discussão artigo sugerem que eu deveria ser capaz de influenciar o $ PATH para um determinado comando simplesmente modificando / etc / profile, um dos arquivos do shell de inicialização, etc.

Oque esta acontecendo aqui?

troutwine
fonte

Respostas:

16

Na ssh(1)página do manual: "Se o comando for especificado, ele será executado no host remoto em vez de no shell de login".

Portanto, resumindo, quando você efetua login no bash da máquina é iniciado como um shell de logon e carrega os arquivos apropriados, quando você se conecta remotamente e emite um comando, ele é executado no lugar do bash, o que significa que esses arquivos NÃO são carregados. Você pode contornar isso usando su -l -cou similar na parte de comando do ssh.

Em alguns casos, vi -targumentos para o ssh funcionar (alocar tty) também.

Edit 1 :
Eu acho que as informações PATH encontradas, que o caminho padrão (a menos que o sobrescrevamos) é o compilado no sshd. Certifiquei-me de que meu / etc / profile, / etc / bash *, arquivos de pontos locais, etc. não continham nenhuma informação PATH, depois efetuei logon e ainda tinha um PATH. Eu procurei por este no sshd e encontrei lá. Então é assim que a página de manual diz:

ahnberg@remote$ strings /usr/sbin/sshd | grep -i x11 | grep bin
/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games

Depois, adiciono PATH=$PATH:/my/testao topo do meu .bashrcarquivo no controle remoto e verifico novamente:

ahnberg@local$ ssh ahnberg@remote "env | grep PATH"
PATH=/usr/local/bin:/usr/bin:/bin:/usr/bin/X11:/usr/games:/my/test

Para que eu possa absolutamente influenciá-lo, o PATH padrão é o compilado no sshd. :)

Mattias Ahnberg
fonte
Hmm, essa frase "executada no host remoto" significa muito mais do que diz, eu acho. A parte mais interessante, que eu perdi anteriormente, vem na seção 'AMBIENTE' da mesma página de manual: "PATH Defina o PATH padrão, conforme especificado ao compilar o ssh." Exceto que isso sugere que eu deveria poder influenciar o CAMINHO de um comando.
troutwine
Bem, o ponto é que não é um shell de logon, portanto, ele não executa / origem / inclui os arquivos de inicialização da mesma maneira que para um shell de logon, daí minhas sugestões para experimentar. Colocar as coisas .bashrcpode funcionar também, mas no geral eu contornaria se PATH for importante. Ou por que não apenas especificar nomes de caminho completos se você precisar da maneira 'command' de executar o ssh? :)
Mattias Ahnberg
Eu editei minha postagem um pouco. Agora, há um shell de login, um shell que não é de login e suas variantes interativas / não interativas. Os comandos SSH são chamados no shell do usuário no formulário não interativo de não logon. A bash(1)INVOCATION sugere que nenhum arquivo de inicialização seja lido dessa maneira, mas não consigo encontrar documentação sobre como o ssh está chamando o shell. Isso parece contrário às fontes vinculadas acima, a menos que outras pessoas tenham o arquivo de inicialização / etc / ssh / sshrc que eu não possuo. (Existem soluções alternativas, é claro, mas o ponto é entender exatamente como Debian SSHD lida com caminhos por padrão.)
troutwine
Se eu modificar PATH em /etc/profileminhas atualizações de caminho da caixa remota para mim, será ssh user@remotebox 'env'exibido o PATH atualizado. A mesma coisa acontece se eu adicionar export PATH=$PATH:/my/testpatha .bashrc (mas no meu caso no topo do arquivo antes de cheques para shells interativos ( -z "$PS1").
Mattias Ahnberg
Atualizado com meus testes / descobertas.
Mattias Ahnberg
3

Consegui que o ssh execute comandos usando o caminho remoto executando:

ssh dist@d6 "bash --login -c 'env'"

Aqui, env pode ser substituído por qualquer comando que você desejar.

Eu tenho chaves autorizadas, portanto não precisava de uma senha para executar o comando ou ssh.

Ian
fonte
3

Eu vim com uma solução diferente para corrigir o problema. Minha preferência pessoal é criar novos arquivos de configuração em vez de alterar os existentes. Dessa forma, posso facilitar a alteração das alterações da configuração padrão.

Aqui estão os conteúdos de /etc/profile.d/ssh_login.sh:

#!/bin/sh
if [ "$SSH_CONNECTION" ]; then
    echo "User '$USER' logged in from '${SSH_CONNECTION%% *}'"
    . /etc/environment
fi

Usando dropbearno lugar de openssh-server(isso também deve funcionar com o openssh), a variável SSH_CONNECTION é definida automaticamente quando eu faço logon remotamente. Criei uma nova configuração de perfil de shell para detectar logins SSH, exibir algumas informações na tela e, mais importante, carregar as configurações do ambiente global /etc/environmentpara substituir os valores compilados. Observe que isso afeta apenas shells SSH interativos, não a execução de comandos remotos.

Como alternativa , se você usar o openssh e sempre desejar carregar o ambiente global, independentemente de ser um shell interativo, poderá colocar um link simbólico da ~/.ssh/seguinte maneira:

ln -s /etc/environment ~/.ssh/environment

Então você precisa habilitar a PermitUserEnvironmentopção /etc/sshd/sshd_config. Entretanto, faça isso apenas para usuários confiáveis, pois isso poderá permitir que eles ignorem as restrições de acesso em algumas configurações usando mecanismos como LD_PRELOAD. Consulte man sshd_configpara obter mais informações, especificamente como usar Matchblocos para restringir opções a usuários / grupos específicos.

tachylatus
fonte
0

Se você deseja que o caminho do perfil seja carregado, tente:

#!/bin/bash -i

no topo do script. Dessa forma, o shell está no modo interativo ao executar o script.

Quando o bash é chamado como um shell de login interativo ou como um shell não interativo com a opção --login, ele primeiro lê e executa comandos do arquivo / etc / profile, se esse arquivo existir. Depois de ler esse arquivo, ele procura ~ / .bash_profile, ~ / .bash_login e ~ / .profile, nessa ordem, e lê e executa comandos do primeiro que existe e é legível. A opção --noprofile pode ser usada quando o shell é iniciado para inibir esse comportamento.

http://linux.die.net/man/1/bash

Adam Brand
fonte