Resultados estranhos da tripla tubulação para STDOUT & tee / dev / null (wc -l tmp.txt) e piping novamente embutindo 'cat tmp.txt'

1
$ seq 1 12773 | tee /dev/null >(wc -l > tmp.txt) | head -$((0x'openssl rand -hex 7' % 'cat tmp.txt' + 1))|tail -1

- > 8473 (aleatório entre 1 ~ 12773)

$ cat tmp.txt

- > 8473

$ seq 1 12774 | tee /dev/null >(wc -l > tmp.txt) | head -$((0x'openssl rand -hex 7' % 'cat tmp.txt' + 1))|tail -1

- > (NULL)

$ cat tmp.txt

- > 8844 (aleatório entre 1 ~ 12773)

$ seq 1 25011 | tee /dev/null >(wc -l > tmp.txt) | cat | head -$((0x'openssl rand -hex 7' % 'cat tmp.txt' + 1))|tail -1

- > 13778 (aleatório entre 1 ~ 25011)

$ cat tmp.txt

- > 13778

$ seq 1 25012 | tee /dev/null >(wc -l > tmp.txt) | cat |head -$((0x'openssl rand -hex 7' % 'cat tmp.txt' + 1))|tail -1

- > (NULL)

$ cat tmp.txt

- > 24939 (aleatório entre 1 ~ 25012)

$ seq 1 46014 | tee /dev/null >(wc -l > tmp.txt) | cat | cat |head -$((0x'openssl rand -hex 7' % 'cat tmp.txt' + 1))|tail -1

- > 34111 (aleatório entre 1 ~ 46014)

$ cat tmp.txt

- > 34111 (aleatório entre 1 ~ 46014)

$ seq 1 46015 | tee /dev/null >(wc -l > tmp.txt) | cat | cat |head -$((0x'openssl rand -hex 7' % 'cat tmp.txt' + 1))|tail -1

- > (NULL)

$ cat tmp.txt

- > 343 (aleatório entre 1 ~ 46014)

como o número de '| cat's behind "(wc -l > tmp.txt)" aumenta, você pode fazer os comandos acima para trabalhar com um número maior de linhas.

O que está acontecendo?

    
por user58029 11.12.2016 / 11:08

1 resposta

0

Como AlexP explicou nos comentários, os comandos em um pipeline são executados em paralelo . Você parece estar convencido de que isso não é verdade; por favor, esqueça este equívoco, você não será capaz de entender o que está acontecendo, desde que você não abra sua mente.

Como os processos estão sendo executados em paralelo, a sequência de operações depende do tempo exato e pode não ser reproduzível de uma execução para a próxima.

Tomando seu primeiro exemplo, os seguintes comandos são executados em paralelo:

  • seq 1 12773
  • tee /dev/null
  • wc -l > tmp.txt (uma substituição de processo também cria um canal e executa o comando em paralelo)
  • head -$((0x'openssl rand -hex 7' % 'cat tmp.txt' + 1)) - envolve três comandos diferentes e head começa depois que openssl e cat saíram
  • tail -1

Como wc -l > tmp.txt e cat tmp.txt são executados em paralelo, é imprevisível quando cat tmp.txt será executado em relação à saída de wc :

  • Ele pode ser executado antes que o redirecionamento para tmp.txt seja executado e, ou pegar o arquivo de uma execução anterior, se houver, ou reclamar que o arquivo não existe de outra forma.
  • Pode ser executado após o redirecionamento ser realizado, mas antes que wc produza qualquer saída; Nesse caso, o arquivo está vazio, pois o redirecionamento trunca o arquivo.
  • Pode ser executado enquanto wc está produzindo saída e seleciona apenas o início da saída. Na maioria dos sistemas, wc produz sua saída atomicamente (porque é muito curto), então isso não acontecerá.
  • Pode ser executado depois que wc terminar de produzir a saída.

Experimentalmente, recebo os mesmos resultados que você (em uma máquina Linux executando o kernel 3.16 que, de outra maneira, é mais ociosa): com seq 1 12773 , cat tmp.txt seleciona a saída de wc ; com seq 1 12774 , cat tmp.txt seleciona um arquivo vazio. Então, por que há uma diferença entre 12773 e 12774, mas os resultados são bastante confiáveis abaixo desse valor?

$ seq 1 12774 | wc -c
65538

Há um limite em 65536 bytes e esse valor é a capacidade do buffer de tubo . O comando head … é lento para iniciar, porque ele precisa executar openssl e cat até a conclusão primeiro. Enquanto está sendo iniciado, o comando anterior no pipeline grava no buffer de tubulação. Quando o buffer de pipe fica cheio, o comando anterior tem que parar. Com números até 12773, o buffer de pipe nunca é preenchido, então, com toda a probabilidade seq termina de ser executado antes de openssl (tem muito menos trabalho a fazer) e wc tem tempo para gravar sua saída. Mas com números maiores que 12774, o buffer do tubo é preenchido; então tee está preso escrevendo na saída que vai para head … e não termina de gravar a saída em wc ainda. Enquanto isso, cat é executado com um arquivo vazio.

Quando você adiciona mais canais, cada um tem seu próprio buffer, portanto, há mais espaço antes de tee parar.

    
por 12.12.2016 / 02:23