Ssh, execute um comando no logon e mantenha-se conectado?

29

Tentei isso com expect, mas não funcionou: fechou a conexão no final.

Podemos executar um script via ssh que fará logon em máquinas remotas, execute um comando e não desconecte?

Então, ssh em uma máquina, faça o cd para esse e aquele diretório e, em seguida, execute um comando e mantenha-se conectado.

-Jonathan

(espero que eu usei)

#!/usr/bin/expect -f
set password [lrange $argv 0 0]
spawn ssh root@marlboro "cd /tmp; ls -altr | tail"
expect "?assword:*"
send -- "$password\r"
send -- "\r"
interact
Jonathan
fonte
9
Sou eu ou você está "automatizando" a autenticação por senha dessa maneira, em vez de usar pubkeys ou outro método sensato?
grawity

Respostas:

25

Adicionar um ; /bin/bashao final da sua linha de comando no lado remoto? Isso é:

spawn ssh -t root@marlboro "cd /tmp; ls -altr | tail; /bin/bash -i"

Melhor ainda, altere o .bashrc do root para algo como:

PROMPT_COMMAND="cd /tmp && ls -altr | tail ; unset PROMPT_COMMAND"

:)

Bill Weiss
fonte
2
Você pode querer adicionar -ia essa festança.
Teddy
Sim, eu suponho :) #
Bill Weiss
Quando faço isso, a conclusão da guia é interrompida no novo shell (mesmo com "-i") - alguma idéia de por que / como corrigir?
Coderer 28/05
1
Testei minha nova resposta aqui, funciona muito bem. Um pouco áspero, mas funciona.
Bill Weiss
7
Tente ssh -talocar um pty.
Pausado até novo aviso.
4

Se você concorda em fazer isso no Python, o pexpect tem um exemplo que faz quase exatamente o que você está pedindo:

import pexpect
child = pexpect.spawn ('ftp ftp.openbsd.org')
child.expect ('Name .*: ')
child.sendline ('anonymous')
child.expect ('Password:')
child.sendline ('[email protected]')
child.expect ('ftp> ')
child.sendline ('ls /pub/OpenBSD/')
child.expect ('ftp> ')
print child.before   # Print the result of the ls command.
child.interact()     # Give control of the child to the user.

Para fazer isso com ssh em vez de ftp, você deseja um código semelhante ao seguinte (os arquivos de exemplo no pexpect têm muito mais detalhes e informações, mas aqui estão os princípios básicos):

import pexpect
child = pexpect.spawn ('ssh root@marlboro')
child.expect ('Password:')
child.sendline ('password')
child.expect ('prompt# ')
child.sendline ('cd /tmp')
child.expect ('prompt# ')
child.sendline ('ls -altr | tail')
child.expect ('prompt# ')
print child.before, child.after   # Print the result of the ls command.
child.interact()     # Give control of the child to the user.

Não me interpretem mal, eu AMO esperar (especialmente a autoexpect), mas o python é muuuuito mais fácil para eu grunhir.

Jed Daniels
fonte
Eu também estou em transição de esperar para esperar. python agora é muito mais onipresente.
JM Becker
4

A maneira provavelmente mais fácil e limpa de ssh em um servidor, gerar um shell interativo e executar comandos dentro desse shell é criar um arquivo rc personalizado para o bash.

No seu arquivo bashrc personalizado no servidor, primeiro crie o arquivo padrão e depois adicione seus comandos personalizados, por exemplo

~ / .bashrc_custom:

. ~/.bashrc
cd dir/
workon virtualenvproject

Você pode iniciar sua sessão SSH assim:

$ ssh -t server "/bin/bash --rcfile ~/.bashrc_custom -i"

A -topção força uma alocação pseudo-tty, para que coisas como conclusão de tabulação funcionem.

A --rcfileopção especifica qual arquivo rc carregar, em vez do padrão. Importante: você deve colocar "argumentos de traço duplo" na linha de comando antes das opções de caractere único para ser reconhecido.

O -iargumento para / bin / bash existe para chamar um shell interativo.

Danilo Bargen
fonte
na verdade não. O que fazer se eu quiser executar comandos diferentes para cada conexão?
Eugen Konkov #
1

Se alguém quiser informações sobre o que está acontecendo em segundo plano, dê uma olhada no manual do sshd:

Quando um usuário efetua login com êxito, o sshd faz o seguinte:

  1. Se o logon estiver em um tty e nenhum comando tiver sido especificado, imprime a última hora do logon e / etc / motd (a menos que seja impedido no arquivo de configuração ou por ~ / .hushlogin; consulte a seção FILES).
  2. Se o login estiver em um tty, registra o tempo de login.
  3. Verifica / etc / nologin e / var / run / nologin; se existir, ele imprime o conteúdo e sai (a menos que seja root).
  4. Alterações para executar com privilégios normais de usuário.
  5. Configura o ambiente básico.
  6. Lê o arquivo ~ / .ssh / environment, se existir, e os usuários podem alterar seu ambiente. Veja a opção PermitUserEnvironment em sshd_config (5).
  7. Alterações no diretório inicial do usuário.
  8. Se existir ~ / .ssh / rc, execute-o; caso contrário, se o / etc / ssh / sshrc existir, execute-o; caso contrário, executa o xauth (1). Os arquivos `` rc '' recebem o protocolo de autenticação X11 e o cookie na entrada padrão. Veja SSHRC, abaixo.
  9. Executa o shell ou comando do usuário .

https://www.freebsd.org/cgi/man.cgi?sshd(8)#LOGIN_PROCESS

Gerry
fonte
0

Geralmente, você deve evitar o uso do ssh dessa maneira, pois isso anula seu objetivo.
Faça um

ssh-add -l | grep "file_of_your_rsa_priv_key_here"

para ver se sua chave está listada no pool de sessões ativas do ssh ou adicione-a você mesmo (com ssh-add).

Kounavi
fonte