2017-08-22 8 views
6

क्योंक्यों subprocess.Popen returncode बैश के साथ इसी तरह आदेश के लिए अलग है

import subprocess 

p = subprocess.Popen(["/bin/bash", "-c", "timeout -s KILL 1 sleep 5 2>/dev/null"]) 
p.wait() 
print(p.returncode) 

रिटर्न

[stderr:] /bin/bash: line 1: 963663 Killed     timeout -s KILL 1 sleep 5 2> /dev/null 
[stdout:] 137 

जब

import subprocess 

p = subprocess.Popen(["/bin/bash", "-c", "timeout -s KILL 1 sleep 5"]) 
p.wait() 
print(p.returncode) 

रिटर्न

[stdout:] -9 

यदि आप डैश में बैश बदलते हैं, तो आपको दोनों मामलों में 137 मिलेंगे। मुझे पता है कि -9 किल कोड है और 137 128 + 9 है। लेकिन अलग-अलग रिटर्नकोड प्राप्त करने के लिए समान कोड के लिए अजीब लगता है।

अजगर 2.7.12 और अजगर 3.4.3

जब /bin/bash का उपयोग कर, लेकिन मैं बाहर क्यों समझ नहीं सकता Popen.wait() की तरह लग रहा Popen._handle_exitstatushttps://github.com/python/cpython/blob/3.4/Lib/subprocess.py#L1468 फोन नहीं करता है पर होता है।

+0

ऐसा लगता है कि 'टाइमआउट' लिनक्स विशिष्ट है, वैसे भी। मुझे ओएस एक्स पर 2.7.10 और 3.6.0 दोनों कोड संस्करणों के साथ 127 का रिटर्न कोड मिलता है। – cdarke

उत्तर

4

इस तथ्य को कैसे bash के साथ या बिना पुनर्निर्देशन/पाइप या किसी अन्य पार्टी सुविधाओं कार्यान्वित timeout की वजह से है:

  • पुनर्निर्देशन के साथ

    1. python शुरू होता है bash
    2. bash शुरू होता है timeout , प्रक्रिया की निगरानी करता है और पाइप हैंडलिंग करता है। एक नई प्रक्रिया समूह में
    3. timeout स्थानान्तरण ही है और शुरू होता है sleep
    4. एक सेकंड के बाद, timeout इसकी प्रक्रिया समूह
    5. के रूप में प्रक्रिया समूह timeout लिए इंतज़ार कर रहे, SIGKILL देखता है और प्रिंट से मृत्यु हो गई, bash रिटर्न में SIGKILL भेजता है संदेश stderr पर चिपकाया गया संदेश। इसके बाद यह 128 + 9 (timeout द्वारा अनुरूपित व्यवहार) पर अपनी निकास स्थिति सेट करता है।
  • पुनर्निर्देशन

    1. python शुरू होता है bash के बिना।
    2. bash देखता है कि इसके पास कुछ भी नहीं है और execve() पर प्रभावी रूप से timeout के साथ प्रभावी रूप से प्रतिस्थापित करने के लिए कॉल करता है।
    3. timeout उपरोक्त के रूप में कार्य करता है, संपूर्ण प्रक्रिया समूह SIGKILL के साथ मर जाता है।
    4. python प्राप्त 9 की एक निकास स्थिति है और (SIGKILL) में कुछ mangling इस चालू करने के लिए करता है

दूसरे शब्दों में, बिना पुनर्निर्देशन/पाइप/आदि। bash कॉल-चेन से खुद को वापस ले जाता है।आपका दूसरा उदाहरण subprocess.Popen() जैसा दिखता है bash निष्पादित कर रहा है, फिर भी प्रभावी रूप से यह नहीं करता है। bash अब नहीं है जब timeout इसका कार्य करता है, यही कारण है कि आपको कोई संदेश और अनमोल निकास स्थिति नहीं मिलती है।

यदि आप लगातार व्यवहार चाहते हैं, तो timeout --foreground का उपयोग करें; आपको दोनों मामलों में 124 का एक्जिट स्टेटस मिलेगा।

मुझे डैश के बारे में पता नहीं है; फिर भी मान लीजिए कि यह किसी भी execve() चालबाजी को प्रभावी ढंग से अपने द्वारा निष्पादित किए जाने वाले एकमात्र प्रोग्राम के साथ बदलने के लिए नहीं करता है। इसलिए आप हमेशा डैश में 128 + 9 की उलझन वाली निकास स्थिति देखते हैं।

अद्यतन: zsh, समान व्यवहार से पता चलता है, जबकि यह इस तरह timeout -s KILL 1 sleep 5 >/tmp/foo और पसंद के रूप में सरल पुनर्निर्देशन, आप -9 की एक निकास स्थिति देने के लिए भी बाहर चला जाता है। timeout -s KILL 1 sleep 5 && echo $? आपको zsh में भी स्थिति 137 देगा।

+0

क्षमा करें, लेकिन मुझे पूरी तरह से समझ में नहीं आता है। यदि पहले मामले में टाइमआउट वापसी 128 + 9 चरण 4 पायथन पर दूसरे मामले में क्यों 9 की निकास स्थिति प्राप्त होती है। चूंकि टाइमआउट 128 + 9 कोड के लिए ज़िम्मेदार है, तो क्या यह चरण 4 पर दूसरे मामले में नहीं लेना चाहिए? – Lehych

संबंधित मुद्दे