É seguro digitar outro comando no STDIN enquanto o comando anterior está gravando no STDOUT?

21

Talvez isso tenha sido respondido anteriormente, eu gostaria de receber um link para outra resposta ...

Se eu executar um comando do shell (em um bashshell) como o seguinte:

make

Então, enquanto a saída de makeestá rolando a partir STDOUTdo makecomando, se eu digitar make checke pressionar enterantes que o primeiro comando seja executado, quando o makecomando finalmente terminar, o próximo comando make checkserá retomado e executado.

Minhas perguntas são simplesmente:

  1. Isso é perigoso de se fazer?
  2. Existem comportamentos potenciais inesperados desse tipo de digitação rápida?
  3. Por que isso funciona da maneira que funciona?
111 ---
fonte
2
1. Espero que não seja ... venho fazendo isso há anos!
John WH Smith

Respostas:

20

Funciona da mesma maneira porque o Unix é full-duplex. Como Ritchie disse em O sistema de compartilhamento de tempo UNIX: uma retrospectiva :

Uma coisa que parece trivial, mas que faz uma diferença surpreendente quando se acostuma, é a E / S do terminal full-duplex, juntamente com a leitura antecipada. Embora os programas geralmente se comuniquem com o usuário em termos de linhas, em vez de caracteres únicos, a E / S do terminal full-duplex significa que o usuário pode digitar a qualquer momento, mesmo se o sistema estiver digitando novamente, sem medo de perder ou distorcer caracteres. . Com a leitura antecipada, não é preciso esperar uma resposta para cada linha. Um bom datilógrafo que entra em um documento fica incrivelmente frustrado por ter que fazer uma pausa antes de iniciar cada nova linha; para quem sabe o que quer dizer, qualquer lentidão em resposta torna-se psicologicamente ampliada se a informação precisar ser inserida pouco a pouco em vez de em velocidade máxima.

[citação final]

Dito isto, existem alguns programas modernos que consomem ou descartam qualquer tipo de digitação; sshe apt-getsão dois exemplos. Se você digitar com antecedência enquanto estiverem em execução, poderá descobrir que a primeira parte da sua entrada desapareceu. Isso poderia ser um problema.

ssh remotehost do something that takes 20 seconds
mail bob
Dan has retired. Feel free to save any important files and then do
# ssh exits here, discarding the previous 2 lines
rm -fr *
.
Mark Plotnick
fonte
Então, após se bash fork()es execo comando, o primeiro comando ainda está anexado ao do STDINshell bash? Parece que a resposta é não, o bash parece estar armazenando buffer para o próximo comando. Isso está correto?
111 ---
A menos que você diga ao shell para redirecionar o stdin do comando, o comando terá o mesmo stdin que o shell. Tudo o que você digita é lido pelo primeiro processo que a lê. O shell intencionalmente não tenta ler nada enquanto um comando está em execução e aguarda até que o comando seja interrompido. As coisas ficam mais complexas se você colocar o comando em segundo plano com &.
Mark Plotnick
Então, é STDINtratado de uma maneira quino? E suponho que, a menos que o processo filho do bash feche explicitamente seu identificador de arquivo herdado STDIN, ele ainda poderá ler a partir de digitação adicional?
111 ---
Sim, toda a entrada do terminal é tratada como FIFO. Não tenho certeza se entendi sua segunda pergunta. O processo filho - o comando que o shell chamou - geralmente não fecha explicitamente seu stdin; o shell sai do caminho e permite que o comando leia tudo o que deseja, então o filho para e o shell retoma a leitura.
Mark-Plotnick
Sim, você respondeu às minhas perguntas de acompanhamento com muita clareza, obrigado!
111 ---
12

O comportamento básico que você está vendo é que a entrada fica em um buffer em algum lugar até que seja lida (bem, se você digitar o suficiente, eventualmente os buffers serão preenchidos e algo será perdido, porém , seria muita digitação). A maioria das coisas executadas pelo make não lê do STDIN, portanto permanece no buffer.

O perigo é que o comando errado leia sua entrada. Por exemplo, makechama algo que decide solicitá-lo e, em seguida, pode ler o seu próximo comando como resposta. Quão perigoso isso depende do comando, é claro. (Eles também podem liberar todas as entradas primeiro, apenas descartando a entrada anterior.)

Um comando, comumente usado em Makefiles, que pode fazer isso é o TeX. Se encontrar um erro (e não receber um sinalizador para nunca solicitar ao usuário), ele perguntará como você deseja continuar.

A melhor opção é provavelmente a prazo: make && make check.

derobert
fonte
8
  1. Bem, semi-obviamente, você não deve executar um segundo comando que dependa do primeiro comando ( makeno seu exemplo) ter sido concluído com êxito. Por exemplo, make foo Enter> ./foo Enter pode causar um problema. Você pode tentar adquirir o hábito de digitar coisas como make && make check, onde o segundo comando será executado apenas se o primeiro for bem-sucedido.
  2. Teoricamente, é possível que o primeiro comando (processo) possa ler parte do segundo comando ou removê-lo do buffer de entrada do terminal. Se make checktivesse os seis primeiros caracteres de , você acabaria executando o comando heck, o que provavelmente não existe no seu sistema (mas pode ser algo desagradável). Se o primeiro comando é algo benigno em que você conhece e confia, não vejo imediatamente nenhum problema.
  3. Como / por que funciona? O sistema armazena em buffer a entrada do teclado. É um pouco como o e-mail: você pode enviar cinco mensagens a uma pessoa em um curto período de tempo, e elas ficam na Caixa de Entrada, esperando que as leia. Da mesma forma, desde que o primeiro comando não seja lido no teclado, o (s) comando (s) digitado (s) aguardará que o shell tente lê-los. Há um limite de quanto "digitação antecipada" pode ser armazenado em buffer, mas geralmente possui várias centenas de caracteres (se não vários milhares).
Scott
fonte
2
Para o ponto 1, imagine que os comandos não sejam relacionados, isto é, lse mountpor exemplo. Estou tentando entender como a entrada em buffer é tratada. Obrigado pela resposta.
111 ---