Um tee (processo) está truncar seu stdout ao gravar um arquivo

3

Quando eu uso tee para canalizar stdout diretamente para um "bloco de código específico" (que então grava os dados modificados em um arquivo), sempre obtenho o complemento total de linhas de saída exectadas no arquivo.

No entanto, quando eu tee os mesmos dados para um processo >("same block of code") , ele pode descartar até 4 linhas da saída. Esse número varia; às vezes escreve todas as linhas.

Como posso resolver esse problema e por que ele está acontecendo apenas no >( process ) ?

Mais informações: Estou indo para 2 substituições de processo e também para o canal stdout normal quando esta linha cair.

usando o GNU bash, versão 4.1.5 (1) -release (i486-pc-linux-gnu) no Ubuntu 10.04.2 LTS.

Aqui está o script atual. A segunda substituição do processo é aquela em questão, aquela que começa com >(tr $'\x60' $X01

#  
# Run 'locate' and direct the output to a temp file
  errflag=""
  locitmct=0  # Count of located items 
  columns=4  # The number of columns in the main dialog
  colmnb=0  # Column number (NB: columns 1 and 2 are processed together) 
  X01=$'\x01'
  eval locate $zenargs |tee \
      >(zenity --progress --pulsate --auto-close) \
      >(tr $'\x60' $X01 \
         |sed -n "s/^\(.*\/\)\(.*\)/\n\n/p" \
            |while IFS= read -r line ; do \
              #
              #
              # process the data
              #
              #
            done > "$listf" )\
      >/dev/null
#
cat "$listf"
#
    
por Peter.O 05.04.2011 / 07:25

2 respostas

2

Já faz 10 horas desde que eu fiz a pergunta, e eu trabalhei com uma solução ... Nota: Como eu mencionei anteriormente em um comentário (sob a pergunta), wait não funciona com estes processos. Presumo que seja porque essas 'substituições de processos' não são processos 'filhos', que acredito ser o que wait espera. (Eu tentei wait sem args) ....

Os comentários sobre suas características e falhas seriam bem-vindos. Eu não entendo muito bem como stdin é pego por zenity e tr quando echo é o primeiro comando, mas eu pensei em dar uma chance ... Parece funcionar (neste caso ), mas este método é seguro?

É bem provável que existam métodos bem experimentados e testados para lidar com isso, então outras respostas valeriam a pena ....

#!/bin/bash
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# Set up flag-files for processes to send PIDs to main process
# The first thing each process does is: echo -n "$BASHPID " > flag-file  
for i in {1..2};do cp /dev/null "$listf".pid$i;done
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
eval locate $zenargs |tee \
    >(echo -n "$BASHPID " > "$listf".pid1 ; \
      zenity --progress --pulsate --auto-close) \
    >(echo -n "$BASHPID " > "$listf".pid2 ; \
      tr $'\x60' $X01 \
       |sed -n "s/^\(.*\/\)\(.*\)/\n\n/p" \
          |while IFS= read -r line ; do \
              #
              #
              # process the data 
              #
              #
          done > "$listf" ) \
    >/dev/null
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
####  WAIT for processes to terminate  
pids=$(cat "$listf".pid{1,2})
while [[ "$pids" == *[0-9]* ]] ; do
   sleep .1 # GNU
   for pid in $pids ; do
      if ! kill -0 "$pid" 2>/dev/null; then
         pids="${pids/$pid/}"
      fi
   done 
done
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
cat "$listf"
#
    
por 05.04.2011 / 18:06
1

A partir da versão 8.24 do coreutils, existe outra maneira:

tee -p </dev/zero >(head -c10M | wc -c ) > >(head -c1 | wc -c ) | numfmt --to=iec

A saída é

1

10M

Os pontos cruciais aqui são

  1. Use -p , o que fará com que tee avise sobre erros ao gravar em qualquer saída, não em um canal. Isso significa que o erro EPIPE em fwrite não fará com que tee seja encerrado e tee será executado enquanto houver pelo menos um arquivo de saída aberto para gravação. Se você gostaria de receber um aviso sobre o EPIPE impresso para stderr, use --output-error=warn em vez de -p .

  2. Use > >(head -c1 | wc -c ) para redirecionar a stdout do tee para outro >(process substitution) . Isto é importante por duas razões. Você precisa cuidar da saída stdout produzida por tee . Se você usar >/dev/null , por exemplo, tee será executado enquanto stdin tiver dados (para sempre neste caso). Ao mesmo tempo, permitirá que a saída de >(process substitution) seja enviada para stdout para o processamento adicional. Outras possibilidades, mas não tão elegantes, são fechar a saída stdout de tee por outros meios. Duas possibilidades são >/dev/full e >&- . No entanto, eles emitirão avisos (tee: saída padrão: sem espaço no dispositivo e tee: saída padrão: descritor de arquivo inválido, respectivamente)

por 20.11.2015 / 03:13