2013-11-03 10 views
6

私はPython 2.7スクリプトを書いています。
要約すると、このスクリプトは毎晩Linuxで実行され、いくつかのプロセスをアクティブにします。python - スクリプトが一度だけ有効になるようにする

私は、このスクリプトが複数回並列に実行されないようにしたいと考えています(基本的にはSingletonパターンを模倣しようとしていますが、アプリケーションレベルで)。

コード例

def main(): 
    # before doing anything, I'd like to know whether this 
    # script was activated and alive. 
    # if so, error out 

    # do something 

if __name__ == "__main__": 
    main() 

提案

素朴な解決策は、ミューテックスとして動作するロックファイルのいくつかの種類を作成することです。
最初に行うことは、このファイルが存在するかどうかを確認することです。もしそうであれば、スクリプトの他のインスタンスがすでにそれを作成しており、エラーが発生するはずです。スクリプトが終了したら、このファイルを削除します。
ファイルシステム上の操作がアトミックである限り、この解決策が動作すると仮定しています。

実装

import os, sys 

lock_file_path = ".lock_script" 

def lock_mutex(): 
    if os.path.exists(lock_mutex_path): 
     print "Error: script was already activated." 
     sys.exit(-1) 

    else: 
     file = open(lock_mutex_path, 'w') 

def unlock_mutex(): 
    assert(os.path.exists(lock_mutex_path)) 
    os.remove(lock_mutex_path) 

def main(): 

    try: 
     lock_mutex() 

     # do something 

     unlock_mutex() 

    except: 
     unlock_mutex() 

if __name__ == "__main__": 
    main() 

lock_mutex()unlock_mutex()を確保するためにどのように問題

アトミックですか?

+0

既に正しく動作している場合は、スクリプトを起動したくないですか? – Artur

+0

好奇心の渦中に、これが心配であるようにスクリプトがどのように開始されましたか? – ratatoskr

+2

あなたのソリューションは* naive *ソリューションではないと思います。実際、スクリプトが実行されているかどうかを確認するためにロックファイルを作成するのは非常に一般的です。 – aIKid

答えて

1

私はスーパーバイザ(http://supervisord.org/)を使用してLinuxで動作させています。 Django、Celerydなどを実行し、予期せず終了した場合に再起動されます。

しかし、コマンドが終了したときに自動的に開始または再起動されないようにオプションを設定することもできます(autostart = false、autorestart = false、starseconds = 0)。私はこれらのcronジョブのために使用します。

cronには、 "supervisorctl start myscript"というコマンドがあります。これは、myscriptが既にスーパーバイザで実行されている場合は何もせず、そうでない場合は起動します。

スクリプトが記述されている言語に関係なく、完全に動作します。

3

Linuxを使っているので、あなたがflockを利用することができます:

import os 
import fcntl 
import time 

def main(): 
    # acquire the prog lock 
    if not prog_lock_acq('singleton.lock'): 
    print("another instance is running") 
    exit(1) 

    print("program is running-press Ctrl+C to stop") 
    while True: 
    time.sleep(10) 

def prog_lock_acq(lpath): 
    fd = None 
    try: 
    fd = os.open(lpath, os.O_CREAT) 
    fcntl.flock(fd, fcntl.LOCK_NB | fcntl.LOCK_EX) 
    return True 
    except (OSError, IOError): 
    if fd: os.close(fd) 
    return False 

if __name__ == '__main__': 
    main() 

プロセスが終了したとき、それは自動的になりますので、我々はprog_lock_acqを終了した後、開いているファイルを残したということを問題ではありません。 OSによって閉じられる。また、LOCK_NBオプションを省略すると、flockコールは、現在の実行中のプロセスが終了するまでブロックされます。あなたのユースケースに応じて、それは役に立つかもしれません。

終了時にファイルを削除していないことに注意してください。それは問題ではありません。ファイルが存在しても、ロックされているライブプロセスは表示されません。したがって、kill -9でプロセスを終了しても、ロックは引き続き解放されます。

警告があります:プロセスの実行中にロックファイルのリンクを解除すると、プロセスの次のインスタンスが実行されると、ロックされていない新しいファイルが作成され、正常に実行されます私たちのシングルトンデザインに違反するでしょう。あなたはリンクを解除するためにディレクトリで巧妙な何かをすることができるかもしれませんが、私はどれくらい頑強なのかは分かりません。

関連する問題