9

別のスレッドで起動されたサブプロセスを強制終了するときに、通信パイプをシャットダウンすることは可能でしょうか。communicate() を呼び出さない場合、kill() は期待どおりに機能し、5 秒ではなく 1 秒後にプロセスが終了します。

ここで同様の問題に関する議論を見つけましたが、本当の答えは得られませんでした。パイプを閉じるか、サブサブプロセス (この例では「スリープ」) を明示的に強制終了し、それを強制終了してパイプのブロックを解除できる必要があると思います。

私も SO で彼女の答えを見つけようとしましたが、私が知る限り、この問題に直接対処していないthisthisthisしか見つかりませんでした (?)。

したがって、私がやりたいことは、2 番目のスレッドでコマンドを実行してすべての出力を取得できるようにすることですが、必要なときにすぐに強制終了できるようにすることです。私はファイルを経由してそれを尾行することもできますが、これを行うためのより良い方法があるはずだと思いますか?

import subprocess, time
from threading import Thread

process = None

def executeCommand(command, runCommand):
    Thread(target=runCommand, args=(command,)).start()

def runCommand(command):
    global process
    args = command.strip().split()
    process = subprocess.Popen(args, shell=False, stdout=subprocess.PIPE)

    for line in process.communicate():
        if line:
            print "process:", line,

if __name__ == '__main__':
    executeCommand("./ascript.sh", runCommand)
    time.sleep(1)
    process.kill()

これはスクリプトです:

#!/bin/bash
echo "sleeping five"
sleep 5
echo "slept five"

出力

$ time python poc.py 
process: sleeping five

real    0m5.053s
user    0m0.044s
sys 0m0.000s
4

3 に答える 3

6

問題は、process.kill() が直接の子プロセス (bash) のみを強制終了し、bash スクリプトのサブプロセスを強制終了しないことだと思います。

問題と解決策は次のとおりです。

Popen(..., preexec_fn=os.setsid) を使用してプロセス グループを作成し、os.pgkill を使用してプロセス グループ全体を強制終了します。例えば

import os
import signal
import subprocess
import time
from threading import Thread

process = None

def executeCommand(command, runCommand):
    Thread(target=runCommand, args=(command,)).start()

def runCommand(command):
    global process
    args = command.strip().split()
    process = subprocess.Popen(
        args, shell=False, stdout=subprocess.PIPE, preexec_fn=os.setsid)

    for line in process.communicate():
        if line:
            print "process:", line,

if __name__ == '__main__':
    executeCommand("./ascript.sh", runCommand)
    time.sleep(1)
    os.killpg(process.pid, signal.SIGKILL)

$ time python poc.py 
process: sleeping five

real    0m1.051s
user    0m0.032s
sys 0m0.020s
于 2011-09-13T04:38:41.967 に答える
0

これを実行してマルチスレッドの問題を回避する最も簡単な方法は、メインスレッドからキルフラグを設定し、通信の直前にスクリプト実行スレッドでそれをチェックし、フラグがオンになったときにスクリプトを強制終了することです。True.

于 2009-10-26T16:51:38.187 に答える
-1

あなたは、Python の超粗粒度同時実行性の犠牲になっているようです。スクリプトを次のように変更します。

#!/bin/bash
echo "sleeping five"
sleep 5
echo "sleeping five again"
sleep 5
echo "slept five"

そして、出力は次のようになります。

process: sleeping five

real    0m5.134s
user    0m0.000s
sys     0m0.010s

スクリプト全体が実行された場合、時間は 10 秒になります。そのため、bash スクリプトがスリープ状態になるまで、Python 制御スレッドは実際には実行されないようです。同様に、スクリプトを次のように変更した場合:

#!/bin/bash
echo "sleeping five"
sleep 1
sleep 1
sleep 1
sleep 1
sleep 1
echo "slept five"

出力は次のようになります。

process: sleeping five

real    0m1.150s
user    0m0.010s
sys     0m0.020s

つまり、コードは論理的に実装されたものとして機能します。:)

于 2009-10-26T15:30:54.683 に答える