Como impedir que o CTRL + C interrompa a conexão ssh?

4

Quando eu quiser parar tail -f , pressiono CTRL + C e retornarei ao prompt. Mas quando eu executo a conexão ssh, a CTRL + C quebra a conexão. (significado das bandeiras descritas aqui )

ssh -t svf "cd ~/w/logs; tail -f some_file.log; exec $SHELL -l"

este post não descreve como evitar o shell remoto sair para ssh -t remotehost command args ...

Como parar o comando (neste exemplo tail -f ) com CTRL + C e não interromper a conexão ssh?

    
por Eugen Konkov 01.03.2016 / 11:50

2 respostas

3

Em

ssh -t svf "cd ~/w/logs; tail -f some_file.log; exec $SHELL -l"

-t significa que a disciplina de linha tty local está definida como modo raw (passagem) e uma pseudo-tty é criada no lado remoto.

Essa pseudo-tty terá configurações padrão que na maioria dos sistemas significa, por exemplo, que um caractere ^C fará com que um SIGINT seja enviado ao grupo de processos em primeiro plano desse pseudo-terminal.

Aqui, quando você ssh com um comando, sshd é executado login-shell-of-the-remote-user -c that-command . Isso é um shell não interativo, portanto, não executa controle de tarefas.

Em particular, esse shell, como todo comando executado, será executado no mesmo grupo de processos que é o grupo de processos em primeiro plano do terminal.

O shell $SHELL -l (note que $SHELL é expandido na máquina local que provavelmente não é o que você quer) será um shell interativo (como é chamado sem -c e seu stdin é um dispositivo terminal) , portanto, executará comandos (pipelines) em diferentes grupos de processos e os tornará o grupo de processos em primeiro plano do terminal ou não conforme necessário.

Aqui, para fazer com que apenas tail -f receba o SIGINT, ou pelo menos que apenas ele e não o shell seja eliminado, você tem várias opções dependendo do shell de login do usuário remoto.

Se o shell de login do usuário remoto for bash ou yash , você poderá fazer:

ssh -t svf 'set -m; cd ~/w/logs && tail -f some_file.log; exec "$SHELL" -l'

A opção -m habilita o controle de trabalho. Isso indica ao shell para executar pipelines em grupos de processos separados (como para shells interativos) e (para bash e yash , geralmente não para todos os outros shells) que o grupo de processos de pipelines executados em primeiro plano se torna o grupo de processos em primeiro plano do dispositivo de terminal (para que eles obtenham o SIGINT on ^C ou SIGTSTP on ^Z , por exemplo), e os iniciados em segundo plano não são (para que eles sejam proibidos (receba SIGTTIN) para ler do terminal, por exemplo).

Dessa forma, tail -f será executado em seu próprio grupo de processos, que será o grupo de processos em primeiro plano. Se você digitar CTRL + C enquanto tail estiver em execução, somente tail receberá o SIGINT.

Outra alternativa, se você sabe que o shell é como o Bourne, é definir um manipulador para o SIGINT:

ssh -t svf 'trap : INT; cd ~/w/logs && tail -f some_file.log; exec "$SHELL" -l'

Aqui, estamos configurando o shell para que ele execute o comando : (no-op) ao receber o SIGINT. Processos filhos herdarão esse manipulador, mas ao executar um comando, o manipulador será redefinido para o padrão (de terminar o processo).

Então, agora, com CTRL-C enquanto tail estiver rodando, tanto o shell quanto o tail receberão o SIGINT, mas somente o final morrerá, e o shell continuará executando "$SHELL" -l .

Se você sabe que bash ou yash estão disponíveis no host remoto (e o shell remoto é como Bourne ou csh), você também pode fazer:

ssh -t svf 'cd ~/w/logs && bash -c "set -m; tail -f some_file.log"; exec "$SHELL" -l'

Invocamos explicitamente o shell bash e transformamos a opção -m para que tail seja iniciado em seu próprio grupo de processos em primeiro plano e apenas receba o SIGINT como para a solução firs.

Com bash-4.3 ou acima, você pode substituir o bash -c "set -m; por bash -mc " . Isso não funcionará com versões mais antigas que ignoram a opção -m (e -i ) passada no interpretador bash se combinada com -c .

    
por 02.03.2016 / 11:36
0

Para evitar que a CTRL + C interrompa a conexão, ela deve ser interativa.

Isso é obtido com bash -i . Então eu posso correr:

ssh -t svf 'cd ~/w/logs; bash -i tail -f some_file.log; exec $SHELL -l'

mas isso causa esse problema . Para resolvê-lo, você pode criar uma solução alternativa. Na máquina remota, crie um script para executar o comando ( Observe -i flag. É importante. Se você precisar do mesmo ENV que o login normal, poderá adicionar -l flag também):

$ cat ~/cmd 
#!/bin/bash -i
cmd="$*"
eval $cmd

Do que modifico meu comando para:

ssh -t svf 'cd ~/w/logs; ~/cmd tail -f some_file.log; exec $SHELL -l'

Agora estou feliz e posso CTRL + C quando tail -f é executado. Por causa da interatividade bash -i , a conexão ssh não está quebrada e o comando exec $SHELL -l é executado depois que a tecla de atalho é chamada.

OBSERVAÇÃO IMPORTANTE: Você deve usar 'em vez de' para expandir $ SHELL em um lado remoto e não no local. Obrigado a Stéphane Chazelas

    
por 01.03.2016 / 22:11

Tags