Com o ssh, como você pode executar um comando na máquina remota sem sair?

29

Normalmente, se você passar um comando para o ssh dessa maneira

ssh [email protected] 'some-command.sh'

Você obtém uma sessão não interativa e o ssh sai assim que o comando (ou script, ou o que seja) é executado. Como posso obter uma sessão interativa e, ainda assim, executar um comando que especifiquei na minha máquina local. Por exemplo, eu gostaria de poder abrir a tela e reiniciar uma sessão de tela específica:

ssh [email protected] 'screen -r 12345'

mas isso não é permitido, retornando o erro "Deve estar conectado a um terminal". que eu presumo que significa essencialmente "deve chamar esse comando de um shell interativo".

Como outro exemplo, eu uso uma tonelada de máquinas no trabalho que muitas vezes exigem que eu use uma conta compartilhada para ter direitos de fazer certas coisas (sim, eu sei: má ideia, mas não me culpe, não configurei coisas que caminho), e eles geralmente têm o ksh como shell padrão. Gostaria de fazer login, alternar para o bash (ou zsh) e obter o .bash_profile da minha conta (ou .zshrc). Seria fácil se eu pudesse estabelecer uma sessão ssh interativa e passar um comando para a máquina remota para executar no logon.

Eu tenho uma solução muito inteligente (e não testada) em mente que postarei, mas espero que alguém saiba uma maneira melhor.

ATUALIZAÇÃO: para aqueles que não perceberam isso, não estou planejando fazer tudo isso manualmente, portanto, me dizer para abrir uma sessão interativa e depois fazê-lo manualmente não resolve nada.

2ª ATUALIZAÇÃO: Para tentar novamente esclarecer: Estou tentando executar comandos (arbitrários) no servidor (especificado programaticamente no cliente), mas depois tenho uma sessão interativa aberta que é afetada por qualquer coisa executada por esses comandos programáticos.

iconoclasta
fonte
echo "command" | ssh user@remote_host
laggingreflex
2
Você perdeu a parte "sem sair" da pergunta? Tenho certeza de que isso será encerrado após a conclusão do comando.
Iconoclast

Respostas:

26

Você pode tentar o seguinte comando para iniciar o bash e criar seu próprio perfil quando você ssh:

ssh  -t hostname "bash --rcfile ~user/.bashrc"
dogbane
fonte
4
+1. A -topção também resolve o problema do interlocutor screen.
Patches
3
Isso pode ser usado com comandos arbitrários, sem fechar a conexão? Se eu tentar ssh -t www.dev "echo 'hi there'", a conexão será fechada imediatamente após a execução do comando.
iconoclast
11

Com base na resposta do dogbane, uma solução completa se parece com:

ssh -t user@server 'cd /a/great/place; bash'

Aqui eu uso -tpara forçar a alocação de um pseudo-terminal, necessário para um shell interativo. Em seguida, executo dois comandos no servidor: primeiro o que eu queria fazer antes de abrir o shell interativo (no meu caso, alterar o diretório para uma pasta específica) e depois o próprio shell interativo. o bash vê que possui um pseudo-terminal e responde de maneira interativa.

As aspas simples garantem que tudo seja passado ao servidor remoto como o comando a ser executado pelo seu shell padrão.

Agradecemos novamente ao dogbane por fornecer a pista necessária -t. Eu costumava resolver esse problema expect, o que definitivamente mata um rato com um canhão. (:

user1179239
fonte
2

Experimente esta solução.

echo "command" | ssh user@remote_host

O logon é interativo e seu comando é passado como se você o digitasse na linha de comando interativa. A sessão termina como se você tivesse digitado

ssh user@remote_host 'command'
user210540
fonte
3
Se a sessão terminar após a conclusão do comando, isso não responderá à pergunta. O ponto inteiro do comando deve ser deixado com uma sessão interativa após a execução do comando, não apenas para enviar comandos aos servidores ssh.
iconoclast
Esta é pelo menos bom para simular um interactve para o comando a ser executado em, sem o uso -tou o seu próprio arquivo de bash. +1
laggingreflex
0

Use ssh -X para usar cmd termIO.

Além disso - você pode encadear seus cmds como "ssh 'source ~ / .bashrc && cd && do'"

ethrbunny
fonte
mas depois que toda a cadeia está concluída, não tenho mais uma sessão interativa, certo? Ainda fecha, certo?
Iconoclasta
E você gostaria de elaborar a solução termIO?
Iconoclasta
0

por que não instalar desanexar no sistema remoto e usar:

ssh -t [email protected] "/home/user/bin/detach ls"
Dan D.
fonte
isso vai correr 'ls' e então me deixa com uma sessão interativa? E se, em vez de 'ls', eu corro 'source .somefile' para obter alguns aliases e funções. Eles estarão disponíveis na minha sessão interativa ou serão executados em uma sessão diferente?
Iconoclast
Não, devido a detach, lsnão mantém a sessão aberta e será desconectada sem imprimir a saída de, lsmas ainda será executada.
Dan D.
Estou tentando executar comandos (arbitrários) no servidor (programaticamente especificado no cliente), mas depois tenho uma sessão interativa aberta que é afetada por qualquer coisa feita por esses comandos programáticos. Então, se eu entendi direito, isso não me ajuda.
iconoclasta
0

A resposta de laggingreflex está próxima ... Eu mudaria da seguinte forma:

echo "command\n$(cat -)" | ssh user@remote_host

Infelizmente, é provável que você não goste da maneira como isso funciona, porque "cat" armazena em buffer as linhas que ele escreve no stdout ... Se criarmos um script chamado "echo-cat" que se parece com isso:

{
  echo "${@}"
 #cat buffers & won't flush to stdout immediately
 #cat -
  IFS='\n'
  while read line
  do
        echo "${line}"
  done
}

obteremos o mesmo resultado sem o buffer:

echo-cat "command" | ssh user@remote_host

Isso provavelmente o levará muito mais perto do seu objetivo ...

Conta
fonte
0

Isso é kludgey e não testado, mas acho que deve funcionar.

Crie um script chamado (por exemplo) remote-starter que use um argumento entre aspas após um argumento user @ host:

remote-starter [email protected] 'some-command.sh arg1 arg2'

Esse script deve primeiro salvar o comando entre aspas (sem aspas) no arquivo nomeado (por exemplo) .onetimena máquina remota e, em seguida, executar um comando ssh regular, desta vez sem passar nenhum comando a ser executado na máquina remota. (Se você estiver executando ssh [email protected] a partir de um script, poderá funcionar para executar exec ssh [email protected].)

Para que isso funcione, a máquina remota deve obter .onetimeseu .bash_profile ou .zshrc ou qualquer outra coisa. Após a execução .onetime, ele deve ser excluído .onetime, para que o arquivo não seja executado na próxima vez que você fizer um logon regular.

iconoclasta
fonte