2017-08-22 1 views
6

なぜsubprocess.Popenリターンコードがbashの

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 
と同様のコマンドについて異なる理由

bashをダッシュ​​に変更すると、どちらの場合も137になります。私は-9がKILLコードで137が128 + 9であることを知っています。しかし、同様のコードが異なる戻りコードを取得するのは変です。

/bin/bashを使用しているときPopen.wait()Popen._handle_exitstatushttps://github.com/python/cpython/blob/3.4/Lib/subprocess.py#L1468を呼び出すことはありませんが、私は理由を理解できなかったように見えるのPython 2.7.12とPythonに3.4.3

を発生します。

+0

「タイムアウト」のように見えるのは、Linux固有のものです。 OS Xの2.7.10と3.6.0の両方のコードバージョンで127のリターンコードを取得します。 – cdarke

答えて

4

これは、bashがリダイレクト/パイプまたは他のbashの機能の有無にかかわらずtimeoutをどのように実行するかという事実にある:

  • リダイレクションで

    1. python開始bash
    2. bash開始をtimeoutプロセスを監視し、パイプの取り扱いを行います。
    3. timeout新しいプロセスグループに転送自体を1秒後sleep
    4. を開始し、プロセスグループが死んだようtimeoutSIGKILLとプリント見て、timeoutを待ってから、そのプロセスグループ
    5. bash戻りSIGKILLを送信します上に貼り付けられたメッセージstderr。その後、自身の終了ステータスを128 + 9(timeoutによってシミュレートされた動作)に設定します。リダイレクトなし
    1. python開始bash
    2. bashは、それ自体が何もしておらず、execve()を呼び出すと、timeoutと効果的に置き換えられます。
    3. timeoutは上記のように動作し、プロセスグループ全体はSIGKILLで終了します。
    4. python GET 9の終了ステータスだとにこれを有効にするためにいくつかのマングリング(SIGKILL)つまり

を行い、リダイレクト/パイプの/ etcなし。 bashはそれ自体をコールチェーンから回収します。あなたの2番目の例はsubprocess.Popen()bashを実行しているように見えますが、それでも有効ではありません。 bashは、timeoutがその行為をしたときにもはやそこには存在しません。そのため、何のメッセージも得られず、終わりのない状態になっていません。

一貫した動作が必要な場合は、timeout --foregroundを使用します。どちらの場合でも終了ステータス124が表示されます。

ダッシュについては分かりません。それが実行している唯一のプログラムで効果的に置き換えることを躊躇しないとします。したがって、ダッシュで常に128 + 9の終了ステータスが表示されます。

更新zshそれはあなた-9の終了ステータスを与えて、でもシンプルなtimeout -s KILL 1 sleep 5 >/tmp/fooなどリダイレクションなどのために低下している間、同じ挙動を示しています。 timeout -s KILL 1 sleep 5 && echo $?は、zshにステータス137も表示します。

+0

申し訳ありませんが、私は完全に理解していません。最初のケースでタイムアウトが128 + 9を返すのなら、なぜステップ4の2番目のケースでは、Pythonは9の終了ステータスを取得します。タイムアウトは128 + 9コードを担当するものなので、ステップ4の2番目のケースでこのコードを渡すべきではありませんか? – Lehych

関連する問題