Qual é o comportamento de 'cat | Menos'?

0

Eu tentei executar o seguinte comando:

cat | less

Eu sei que ambos os comandos exigem algo da entrada padrão. Quando eu corro isso é o que eu esperava: todas as minhas entradas vão para o cat e eu não serei capaz de enviar comandos para menos (eventualmente sem poder sair do programa com o comando q .).

Isso não é o que acontece. Na verdade, funciona corretamente desde que o número de linhas enviadas na entrada padrão seja menor que o número de linhas da tela. Quando o número de linhas enviadas na entrada padrão tornou-se maior do que o número de linhas da minha consola, uma aparência estranha era a que aparecia. Parece que a entrada é enviada às vezes para cat , às vezes para less . Por exemplo, inespectivamente, a letra q sometims deixa o programa sair.

Por que o motivo desse comportamento que eu (ingenuamente) não esperaria?

    
por user1833218 06.09.2015 / 22:28

2 respostas

2

O CAT aceitará entrada de stdin (embora indubitavelmente prefere a entrada de um arquivo ou pipe), E SAI PARA STDOUT

Isso significa que a entrada é simplesmente enviada por meio de cat e, em seguida, direcionada para menos. Assim, você pode ver a saída em menos.

Suas confusões provavelmente estão chegando com o buffer. O CAT está armazenando em buffer a entrada e estará enviando em lote (ou aguardando pelo final do arquivo) ao enviá-la para menos para formatação.

    
por 06.09.2015 / 22:47
2

Eu me odeio por dizer isso, mas

There’s more than one way to skin a cat.

Por que eu quero dizer, há entrada padrão e, em seguida, há entrada padrão. Ou está lendo no teclado (terminal) e depois há a leitura do teclado. Experimente

less < afilename

Funciona exatamente como

less afilename

que significa que less deve ter alguma maneira de ler no teclado além de ler a entrada padrão. Veja outro comando que funciona, mesmo que você não espere:

less afilename < /dev/null

Veja o comando tty . Ele relata o nome do tty (terminal) conectado à entrada padrão. Ele funciona chamando a função de biblioteca ttyname com um argumento de 0 (o descritor de arquivo da entrada padrão).

less provavelmente está chamando ttyname(1) para obter o nome do tty (terminal) conectado à saída padrão. Em seguida, ele abre esse arquivo para leitura e aceita comandos dele. Não lê comandos da entrada padrão; isso é apenas para dados.

Então, o que temos são dois processos quase independentes ( cat e less ) independentemente (concorrentemente) lendo no teclado (isto é, o tty / terminal) em dois descritores de arquivos independentes. Esta é uma situação confusa e é uma espécie de “condição de corrida”. Eu acho isso um pouco análogo ao funcionamento de uma máquina de pinball , em que existem muitas pistas, ou caminhos, que a bola pode levar - e sempre leva um ; nunca pode demorar mais do que um. Similarmente, quando vários processos estão lendo do mesmo terminal simultaneamente, cada linha digitada (se o terminal estiver no modo de linha) ou cada caractere digitado (se o terminal estiver no modo de caractere) vai para exatamente um processo. E a seleção é arbitrária, não diferente da ação do fliperama. Não é totalmente "aleatório", assim como o agendamento de processos é aleatório; mas é essencialmente imprevisível.

Então, eis o que acontece:

  • cat lê sua entrada padrão, que, por padrão, é o terminal, e grava em sua saída padrão, que é o canal para less .
  • Em algum momento, less chama ttyname(1) , obtém o nome do terminal em que está e abre para leitura.
  • less lê uma tela cheia de dados (ou seja, 24 linhas ou qualquer outra coisa) a partir de sua entrada padrão (o tubo) e grava-o na saída padrão (o terminal).
  • Em seguida, less emite o aviso : , coloca o terminal no modo de caractere, e começa a ler do terminal ( não da entrada padrão).
  • Então, agora temos dois processos ( cat e less ) lendo do terminal simultaneamente, e o fenômeno pinball entra em ação - os personagens (e / ou linhas) que você digita ir para cat ou less , semi-aleatoriamente. Se for para cat , ele será gravado no pipe e less tratará como dados. Se for para less , ele será interpretado como um comando less .

Isso não tem nada a ver com o armazenamento em buffer.

    
por 07.09.2015 / 02:00