6

私はPython 2.7スクリプトを書いています。
要約すると、このスクリプトは毎晩実行されLinux、いくつかのプロセスをアクティブにします。

このスクリプトが複数回並行して実行されないようにしたいと思います (基本的には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()

4

2 に答える 2

5

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、ロックは解除されたままです。

ただし、注意点があります。プロセスの実行中にロック ファイルのリンクを解除すると、プロセスの次のインスタンスが実行されたときに、ロックを持たない新しいファイルが作成され、問題なく実行されます。シングルトンデザイン。リンク解除を防ぐためにディレクトリで何か賢いことができるかもしれませんが、それがどれほど堅牢かはわかりません。

于 2013-11-03T12:32:34.933 に答える
1

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

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

cron に、「supervisorctl start myscript」というコマンドを入れました。これは、myscript が既にスーパーバイザーの下で実行されている場合は何もせず、それ以外の場合は起動します。

スクリプトが書かれている言語に関係なく、完全に機能します。

于 2013-11-03T12:44:19.753 に答える