「xargs」が子プロセスの終了を無視し、さらに処理を続行させる方法

「xargs」が子プロセスの終了を無視し、さらに処理を続行させる方法

時にはxargs一晩中作業を実行し、朝の作業がxargs途中で消えたことがわかります。これは本当に迷惑なことです。たとえば、今夜発生した特別なケースの分割エラーが原因です。

一人の子供が死んでも、もうxargs入力を処理しません。

コンソール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>

コンソール2:

[09:35:54] kill 5601

xargs子プロセスが終了したら、より多くの入力処理を中止するのを防ぎ、代わりに処理を続行できますか?

答え1

いいえ、できません。 ~からxargsソース: 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;

このチェックまたはそれを呼び出す関数にはフラグがありません。これはmax-processesと関連があるようです。私の考えは理にかなっています。 max-processを十分に高く設定すると、限界に達するまで確認されず、おそらく限界に達しません。

あなたがしたいことに対するより良い解決策は次のとおりです。GNUが作る:

TARGETS=$(patsubst %,target-%,$(shell seq 1 40))

all: $(TARGETS)

target-%:
    sleep 10; date +"%H:%M:%S $*"

それから:

$ make -k -j4 

同じ効果を持ち、より良い制御を提供します。

答え2

最も明白な口語の1つが他の提案で言及されているようです。

つまり、次のものを使用できます。

bash -c '$PROG_WHICH_MAY_FAIL ; (true)'

「成功を強制」します。

これは提案の内容と一致しています。ロニックス(ただ多くの言葉ではありません)。

とにかく、これは実際のプロセス終了状態を効果的に無視するので、事後分析のために何らかの方法でサブプロセス状態を保存することをお勧めします。たとえば、

bash -c '$PROG_WHICH_MAY_FAIL || touch failed; (true)'

ここでは少し重複しているので、true次のように書くことをお勧めします。

bash -c '$PROG_WHICH_MAY_FAIL || touch failed'

「失敗した」ファイルにいつ触れることができないかを知りたいかもしれないからです。つまり、私たちはもはや無視する失敗、録画を続けています。

そして、この問題の再帰的性質を考慮した後、おそらく私たちは正確に知ることができます。なぜxargsは失敗を簡単に無視しません。これは決して良い考えではないため、開発中のプロセスでエラー処理を強化する必要があります。しかし、私はこの概念が「Unix哲学」自体にもっと本質的にあると信じています。

trap最後に、James Youngmanがおそらく同様の方法で使用できることをお勧めしますが、これが暗示されていると思います。つまり、問題を無視しないでください...問題をキャッチして処理します。そうでなければ、ある日目が覚めて、サブルーチンのどれも成功しないでしょう;-)

答え3

使用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

または、シェルでシグナルハンドラを設定できる他の言語に切り替えます。

また、生成された最初の単語が食べられないようにインポートする必要があるbash -c foo..$0(ここ)を指定した後は注意してください。fnordseq

答え4

timeどちらも私に合わなかったのでenv(サブルーチンの戻り値を渡す)、次のように書きましたbliss

#!/bin/sh
"$@"
exit 0

それからchmod u+x ~/bliss

そして同様のものfind_or_similar | xargs ~/bliss fatally_dying_program.sh

関連情報