Eu tenho esta função zsh:
f() {
/usr/bin/find . -type f | less
}
Quando executo essa função, suspendo com Ctrl+z e, em seguida, executo fg, ela exibe zsh: suspended (tty output) /usr/bin/find . -type f |
e não consigo continuar. Por que isso? Como posso continuar?
arch% f
zsh: suspended /usr/bin/find . -type f |
arch% fg
[2] - continued /usr/bin/find . -type f |
zsh: suspended (tty output) /usr/bin/find . -type f |
zsh: suspended (tty output) /usr/bin/find . -type f |
arch%
Se eu executar /usr/bin/find . -type f | less
diretamente da linha de comando sem torná-lo uma função, ele será suspenso e retomado normalmente.
Este é um bug que afeta o zsh 5.9 . Foi corrigido em novembro de 2022, mas não houve nenhum lançamento desde dezembro de 2024.
Se você fizer:
11128 é de fato o PGID do trabalho que tem
find
eless
, e a retomada funciona bem, mas:Desta vez, 11493 é o PID de
less
, não o PGID do trabalho que tem ambosfind
eless
que é 11492.Então, quando
fg
tenta colocar o trabalho em primeiro plano, ele faz umtcsetpgrp(11493)
que não consegue colocar esse trabalho em primeiro plano, então continua retomando todos os processos com SIGCONT, e acontece queless
ao retomar faz umtcsetattr()
(o que ostty
comando normalmente faz) que os processos em segundo plano não têm permissão para fazer, então todo o grupo de processos recebe um sinal SIGTTOU e é suspenso novamente.Aqui, uma solução alternativa seria alterar a definição da função para:
Ou seja, use um subshell em vez de um grupo de comando como o corpo da função, para que haja apenas um processo com o qual o processo pai precisa se preocupar e não haja espaço para confusão.
Usando:
Também parece funcionar (embora implique um processo adicional por algum motivo).
O controle de tarefas é um negócio bem complicado, especialmente quando, como o zsh ou o ksh fazem, você tenta executar o lado direito de um pipeline no shell atual e, como o zsh ou o AT&T ksh, você tenta ter um comportamento mais útil ao pressionar ^Z em um comando composto (como o corpo da sua
f
função aqui).Observe o processo extra 11501 que apareceu acima quando
f
foi suspenso. Ele está lá para que o resto da função possa continuar após ofind
,less
ser retomado (comfg
oubg
) e eventualmente terminar.Veja como no bash ou mksh, se você fizer isso:
E aperte ^Z,
sleep
está suspendendo masecho here
é executado naquele ponto ! E então se vocêfg
,sleep
é retomado, mas o resto da função já foi executado!Veja o comentário explicando isso no código:
Um dos problemas (e não sei o quanto isso contribui para o problema discutido aqui; edite , provavelmente não estou olhando para a correção ) é que esse "superjob" não é o pai dos processos que foram suspensos, então, por exemplo, não pode obter seu status de saída:
echo "$?"
foi de fato executado após(sleep...)
ser encerrado e não quando foi suspenso como embash
, mas$?
reflete um status suspenso, não o que4
você esperaria.Conforme sugerido no comentário acima, você pode encontrar o comportamento descrito em
zshmisc(1)
ouinfo zsh jobs
: