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
.