5

複数のコアをより有効に活用するために、複数の Python スクリプトを並行して呼び出す Bash スクリプト (Bash 3.2、Mac OS X 10.8) があります。各 Python スクリプトは、完了するまでに非常に長い時間がかかります。

問題は、Bash スクリプトの途中で Ctrl+C を押しても、Python スクリプトが実際には強制終了されないことです。Bash スクリプトを強制終了すると、バックグラウンドのすべての子も強制終了されるように、Bash スクリプトを作成するにはどうすればよいですか?

これが私の元の「縮小テストケース」です。残念ながら、私はそれを大幅に減らしたようで、もはや問題を示していません。私の間違い。

set -e

cat >work.py <<EOF
import sys, time
for i in range(10):
    time.sleep(1)
    print "Tick from", sys.argv[1]
EOF

function process {
    python ./work.py $1 &
}

process one
process two
wait

これは完全なテスト ケースですが、まだ大幅に削減されていますが、これで問題が実証されることを願っています。それは私のマシンで再現されます... しかし、2 日前に古いテスト ケースが私のマシンで再現されると思っていましたが、今日は間違いなくそうではありません。

#!/bin/bash -e
set -x

cat >work.sh <<EOF
for i in 0 1 2 3 4 5 6 7 8 9; do
    sleep 1; echo "still going"
done
EOF
chmod +x work.sh

function kill_all_jobs { jobs -p | xargs kill; }
trap kill_all_jobs SIGINT

function process {
    ./work.sh $1
}

process one &
wait $!
echo "All done!"

still goingこのコードは、Ctrl+C の後でも引き続き出力されます。しかし、&を外側processから内側 (つまり: ./work.sh $1 &) に移動すると、Ctrl+C が期待どおりに機能します。これが全然わからない!

私の実際のスクリプトにprocessは複数のコマンドが含まれており、コマンドは長時間実行され、順番に実行する必要があります。&その場合、「内側を移動」する方法がわかりませんprocess。それは可能だと確信していますが、それは自明ではありません。

$ bash --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin12)
Copyright (C) 2007 Free Software Foundation, Inc.

編集:Bashのことを教えてくれた@AlanCurryに感謝します。残念ながら、私の例で何が起こっているのかまだ正確には理解できていませんが、実際には議論の余地があります. make -j3!を使用したメイクファイル make可能な場合は並行して実行し、Ctrl+C も完全に理解します。問題は解決しました(質問には回答されていませんが)。

4

2 に答える 2

1

あなたtrapは私に似合います:

$ bash --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin11)
Copyright (C) 2007 Free Software Foundation, Inc.

$ cat ./thang 
#! /bin/bash
set -e

cat >work.py <<EOF
import sys, time
for i in range(10):
  time.sleep(1)
  print "Tick from", sys.argv[1]
EOF

function process {
  python ./work.py $1 &
}

function killstuff {
  jobs -p | xargs kill
}

trap killstuff SIGINT

process one
process two
wait

$ ./thang 
Tick from one
Tick from two
Tick from one
Tick from two
^C$ ps aux | grep python | grep -v grep
$
于 2012-07-28T02:41:35.640 に答える
1

わかった!あなたがしなければならないことは、その python SIGINT ハンドラを取り除くことだけです。

cat >work.py <<'EOF'
import sys, time, signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
for i in range(10):
    time.sleep(1)
    print "Tick from", sys.argv[1]
EOF 
chmod +x work.py

function process {
    python ./work.py $1
}

process one &
wait $!
echo "All done!"
于 2012-07-29T18:43:08.650 に答える