Em um script de shell, faço o seguinte:
#!/bin/sh
while true; do ssh -o ExitOnForwardFailure=yes -L 8080:localhost:80 -N server; sleep 1; done &
... rest of the script, which uses the tunnel as made above ...
Isso garante que o túnel seja sempre mantido aberto e, portanto, seja reaberto em caso de perda de conexão. Este túnel é usado em outras partes do script principal, omitido aqui. Essas peças podem lidar com um túnel não funcional, elas simplesmente tentam novamente mais tarde.
Quando o script principal morre, por exemplo devido a um SIGTERM
ou SIGINT
, quero que esse while
loop pare também. Não há necessidade de manter esse túnel aberto depois que o script principal morre.
Qual é a abordagem comum para fazer isso em scripts de shell? Note que eu quero duas coisas:
- impedir a reexecução do
ssh
comando - interrompa e desconecte a sessão atual em andamento
ssh
o mais rápido possível
Não tenho certeza de como fazer tudo isso em scripts de shell.
Observe que atualmente estou trabalhando em plain sh
, mas posso prosseguir bash
se necessário.
Uma abordagem um tanto geral.
O truque é que o script executa processos filhos (aqui
foo
entre outros) com ID do grupo de processos (PGID) igual ao PID do shell. Isso se propaga para netos e assim por diante. O próprio shell também está nesse grupo de processos. Existem exceções (trabalhos em shells interativos,timeout
) portanto, isso não é tão geral quanto você deseja; ainda assim, comfoo
umssh
comando simples ou semelhante em um script não interativo, a abordagem deve funcionar.kill
com um argumento negativo envia sinais para todo o grupo de processos.Uma ressalva: uma possível condição de corrida. Em geral,
foo
pode ser eliminado antes que o subshell receba e manipule o sinal. Se o atraso for longo o suficiente (por qualquer motivo), um novofoo
pode ser gerado (especialmente se semsleep 1
) depois dekill
fazer seu trabalho. Considere esta melhoria:A armadilha está aqui apenas para fazer o shell principal sair normalmente sem imprimir
Terminated
no console.Não é uma abordagem geral para qualquer processo em segundo plano, mas geralmente é um método útil para
ssh
cenários semelhantes.Use
autossh
. Do seu manual :Portanto:
Observe que você não será notificado se o túnel não puder ser estabelecido em primeiro lugar. Como essa também é uma possível falha em sua abordagem original, não estou abordando esse problema aqui.