2016-03-26 23 views
1

私はバックグラウンドでPythonスクリプトを実行するスクリプトランチャー(bash)を持っているので、起動してからターミナル/ ssh接続を閉じることができます。バックグラウンドプロセスがLinux上で作業を完了した後のクリーンアップ

実行するスクリプトの名前とそこに渡すオプションの引数を受け入れます。次に、Pythonスクリプト(デタッチ)を起動し、同じディレクトリにPID(Pythonスクリプトのファイル)を作成します。このファイルからPIDを使用して、後でサーバーに再接続してこのバックグラウンドプロセスを終了させることができます。

また、このPIDファイルは、すでに実行されている(シングルトン)場合に同じスクリプトが開始されないようにするために使用されます。

問題は、Pythonスクリプトが作業を終えた後、このPIDファイルを削除する方法がわかりません。私はこれをbashスクリプト、Pythonソリューション(すべての場合に使用したいので)、またはのスクリーンツールで実装する必要があります。このスーパーバイザ(スクリプト終了後にPIDファイルを削除する)もバックグラウンドで実行する必要があります(!)ので、私は同じことをすることができます:ターミナルセッションを閉じます。

#!/bin/bash 

PIDFILE=$1.pid 

if [ -f $PIDFILE ]; then 
    echo "Process is already running, PID: $(< $PIDFILE)" 
    exit 1 
else 
    nohup python $1 "${@:2}" > /dev/null 2>&1 & 
    PID=$! 
    echo $PID > $PIDFILE 
    # supervisor 
    nohup sh -c "wait $PID; rm -f $PIDFILE" > /dev/null 2>&1 & 
fi 

この例ではPIDファイルがすぐに削除され、はすぐコマンド戻りを待つ(私は新しいプロセスはの子ではないからだと思うので、私がこれまで試したどのような

現在のものなので、待ちは私の予想どおりこの場合は機能しません)。

どのように実装することができますか? は基本的に、私はその作業を終了します(この場合はPythonの)前のスクリプトまで待ち、その後、PIDファイルを削除します。このライン

nohup sh -c "wait $PID; rm -f $PIDFILE" > /dev/null 2>&1 & 

に置き換えるために何かを必要としています。

UPD:問題はであり、子プロセス以外のプロセスを待つことができないため、コマンドを待機しています。 、シェルスクリプトの場合

#!/bin/bash 

function cleanup { 
    while [ -e /proc/$1 ]; do 
     sleep 1; 
    done 
    rm -f $PIDFILE 
} 

PIDFILE=$1.pid 

if [ -f $PIDFILE ]; then 
    echo "Process is already running, PID: $(< $PIDFILE)" 
    exit 1 
else 
    python $1 "${@:2}" > /dev/null 2>&1 & 
    PID=$! 
    echo $PID > $PIDFILE 
    cleanup $PID > /dev/null 2>&1 & 
    disown 
fi 

答えて

1

traps使用します:

#!/bin/bash 
function finish { 
    wait $PID 
    rm $PIDFILE > /dev/null 2>&1 & 
} 

trap finish   EXIT 
trap "exit 2; finish" SIGINT 

PIDFILE=$1.pid 

if [ -f $PIDFILE ]; then 
    echo "Process is already running, PID: $(< $PIDFILE)" 
    exit 1 
else 
    nohup python $1 "${@:2}" > /dev/null 2>&1 & 
    PID=$! 
    echo $PID > $PIDFILE 
fi 

トラップはあなたがsignalsをキャッチし、上記のコードではので、それらに対応できるようにする作業溶液は、 whileループでそれを置き換えることですEXITシグナル(正常終了)は、$PIDFILEを除去して終了を実行します。 SIGINT(Ctrl-Cを持つユーザ要求の出口)には、スクリプトはPythonで直接2.

$PIDFILEして終了を削除します:あなたはそれを手動でatexitを見て処理したい場合。私は、ソースを見ていないが、それはクリーンアップ機能を登録するためにtrapsを実装ように見えます:

import atexit 
import os 


def cleanup(): 
    os.unlink(pidfile) 


atexit.register(cleanup) 

またはすべて独自に同時実行を防止し処理するどのチェックアウトpidを扱うpidファイルを自動化する:

from pid import PidFile 

with PidFile(): 
    do_something() 

またはいっそ

from pid.decorator import pidfile 

@pidfile() 
def main(): 
    pass 

if __name__ == "__main__": 
    main() 
+0

このソリューションは、Pythonにロックされているが、私だけでなく、Pythonスクリプトを実行しますので、私は何かイムを必要としますBashで実装された –

+0

ああ、謝罪、一瞬。 – bschlueter

+0

このコードの問題は、Pythonスクリプトが作業を終了するまでブロックされることです。このスーパーバイザーはバックグラウンドでも作業する必要があるので、このスクリプトランチャーはすぐに作業を終了する必要があります(Pythonスクリプトの起動、スーパーバイザーの起動、終了)。 –

関連する問題