'xargs'가 자식의 종료를 무시하고 계속 처리하는 방법


24

나는 때때로 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자식 프로세스가 종료되고 대신 처리를 계속하면 더 이상 입력을 처리하지 못하게 할 수 있습니까 ?


xargs4.4.2 버전을 사용 debian wheezy하고 있으며 특정 sleep프로세스를 종료 하더라도 모든 것이 잘 실행되는 것처럼 보입니다 . 어떤 버전 xargs을 사용하고 있습니까? 최신 버전에서 문제가 해결되었을 수 있습니다.
Kannan Mohan

늦은 파티에 작은, 그러나 방법에 대한 xargs ... bash -c '...;exit 0'또는xargs ... bash -c '... || echo erk'
Samveen

참고 parallel -j 1가능한 해킹 솔루션입니다.
barrycarter

답변:


25

아냐, 못해 xargssavannah.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 procs와 관련이있는 것 같습니다. 이것이 의미가 있다고 생각합니다 .max procs를 충분히 높게 설정하면 한계에 도달 할 때까지 확인하지 않아도됩니다.

당신이하려는 일에 대한 더 나은 해결책은 GNU Make 를 사용하는 것일 수 있습니다 .

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

all: $(TARGETS)

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

그때:

$ make -k -j4 

동일한 효과가 있으며 훨씬 더 나은 제어 기능을 제공합니다.


9

그것은 가장 명백한 구어체 중 하나가 다른 제안에 의해서만 언급되는 것처럼 보일 것입니다.

즉, 다음을 사용할 수 있습니다.

bash -c '$PROG_WHICH_MAY_FAIL ; (true)'

"성공을 강요"하기 위해.

이것은 lornix 가 제안한 내용을 따르고 있습니다.

어쨌든 이것은 실제 프로세스 종료 상태를 효과적으로 무시하기 때문에 사후 분석을 위해 하위 프로세스 상태를 어떻게 저장하는지 고려해야합니다. 예 :

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(여기서는 fnord) 을 지정해야합니다 seq.


2

죽어가는 프로그램의 신호를 '먹는'다른 명령을 넣으십시오.

나는 문제를 증명하기 위해 처음에 당신의 예제를 시도했습니다 ... 'killall sleep'은 수면 프로세스를 죽이고 bash를 중단하고 xargs는 종료됩니다.

테스트로, xargs와 bash 사이에 'Run another command'유형 명령을 사용했습니다 ...이 경우 '/ usr / bin / time'. 이번에는 (말장난 없음) killall sleep이 절전 프로세스를 종료하지만 xargs는 계속 진행됩니다.

시간 출력을 / dev / null로 파이프하면 기존 프로세스를 크게 다시 작성하지 않고도 원하는 결과를 정확하게 얻을 수 있습니다.

나는 잠시 동안 숙고하면 '/ usr / bin / time'에서 stderr chatter없이 동일한 작업을 수행 할 수있는 다른 프로그램을 생각해 낼 수 있다고 생각합니다. 또는 직접 작성해도 '포크'(또는 exec () 파생물) 일뿐입니다.

bash의 내장 '시간'이 신호의 동일한 '먹음'을 수행하는지 확실하지 않으므로 '/ usr / bin / time'을 사용하십시오.


1
time이 목적 을 수행하는 좋은 대안 env은 실행되는 프로그램 환경에 0 개 이상의 선택적 변수를 추가하는 것뿐입니다. 자체 출력을 생성하지 않으며 호출 된 프로그램의 리턴 코드는 호출 된 모든 것에 다시 전달됩니다 env.
James Sneeringer

{Chuckle}이 글을 쓴 후 잠시 생각했습니다. "무엇을 실행"명령으로 생각한 것은 시간이 처음이었습니다. 그래도 잘 작동합니다. 축하하고 고마워
lornix

2

나는 나를 위해 일 하지도 time않았고 env(자녀 프로그램의 반환 가치를 전달 하지 않음 ) 나는 썼다 bliss.

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

그때 chmod u+x ~/bliss

그리고 같은 find_or_similar | xargs ~/bliss fatally_dying_program.sh

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.