arquivos de inicialização sh sobre ssh

10

Eu tenho alguns comandos importantes que preciso executar antes que qualquer sh shell seja iniciado. Isso é necessário para a passagem de comandos SSH no comando SSH ( ssh host somecommand) e outros programas que executam comandos.

No meu .profileeu tenho isso:

ihammerhands@wreckcreations:~> cat .profile
#specific environment and startup programs
export PS1="\u@wreckcreations:\w> "
export PYTHONPATH=~/python/lib/python2.4/site-packages
export PATH=$PATH:~/bin:~/python/bin

No entanto, isso falha:

W:\programming\wreckcreations-site\test-hg>ssh name@host echo $PATH
Enter passphrase for key '/home/Owner/.ssh/id_rsa':
/usr/local/bin:/bin:/usr/bin

Observe as opções PATH ausentes

Qual é o nome apropriado para o perfil sh? Nota: Eu não tenho acesso root e não quero que isso seja aplicado a outros usuários. Há outra maneira de fazer isso?


EDIT: Parece /bin/shlinks para bash, o que não é surpreendente. O que é surpreendente é que meu perfil ainda é ignorado. Alguma sugestão?

TheLQ
fonte
1
Não tenho vontade de repetir o que há na página de manual, portanto, basta olhar na página de manual do bash na seção 'INVOCATION'. Está perto do topo e descreve tudo o que você precisa saber.
Camh
Você pode tentar usar ssh name@host -t echo $PATH.
Gert
A saída @Gert é a mesma #
TheLQ
@camh Você acha que eu faria essa pergunta se ainda não tivesse verificado as páginas de manual? Eu li-lhes muitas vezes + outros lugares, mas nunca poderia encontrar uma resposta para esta questão específica, desde que eu não tenho certeza de que comandos fase ssh e comandos de outro programa são executadas em
TheLQ
1
@ TheLQ: Eu não te conheço, então não sei se você verificaria a página de manual. Tudo que eu sabia é que as respostas estavam ali, então, em vez de repetir palavra por palavra, apontei para você. Um ponteiro mais específico é procurar shells não interativos, já que esse é o seu cenário ssh. Se algo na página do manual não estiver claro, talvez você possa fazer uma pergunta mais específica.
Camh

Respostas:

8

Parece interessante notar que o comando que você mencionou na sua pergunta

ssh name@host echo $PATH

praticamente nunca será útil. A substituição da variável por $ PATH é feita pelo shell local e passada para o ssh, que executa eco no sistema remoto para imprimir o conteúdo da variável do caminho, à medida que se expandia no sistema local. Aqui está um exemplo de mim fazendo algo semelhante entre o meu Mac e uma máquina Linux na minha rede:

LibMBP:~ will$ echo $PATH
/opt/local/bin:/opt/local/sbin:/Users/will/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/texbin:/usr/X11/bin
LibMBP:~ will$ ssh warren echo $PATH
will@warren's password: 
/opt/local/bin:/opt/local/sbin:/Users/will/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/texbin:/usr/X11/bin
LibMBP:~ will$ ssh warren 'echo $PATH'
will@warren's password: 
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
LibMBP:~ will$ 

Observe como eu precisava usar aspas para impedir que meu shell local expanda a variável.

wrosecrans
fonte
No Windows Cygwin land, aspas simples não fazem nada no Cygwin ou no prompt de comando. Estranhamente, aspas duplas fazem o PATH se expandir completamente para minha máquina local em Cygwin. Portanto, o que o ssh estava me dando não era o meu caminho, era o servidor #
TheLQ
@TheLQ As aspas simples são necessárias em um prompt unix (incluindo Cygwin), mas você não precisa de aspas em um prompt de cmd.
Gilles 'SO- stop be evil'
12

~/.profileé executado apenas por shells de login. O programa que chama o shell decide se o shell será um shell de logon (colocando a -como o primeiro caractere do argumento zeroth na invocação do shell). Normalmente não é executado quando você efetua login para executar um comando específico.

O OpenSSH, em particular, chama um shell de login apenas se você não especificar um comando. Portanto, se você especificar um comando, ~/.profilenão será lido.

O OpenSSH permite definir variáveis ​​de ambiente no lado do servidor. Isso deve estar ativado na configuração do servidor , com a PermitUserEnvironmentdiretiva. As variáveis podem ser definidas no arquivo ~/.ssh/environment. Supondo que você use autenticação de chave pública, também é possível definir variáveis ​​por chave em ~/.ssh/authorized_keys: add environment="FOO=bar"no início da linha relevante.

O Ssh também suporta o envio de variáveis ​​de ambiente. No OpenSSH, use a SendEnvdiretiva em ~/.ssh/config. No entanto, a variável de ambiente específica deve ser ativada com uma AcceptEnvdiretiva na configuração do servidor; portanto, isso pode não funcionar para você.

Uma coisa que eu acho que sempre funciona (por incrível que pareça), desde que você esteja usando autenticação de chave pública é (ab) usar a command=opção no authorized_keysarquivo . Uma chave com uma commandopção é boa apenas para executar o comando especificado; mas o comando no authorized_keysarquivo é executado com a variável de ambiente SSH_ORIGINAL_COMMANDdefinida para o comando especificado pelo usuário. Essa variável está vazia se o usuário não especificou um comando e, portanto, esperava um shell interativo. Portanto, você pode usar algo parecido com isso ~/.ssh/authorized_keys(é claro, isso não se aplicará se você não usar essa chave para autenticar):

command=". ~/.profile; if [ -n \"$SSH_ORIGINAL_COMMAND\" ]; then eval \"$SSH_ORIGINAL_COMMAND\"; else exec \"$SHELL\"; fi" ssh-rsa 

Outra possibilidade é escrever scripts de wrapper no servidor. Algo como o seguinte em ~/bin/ssh-wrapper:

#!/bin/sh
. ~/.profile
exec "${0##*/}" "$@"

Em seguida, faça links simbólicos para esse script chamado rsync, unisonetc. Passe --rsync-path='bin/rsync'na rsynclinha de comando e assim por diante para outros programas. Como alternativa, alguns comandos permitem especificar um snippet de shell inteiro para executar remotamente, o que permite tornar o comando independente: por exemplo, com o rsync, você pode usar --rsync-path='. ~/.profile; rsync'.

Existe outro caminho que depende do seu shell de login ser bash ou zsh. O Bash sempre lê ~/.bashrcquando é chamado por rshd ou sshd, mesmo que não seja interativo (mas não se for chamado como sh). Zsh sempre lê ~/.zshenv.

## ~/.bashrc
if [[ $- != *i* ]]; then
  # Either .bashrc was sourced explicitly, or this is an rsh/ssh session.
  . ~/.profile
fi

## ~/.zshenv
if [[ $(ps -p $PPID -o comm=) = [rs]shd && $- != *l* ]]; then
  # Not a login shell, but this is an rsh/ssh session
  . ~/.profile
fi
Gilles 'SO- parar de ser mau'
fonte
E os comandos que outros comandos executam? Nesse caso, seriam ganchos Mercurial. Mercurial precisa estar no caminho para o gancho pensar em trabalhar #
TheLQ
Use qualquer uma das técnicas indicadas para que seu perfil seja executado em comandos ssh não interativos. Um deles ( command=in authorized_keys) funciona de forma transparente. Outros requerem um shell ou opções específicas na configuração do servidor ssh. O equivalente mercurial de --rsync-pathé --remotecmd.
Gilles 'SO- stop be evil'
Pode ser útil para alguns para incluir o mesmo cheio command=de comando como no seu post superuser.com/a/207262/137762
mforbes
1

Normalmente, após o login, o bash lê comandos de:

~ / .bash_profile
~ / .bashrc

Na página do manual do bash:

~ / .bash_profile
O arquivo de inicialização pessoal, executado para shells de login

~ / .bashrc
O arquivo de inicialização individual por shell interativo

Alexander Pogrebnyak
fonte
0

Estou sem tempo para testar isso, mas procurando nas páginas de manual que encontrei:

man bash: quando o bash é iniciado de maneira não interativa, para executar um script de shell, por exemplo, ele procura a variável BASH_ENV no ambiente, expande seu valor se aparecer lá e usa o valor expandido como o nome de um arquivo para leia e execute. O Bash se comporta como se o seguinte comando fosse executado: if [-n "$ BASH_ENV"]; então . "$ BASH_ENV"; fi mas o valor da variável PATH não é usado para procurar o nome do arquivo.

man ssh: ~ / .ssh / environment Contém definições adicionais para variáveis ​​de ambiente; veja AMBIENTE, acima.

A combinação sugere como você pode fazer com que o ssh execute seu .profile

Infelizmente, meu servidor tem PermUserEnvironment com o valor padrão de não, o que faz com que isso não funcione para mim (e, como eu disse, não tenho tempo para brincar mais).

kasterma
fonte
Mesmo que eu pudesse fazer com que o SSH funcionasse declarando explicitamente algumas variáveis ​​de ambiente no ambiente, ele ainda não ajudaria a corrigir a execução do meu perfil quando outros programas chamam comandos
TheLQ
No seu exemplo, tudo o que você está fazendo é definir variáveis ​​de ambiente, o que mais você quer fazer?
kasterma
0

(removido ... só pode ter um hiperlink como novo usuário ~)

Atualizar

Desculpe, não vi que se trata de uma sessão não interativa, à qual o link acima não se aplica.

Quando o Bash é iniciado no modo de compatibilidade SH, ele tenta imitar o comportamento de inicialização das versões históricas do sh o mais próximo possível, além de estar em conformidade com o padrão POSIX®. Os arquivos de perfil lidos são / etc / profile e ~ / .profile, se for um shell de login.

Se não for um shell de logon, a variável de ambiente ENV é avaliada e o nome do arquivo resultante é considerado o nome do arquivo de inicialização.

Após a leitura dos arquivos de inicialização, o Bash entra no modo de compatibilidade POSIX (r) (para execução, não para iniciar!).

O Bash inicia no modo de compatibilidade sh quando:

  • o nome do arquivo base em argv [0] é sh (:!: Atenção, queridos usuários super inteligentes de Linux ... / bin / sh podem estar vinculados a / bin / bash, mas isso não significa que ele age como / bin / bash :! :)

Portanto, a questão é: por que não o executa, mesmo que seu shell seja iniciado assim?

Fonte


fonte
Eu olhei, mas como disse a camh, não sei em quais comandos do estágio ssh e outros comandos do programa são executados. Já li as páginas de manual e outros guias muitas vezes
TheLQ