Estou escrevendo um script wrapper de shell que deve funcionar como um pager (recebendo entrada em stdin e executando saída em um tty).
Este wrapper prepara o ambiente e as linhas de comando e, em seguida, inicia dois processos em um pipeline: o primeiro é um filtro não interativo e o último é o pager real que precisa controlar um tty (ou melhor, gera o próprio pager real) :
#!/bin/bash
...
col -bx | bat "${bat_args[@]}" --paging=always
A árvore de processos resultante é assim:
<parent>
\- wrapper.sh
|- col -bx (dies)
\- bat ...
\- less ...
O col -bx
processo sai após filtrar a entrada e é colhido pelo shell.
É possível se livrar do processo shell, de modo que ele não permaneça enquanto o pager estiver em execução?
Pensei em uma solução alternativa usando substituição de processo:
exec bat "${bat_args[@]}" --paging=always < <(col -bx)
Porém, o col -bx
processo não é colhido pelo shell e permanece no estado Z. Existe uma maneira "certa" de escrever esse wrapper?
Você também pode fazer:
Ou:
(não com as implementações de ksh derivadas de pdksh)
No final, funcionalmente equivalente ao que você faz com um redirecionamento de uma substituição de processo, mas pule aquele embaralhamento extra de fd e a criação de pipe nomeado (ou
/dev/fd/x
abertura em sistemas que os possuem (a maioria)).Em qualquer caso, para colher um processo, é preciso esperar por ele. Com
ksh
// e as abordagens acima, será um filho do processo que eventualmente executa , então receberá um SIGCHLD quando morrer, o que ele fará comzsh
ele depende dele. Se ele não lidar com o SIGCHLD (poucos aplicativos o fazem para processos que eles próprios não geraram), será exibido como um zumbi até o término, após o qual o processo será re-parentado para o sub-reaper filho ou e cuidado de lá.bash -O lastpipe
col
bat
bat
col
col
bat
col
init
De qualquer forma, observe que em
A | B
, ksh não espera porA
nenhum dos dois, a menos que você defina apipefail
opção.Agora, por POSIX na opção XSI , e isso também se aplica ao Linux,
(ênfase minha).
Agora, nem todos os shells permitirão que você ignore o SIGCHLD, sendo tão essencial para o seu funcionamento (o objetivo dos shells é executar comandos e relatar seu status de saída), mas parece com as versões atuais de
bash
(5.2.21 no meu teste) pelo menos faça, então em:O processo em execução
col
nunca se tornaria um zumbi, desde quebat
não ignore o SIGCHLD antes decol
sair.De qualquer forma, os zumbis não são necessariamente uma coisa ruim. O estágio zumbi faz parte do processo da vida, a maioria dos processos passa por lá entre o momento em que morrem e seus pais (ou
init
filho sub-ceifador) reconhecem isso.