Às vezes faço xargs
trabalhos longos durante a noite e é muito chato descobrir pela manhã que xargs
morreu algures no meio, por exemplo devido a uma falha de segmentação num único caso especial, como aconteceu esta noite.
Se pelo menos um xargs
filho for morto, ele não processará mais nenhuma entrada:
Consola 1:
[09:35:48] % seq 40 | xargs -i --max-procs=4 bash -c 'sleep 10; date +"%H:%M:%S {}";'
xargs: bash: terminated by signal 15
09:35:58 3
09:35:58 4
09:35:58 2
<Exit with code 125>
Consola 2:
[09:35:54] kill 5601
Posso, de alguma forma, impedir xargs
a interrupção do processamento de mais entradas quando um processo filho morrer e, em vez disso, continuar o processamento?
Responder1
Não, você não pode. Dexargs
fontes em savannah.gnu.org:
if (WEXITSTATUS (status) == CHILD_EXIT_PLEASE_STOP_IMMEDIATELY)
error (XARGS_EXIT_CLIENT_EXIT_255, 0,
_("%s: exited with status 255; aborting"), bc_state.cmd_argv[0]);
if (WIFSTOPPED (status))
error (XARGS_EXIT_CLIENT_FATAL_SIG, 0,
_("%s: stopped by signal %d"), bc_state.cmd_argv[0], WSTOPSIG (status));
if (WIFSIGNALED (status))
error (XARGS_EXIT_CLIENT_FATAL_SIG, 0,
_("%s: terminated by signal %d"), bc_state.cmd_argv[0], WTERMSIG (status));
if (WEXITSTATUS (status) != 0)
child_error = XARGS_EXIT_CLIENT_EXIT_NONZERO;
Não há sinalizador em torno dessa verificação ou na função que a chama. Parece estar relacionado ao max procs, o que suponho que faz sentido: se você definir max procs alto o suficiente, não será necessário verificar até atingir o limite, o que talvez nunca aconteça.
Uma solução melhor para o que você está tentando fazer pode ser usarGNU Make:
TARGETS=$(patsubst %,target-%,$(shell seq 1 40))
all: $(TARGETS)
target-%:
sleep 10; date +"%H:%M:%S $*"
Então:
$ make -k -j4
terá o mesmo efeito e lhe dará um controle muito melhor.
Responder2
Parece que um dos coloquialismos mais óbvios só é aludido por outras propostas.
Ou seja, você pode usar o seguinte:
bash -c '$PROG_WHICH_MAY_FAIL ; (true)'
para "forçar o sucesso".
Observe que isso está de acordo com a proposta deLórnix(só não com tantas palavras).
De qualquer forma, como isso está efetivamente ignorando o status real de saída do processo, eu garantiria que você considerasse de alguma forma salvar o status do subprocesso para análise post-mortem. Por exemplo:
bash -c '$PROG_WHICH_MAY_FAIL || touch failed; (true)'
O true
aqui é um tanto redundante e, portanto, pode ser melhor escrito como:
bash -c '$PROG_WHICH_MAY_FAIL || touch failed'
Já que provavelmente gostaríamos de saber quando o arquivo 'com falha' não pôde ser tocado. Em outras palavras, não estamos maisignorandoa falha, estamos tomando nota e continuando.
E, depois de considerar a natureza recursiva desta questão, talvez vejamos exatamentepor quexargs não facilita ignorar falhas. Porque nunca é uma boa ideia - você deveria aprimorar o tratamento de erros no processo que está desenvolvendo. Acredito que esta noção, entretanto, seja mais inerente à própria "filosofia Unix".
Finalmente, suponho que é também a isso que James Youngman alude ao recomendar trap
, que presumivelmente poderia ser usado de maneira semelhante. Ou seja, não ignore o problema... prenda-o e resolva-o ou você acordará um dia e descobrirá que nenhum dos subprogramas teve sucesso ;-)
Responder3
Usar trap
:
$ seq 40 | xargs -i --max-procs=4 bash -c \
'trap "echo erk; exit 1" INT TERM; sleep 10; date +"%H:%M:%S {}";' fnord
16:07:39 2
16:07:39 4
erk
16:07:39 1
^C
erk
erk
erk
erk
Como alternativa, mude do shell para outro idioma no qual você também possa definir manipuladores de sinal.
Observe também que depois bash -c foo..
você deve especificar o valor que $0
deve receber (aqui, fnord
) para que a primeira palavra produzida por seq
não seja comida.
Responder4
Nem time
nem env
funcionou para mim (eles repassam o valor de retorno de seu programa filho), então escrevi bliss
:
#!/bin/sh
"$@"
exit 0
entãochmod u+x ~/bliss
e algo comofind_or_similar | xargs ~/bliss fatally_dying_program.sh