कैसे `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से किसी भी इनपुट को संसाधित करने से रोकने से रोक सकता हूं जब एक बच्चे की प्रक्रिया मर जाती है और इसके बजाय प्रसंस्करण जारी रहता है?


मैं xargsसंस्करण 4.4.2 का उपयोग कर रहा हूं debian wheezyऔर ऐसा लगता है कि अगर मैं किसी विशिष्ट sleepप्रक्रिया को मारता हूं तो भी हर चीज ठीक चलती है । आप किस संस्करण का xargsउपयोग कर रहे हैं? हो सकता है कि उन्होंने नवीनतम संस्करण में समस्या को ठीक कर दिया हो।
कन्नन मोहन

थोड़ी देर पार्टी में, लेकिन कैसे xargs ... bash -c '...;exit 0'या यहाँ तक किxargs ... bash -c '... || echo erk'
सैमवेन 14'17

ध्यान दें कि parallel -j 1एक संभव हैक समाधान है।
बैरीकेटर

जवाबों:


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;

उस चेक के चारों ओर या उस फ़ंक्शन के चारों ओर कोई ध्वज नहीं है जो उसे कॉल करता है। यह अधिकतम प्रोक्स से संबंधित प्रतीत होता है, जो मुझे लगता है कि समझ में आता है: यदि आप अधिकतम प्रोक्स को काफी ऊंचा सेट करते हैं, तो यह सीमा तक हिट होने तक परेशान नहीं करेगा, जो आपको कभी नहीं मिल सकता है।

जीएनयू मेक का उपयोग करने के लिए आप क्या करने की कोशिश कर रहे हैं, इसके लिए एक बेहतर समाधान :

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)'

"बल सफलता" के लिए।

ध्यान दें, यह प्रलोभन द्वारा प्रस्ताव की लाइनों के साथ है (बस इतने सारे शब्दों में नहीं)।

वैसे भी, चूंकि यह प्रभावी रूप से वास्तविक प्रक्रिया निकास स्थिति की अनदेखी कर रहा है, इसलिए मुझे यकीन है कि आप किसी भी तरह पोस्टमार्टम विश्लेषण के लिए उप-प्रक्रिया की स्थिति को बचाने पर विचार करेंगे। उदाहरण के लिए:

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

trueयहाँ कुछ हद तक निरर्थक है और इसलिए यह बेहतर रूप में लिखा जा सकता है:

bash -c '$PROG_WHICH_MAY_FAIL || touch failed'

चूंकि हम शायद यह जानना चाहते हैं कि 'असफल' फाइल को कब छुआ जा सकता है। दूसरे शब्दों में, हम अब विफलता को अनदेखा नहीं कर रहे हैं, हम ध्यान दे रहे हैं और जारी रख रहे हैं।

और, इस मुद्दे की पुनरावर्ती प्रकृति पर विचार करने के बाद, शायद हम ठीक से देखते हैं कि क्यों xargs उपेक्षा को आसान नहीं बनाते हैं। क्योंकि यह कभी भी एक अच्छा विचार नहीं है - आपको उस प्रक्रिया में त्रुटि को बढ़ाना चाहिए जो आप इसके बजाय विकसित कर रहे हैं। मेरा मानना ​​है कि यह धारणा, "यूनिक्स दर्शन" में ही निहित है।

अंत में, मुझे लगता है कि यह भी जेम्स यंगमैन की सिफारिश के अनुसार है trap, जो संभवतः एक समान तरीके से इस्तेमाल किया जा सकता है। यही है, समस्या को नजरअंदाज न करें ... इसे फँसाएँ और इसे सँभालें या आप एक दिन जाग जाएँ और पाएँ कि कोई भी उप-कार्यक्रम सफल नहीं हुआ; ;-)


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

मरने के कार्यक्रम से संकेत को 'खाने' के लिए एक और कमांड रखो।

मैंने आपके उदाहरण को आज़माया, जैसा कि समस्या को साबित करने के लिए सामान्य रूप से दिखाया गया है ... 'किंडल स्लीप' नींद की प्रक्रिया को मारता है, बैश को बाधित करता है, और ज़ार्ग क्विट करता है।

एक परीक्षण के रूप में, मैंने xargs और bash ... के बीच 'इस मामले में एक और कमांड' टाइप कमांड को चलाया। इस बार (कोई सज़ा नहीं), किल्लड स्लीप नींद की प्रक्रिया को मारता है, लेकिन एक्सगार्स जारी है।

आप समय के आउटपुट को / dev / null में पाइप करेंगे, और यह वही करेगा जो आप अपनी मौजूदा प्रक्रिया के प्रमुख पुनर्लेखन के बिना देख रहे हैं।

मुझे लगता है कि अगर मैं एक पल के लिए विचार करता हूं तो मैं '/ usr / बिन / समय' के स्टैडर चैटर के बिना एक और कार्यक्रम करने के लिए आ सकता हूं। या यहां तक ​​कि खुद को एक लिखें, यह सिर्फ एक 'कांटा' (या निष्पादन) (व्युत्पन्न) है।

याद रखें '/ usr / bin / time' का प्रयोग करें, क्योंकि मुझे यकीन नहीं है कि बैश से बिल्ट-इन 'time' सिग्नल का समान 'खा' करेगा।


1
timeइस उद्देश्य के लिए एक अच्छा विकल्प होगा env, क्योंकि यह सब चलता है कार्यक्रम के वातावरण में शून्य या अधिक वैकल्पिक चर जोड़ता है। यह अपने स्वयं के कोई आउटपुट का उत्सर्जन नहीं करता है, और आह्वान किए गए प्रोग्राम का रिटर्न कोड जो भी कहा जाता है, उसे वापस पारित किया जाएगा env
जेम्स स्नेनरिंग जूल

{चकली} मैंने इसे लिखने के कुछ समय बाद सोचा। समय पहली चीज़ थी जो "रन समथिंग" कमांड के रूप में ध्यान में आई। हालांकि अच्छी तरह से काम करता है। बधाई और धन्यवाद।
lornix

2

न तो timeहै और न ही envमुझे (वे अपने बच्चे कार्यक्रम की वापसी मान साथ भेज देते हैं) तो मैं ने लिखा है के लिए काम किया bliss:

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

फिर chmod u+x ~/bliss

और कुछ इस तरह find_or_similar | xargs ~/bliss fatally_dying_program.sh

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.