Como posso definir variáveis ​​de ambiente para um processo rsync remoto?

12

Quando uso o rsync para copiar arquivos de um computador para outro, um processo rsync é iniciado nas duas extremidades. No entanto, no lado remoto, aparentemente, os arquivos de inicialização do shell não são lidos, portanto, não consigo configurar variáveis ​​de ambiente para o processo rsync remoto. Infelizmente, há um servidor no qual preciso fazer o rsync no qual o rsync requer uma variável de ambiente para funcionar. Como não sou administrador no servidor, não posso alterar a configuração global. O que posso fazer para definir variáveis ​​de ambiente para um processo remoto de rsync?

Ryan C. Thompson
fonte
Como você inicia o processo rsync no servidor? Você poderia disparar um script via ssh?
Kraftan
Quando você faz isso rsync localfilename remotehost:remotefilename, um processo rsync é iniciado no servidor. Eu não sei exatamente como, mas não lê arquivos de inicialização do shell.
Ryan C. Thompson

Respostas:

20

~/.profilenormalmente não é lido quando você executa ssh somecommand, em oposição a uma sessão ssh interativa (ou outro método de login no qual você inicia uma sessão interativa).

O Ssh 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ê.

OpenSSH também permite definir variáveis de ambiente no lado do servidor. Novamente, isso deve estar ativado na configuração do servidor, aqui 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.

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 (vazio para sessões interativas). Portanto, você pode usar algo assim em ~/.ssh/authorized_keys(é claro, isso não se aplicará se você não usar essa chave para autenticar):

command="export LD_LIBRARY_PATH=\"$HOME\"/lib;
         if [ -n \"$SSH_ORIGINAL_COMMAND\" ]; then
           eval \"$SSH_ORIGINAL_COMMAND\";
         else exec \"$SHELL\"; fi" ssh-rsa …

Observe que eu coloquei as quebras de linha acima para legibilidade, mas isso realmente precisa estar tudo em uma linha.

Outra possibilidade é escrever um script de wrapper ~/bin/rsync-wrapperno servidor, algo como

#!/bin/sh
. ~/.profile
exec rsync "$@"

Em seguida, passe --rsync-path='bin/rsync-wrapper'na rsynclinha de comando. O argumento to --rsync-pathé expandido por um shell; portanto, se você preferir, pode tornar a linha de comando do rsync independente, passando algo como --rsync-path='. ~/.profile; rsync'.

Existe outro caminho que depende do seu shell de login ser bash ou zsh. O Bash sempre lê ~/.bashrcquando é invocado 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
Bem, isso resume tudo. Eu esperava que houvesse uma maneira melhor do que usar um script de wrapper.
Ryan C. Thompson
Mas espere um pouco. Se meus arquivos init do shell não estão sendo lidos, como ele pode encontrar o binário rsync no servidor? Eu instalei em ~ / usr, um local não padrão que tenho que adicionar aos meus $PATHscripts shell init.
Ryan C. Thompson
@ Ryan: Na verdade, eu tinha esquecido o método mais direto (veja minha edição), mas também exige que uma diretiva seja ativada na configuração do servidor. Se você encontrou uma maneira de levar isso PATHem consideração, deve poder definir qualquer outra variável lá. (Se isso não funcionar, tente adicionar o maior número possível de rastreamentos, começando set -xem qualquer script de shell; substitua o rsyncbinário por um script de wrapper que despeja o ambiente em um arquivo e depois chama o binário real.)
SO de Gilles - pare de ser mau '
Que tal ~/.ssh/rc?
Ryan C. Thompson
@ Ryan: ~/.ssh/rcé executado por um processo de shell separado. Eu acho que sua melhor aposta é um script de wrapper ou --rsync-path='. ~/.profile; rsync'. Ou recompilar rsynccom um rpath adequado conforme sua outra pergunta.
Gilles 'SO- stop be evil'