Execute comandos bash sobre SSH enquanto permanece no modo interativo depois

5

Provavelmente, é uma coisa estranha que eu gostaria de conseguir, mas: Eu gostaria de SSH para um host remoto e, em seguida, executar alguns comandos bash como "alias" automaticamente para usá-los depois em um modo interativo. O host remoto não permite o ambiente pessoal.

Isso é possível? "Esperaria" fazer isso? Ou existe alguma outra maneira de conseguir isso?
Basicamente eu gostaria de ter meu bashrc sem modificar nenhum arquivo no host remoto.

    
por thonixx 20.03.2014 / 23:15

2 respostas

3

Em outras palavras, você gostaria de ter um controle remoto ~/.bashrc , mas não é possível, nem mesmo com outro nome. O Bash não suporta a transmissão de comandos iniciais como argumentos de linha de comando ou através de variáveis de ambiente, eles precisam estar em um arquivo. No entanto, o arquivo não precisa estar no sistema de arquivos!

bash --rcfile /dev/fd/3 3< <(echo 'alias foo="echo hello"')
$ foo
hello

Muitos servidores SSH permitem a transmissão de variáveis de ambiente cujo nome está no formato LC_XXX , porque geralmente são usados para indicar localidades, que precisam ser transmitidas entre hosts e não têm implicação de segurança. Se o seu permite isso, você pode transmitir o conteúdo do seu .bashrc por meio de uma variável de ambiente e, em seguida, alimentar essa variável de ambiente em um descritor de arquivo.

LC_BASHRC=$(cat ~/.bashrc; exec 3<&-) \
ssh -t remote.example.com \
    'exec bash --rcfile /dev/fd/3 3< <(printf %s "$LC_BASHRC")'
  • O conteúdo do local ~/.bashrc é transmitido para o servidor na variável de ambiente LC_BASHRC .
  • exec 3<&- é anexado, para fechar o descritor de arquivo depois de ler o arquivo.
  • No lado remoto, o shell de login é substituído ( exec ) por uma nova instância de bash, que é instruída a ler seu arquivo de inicialização no descritor de arquivo 3.
  • 3< <(…) redireciona o descritor de arquivo 3 para uma substituição de comando: a saída de printf é alimentada para o processo pai por meio de um canal.

Se o seu shell de login no servidor for /bin/sh em vez de bash ou ksh, você não poderá usar a substituição do processo diretamente nesse shell, você precisará de uma camada extra:

LC_BASHRC=$(cat ~/.bashrc; exec 3<&-) \
ssh -t remote.example.com \
    'exec bash -c '\''exec bash --rcfile /dev/fd/3 \
                           3< <(printf %s "$LC_BASHRC")'\'

Você pode verificar quais variáveis de ambiente o servidor SSH aceita procurando por AcceptEnv directive in its [ configuration ](http://www.openbsd.org/cgi-bin/man.cgi?query=sshd_config&sektion=5) ( / etc / sshd_config or / etc / ssh / sshd_config ').

Em vez de usar a substituição de comandos 3< <(…) , você pode usar uma string here. Isso cria um arquivo temporário (em $TMPDIR ou /tmp ) em vez de um canal, portanto, isso só funcionará se você não se importar em criar um arquivo temporário.

LC_BASHRC=$(cat ~/.bashrc; exec 3<&-) \
ssh -t remote.example.com \
    'exec bash --rcfile /dev/fd/3 3<<<"$LC_BASHRC"'

Se você não se importar em criar um arquivo temporário, há uma técnica muito mais simples:

  1. Copie seu .bashrc para um arquivo remoto temporário. Você precisa fazer isso apenas uma vez até que o arquivo temporário seja excluído.
  2. Inicie um shell interativo com --rcfile apontando para o arquivo temporário.
remote_bashrc=$(ssh remote.example.com 'bashrc=$(mktemp) && cat >>"$bashrc" && echo "$bashrc"' <~/.bashrc)
ssh -t remote.example.com "exec bash --rcfile '$remote_bashrc'"

Se a implementação do SSH não for muito antiga, você poderá use uma conexão mestre para acelerar o lançamento de vários comandos SSH para o mesmo host.

Se você estiver efetuando login com uma chave e tiver controle sobre o arquivo de chave pública, poderá automatizar mais. Em ~/.ssh/authorized_keys , uma chave pode ter uma diretiva command=… que permite executar um comando em vez do que foi especificado na linha de comando. Consulte Como posso definir o ambiente variáveis para um processo de rsync remoto? para mais explicações.

command="if [ -n \"$SSH_ORIGINAL_COMMAND\" ]; then
           eval \"$SSH_ORIGINAL_COMMAND\";
         else exec bash -c 'bash 3<<<\"$LC_BASHRC\"'; fi" ssh-rsa …

ou

command="if [ -n \"$SSH_ORIGINAL_COMMAND\" ]; then
           eval \"$SSH_ORIGINAL_COMMAND\";
         else exec bash -c 'bash 3<<<\"alias foo=bar; …\"'; fi" ssh-rsa …

(Isso precisa ser tudo em uma linha, eu só coloco quebras de linha para legibilidade.)

    
por 21.03.2014 / 03:04
1

Você pode usar SendEnv no seu .ssh/config . Na página man do ssh_config:

SendEnv Specifies what variables from the local environ(7) should be sent to the server. Note that environment passing is only supported for protocol 2. The server must also support it, and the server must be configured to accept these environment variables. Refer to AcceptEnv in sshd_config(5) for how to configure the server. Variables are specified by name, which may contain wildcard characters. Multiple environment variables may be separated by whitespace or spread across multiple SendEnv directives. The default is not to send any environment variables.

    
por 20.03.2014 / 23:24

Tags