Os programas executados a partir de uma sessão ssh dependem da conexão?

28

Um programa executado a partir de uma sessão ssh depende da conexão com o cliente? Por exemplo, quando a conexão é muito lenta. Então, espera ativamente até que as coisas sejam impressas na tela?

E se depender da conexão, isso também acontece com a tela ou byobu por exemplo? Uma vez que com estes os programas são mantidos em execução mesmo depois de desconectar do host.

Nota: encontrei apenas estas questões relacionadas:

por agold 13.05.2016 / 14:16

3 respostas

25

A saída dos programas é armazenada em buffer, portanto, se a conexão for lenta, o programa será interrompido se o buffer ficar cheio.

Se você usar screen , ele também terá um buffer que será usado para tentar exibir uma sessão conectada. Mas um programa conectado na sessão de tela não será não interrompido se screen não puder atualizar o terminal remoto com rapidez suficiente. Assim como quando uma conexão é perdida, o programa continua preenchendo screens do buffer até que ele transborda (empurrando as informações mais antigas). O que você vê chegando (e pode rolar de volta para) depende do que está (ainda) naquele buffer. O screen discipula efetivamente seu programa do seu terminal (e sua conexão SSH lenta).

    
por 13.05.2016 / 14:22
9

Uma conexão SSH pode morrer prematuramente se a conexão TCP subjacente receber um pacote com o sinalizador RST . Isso pode acontecer se um lado enviar um pacote (que pode ser um probe de keepalive de SSH periódico), mas não receber uma confirmação de TCP em um período de tempo razoável ou se um roteador decidir que a conexão ficou ociosa por muito tempo ou se um ISP está apenas sendo malvado.

No modelo de terminal Unix, quando a conexão do terminal é interrompida, o driver do terminal envia um sinal HUP para o shell , cuja terminação também faz com que um SIGHUP seja enviado para processos em execução no shell.

Da FAQ do Programador Unix , item 1.15:

SIGHUP is a signal that means, by convention, "the terminal line got hung up". It has nothing to do with parent processes, and is usually generated by the tty driver (and delivered to the foreground process group).

However, as part of the session management system, there are exactly two cases where SIGHUP is sent on the death of a process:

  • When the process that dies is the session leader of a session that is attached to a terminal device, SIGHUP is sent to all processes in the foreground process group of that terminal device.

  • When the death of a process causes a process group to become orphaned, and one or more processes in the orphaned group are stopped, then SIGHUP and SIGCONT are sent to all members of the orphaned group. (An orphaned process group is one where no process in the group has a parent which is part of the same session, but not the same process group.)

O manipulador de sinal padrão para o SIGHUP é para finalizar o processo:

Signal     Value     Action   Comment
----------------------------------------------------------------------
SIGHUP        1       Term    Hangup detected on controlling terminal
                              or death of controlling process

É possível evitar a finalização do processo.

  • Você pode inserir um manipulador de sinal que ignore o SIGHUP. Para fazer isso como um usuário, coloque o comando em nohup . Por exemplo:

    nohup make all &
    
  • Você pode dizer ao shell para dissociar um processo filho dele. Por exemplo, o Bash tem um comando interno disown :

    make all
    

    CtrlZ

    bg
    disown %1
    

    Em seguida, o SIGHUP não será propagado para o filho (que não é mais um filho).

  • Alguns programas, especialmente daemons , usarão os mecanismos acima automaticamente: um programa pode instalar um SIGHUP alternativo manipulador (usando sigaction(2) ), ou ele poderia optar por participar de uma nova sessão ( setsid(2) ).
  • Você pode executar screen ou tmux , que aloca um pseudo-TTY para executar uma sessão com um shell que não recebe o SIGHUP quando a conexão SSH é interrompida. O SIGHUP não é retransmitido da sessão SSH para a sessão screen / tmux.

A propósito, uma maneira alternativa de lidar com conexões SSH não confiáveis é usar o protocolo Mosh . Mosh é executado em UDP, portanto, não há conexão TCP que corra o risco de ser redefinida.

    
por 13.05.2016 / 20:46
1

Sim, um programa executando o SSH dependerá de sua saída para algum lugar. Se a conexão é lenta, a saída deve ser armazenada em algum lugar, e os buffers não podem ser infinitos, então o programa deve bloquear se eles estiverem cheios.

Observe que a saída pode não necessariamente ir para um terminal: considere executar algo como

ssh user@somewhere "cat file.txt" > file.txt

Isso irá, na verdade, copiar o arquivo. Para que isso funcione, a taxa de saída do gato deve coincidir com a da conexão: deve ser óbvio que perder partes da saída do meio seria inaceitável.

A tela mudará a situação, pois atuará como um terminal e salvará o que deve ser mostrado "na janela do terminal" (mais rolagem). Não precisa se lembrar de tudo que o seu programa produz, apenas as partes que caberão na "janela" e rolarão. Por padrão, a tela aguardará uma conexão lenta (bloqueando o programa), mas ela pode ser configurada para detectar uma conexão bloqueada configurando "nonblock on".

Da página do manual:

nonblock [on|off|numsecs]

Tell screen how to deal with user interfaces (displays) that cease to accept output. This can happen if a user presses ^S or a TCP/modem connection gets cut but no hangup is received. If nonblock is off (this is the default) screen waits until the display restarts to accept the output. If nonblock is on, screen waits until the timeout is reached (on is treated as 1s). If the display still doesn't receive characters, screen will consider it "blocked" and stop sending characters to it. If at some time it restarts to accept characters, screen will unblock the display and redisplay the updated window contents.

Uma desconexão é diferente de uma conexão lenta. O SSH simples não pode se recuperar automaticamente, portanto, seu programa receberá um SIGHUP. Por outro lado, a tela detectará uma desconexão, desconectará e retornará ao buffer local até que a tela seja reconectada. Isso não bloqueará o programa em execução.

(Configurar nonblock 1 no seu .screenrc é importante se você executar algo como o irssi que produzirá continuamente a saída, mas ainda precisa falar com a rede ao mesmo tempo. O bloqueio levaria à desconexão do IRC, que é extremamente irritante ...)

    
por 14.05.2016 / 19:53