Como verificar o status de saída do comando esquerdo no pipe “left | direita ”em traço quando o comando esquerdo produz uma saída grande

1

Parece que a variável "PIPESTATUS" não está disponível em dash . A execução separada simples não está funcionando porque o comando esquerdo produz uma saída muito grande. Eu usei um fifo para fazer essa tarefa:

#!/bin/dash
mkfifo command1 command2
dash -c "cat ./content;code=\${?};echo \${code} > command1 &" | dash -c "md5sum;code=\${?};echo \${code} > command2 &"
echo "$(cat ./command1)" "$(cat ./command2)"

mas não sei por que foi enforcado?

    
por illiterate 23.09.2018 / 11:28

2 respostas

1

Você pode soltar o seu script fechando o stdout na mão esquerda do pipe e o stdin à direita logo após os comandos terem saído:

Exemplo:

#! /bin/dash
rm -f /tmp/s1 /tmp/s2
mkfifo /tmp/s1 /tmp/s2
{ (echo yes; exit 13); s1=$?; exec >&-; echo $s1 >/tmp/s1 & } | { (cat; exit 17); s2=$?; exec <&-; echo $s2 >/tmp/s2 & }
echo "'cat /tmp/s1' 'cat /tmp/s2'"

Substitua o (...; exit ..) pelos seus respectivos comandos.

Fechar o stdin à direita do pipe após o comando ter saído, faz com que um write () na mão esquerda receba um SIGPIPE ou EPIPE ao invés de bloquear ao tentar canalizar para o comando echo ... >fifo & do right (que é bloqueado em um open ()), e fechar a stdout à esquerda está causando um read () na mão direita do pipe para receber um EOF em vez de tentar canalizar a partir do echo ... >fifo & de bloqueio no esquerda.

Obrigado a @ilkkachu pela correção.

    
por 23.09.2018 / 23:57
1

Você pode usar um pipe nomeado e conectar os dois processos manualmente. Inicie-os na ordem oposta, de modo que o lado esquerdo seja executado em primeiro plano e você obtenha o status de saída de $? como de costume.

#!/bin/sh
dir=$(mktemp -d)
mkfifo "$dir/p"
cat < "$dir/p" > /dev/null &
( echo foo; exit 12; ) > "$dir/p"
echo "exit status: left: $?"
rm -r "$dir"

Ou, se você quiser os dois, obtenha o PID do processo em segundo plano de $! e wait para obter o status de saída.

#!/bin/sh
dir=$(mktemp -d)
mkfifo "$dir/p"
( echo foo; exit 12; ) > "$dir/p" &          # left-hand side
pidleft=$!
( cat; exit 34; ) < "$dir/p" > /dev/null &   # right-hand side
pidright=$!
wait "$pidleft"; exitleft=$?
wait "$pidright"; exitright=$?
echo "exit status: left: $exitleft right: $exitright"
rm -r "$dir"

Você ainda pode deixar a segunda parte do tubo em primeiro plano, eu só queria fazer simetricamente.

Você também pode, por exemplo armazene o status de saída para os arquivos e busque-os de lá:

#/bin/sh
( somecmd; echo "$?" > exit1 ) | ( cat; echo "$?" > exit2)
echo "exit status: left: $(cat exit1) right: $(cat exit2)"

Eu não acho que um pipe nomeado será de muita utilidade aqui, já que o status de saída é apenas um par de bytes. O shell aguardará a conclusão do pipeline antes de tentar ler exit1 e exit2 na segunda linha.

Se você quiser usar pipes nomeados, precisará colocar o pipeline em segundo plano, já que as gravações nos canais serão bloqueadas até que o lado da leitura seja aberto.

#/bin/sh
mkfifo exit1 exit2
( somecmd; echo "$?" > exit1 ) | ( cat; echo "$?" > exit2) &
echo "exit status: left: $(cat exit1) right: $(cat exit2)"

No entanto, se o cat s ler os canais não for executado por algum motivo, sub-submarinos escrevendo para eles serão bloqueados indefinidamente em segundo plano.

    
por 23.09.2018 / 17:08

Tags