2013-11-03 2 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

귀하의 솔루션이 단순한 솔루션이라고 생각하지 않습니다. 실제로 스크립트가 실행 중인지 확인하기 위해 잠금 파일을 만드는 것이 일반적입니다. – aIKid

답변

1

관리자 (http://supervisord.org/)를 사용하여 Linux에서 작업을 수행합니다. Django, Celeryd 등을 실행하고 예기치 않게 종료 될 경우 다시 시작되도록합니다.

그러나 명령이 완료 될 때 자동으로 시작되거나 다시 시작되지 않도록 옵션을 설정할 수도 있습니다 (autostart = false, autorestart = false, starseconds = 0). 나는이 크론 작업에 이것을 사용합니다.

cron에서 myscript가 이미 관리자 아래에서 실행중인 경우 아무 작업도 수행하지 않고 "supervisorctl start myscript"명령을 입력하고 그렇지 않으면 시작합니다.

스크립트가 작성된 언어에 관계없이 완벽하게 작동합니다.

3

, 당신은 flock의 사용을 할 수 있습니다 : 우리가 prog_lock_acq을 종료 한 후 열려있는 파일을 떠났다 중요하지 않습니다

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() 

프로세스 종료, 그것은 자동으로시기 때문에 운영 체제에 의해 닫힙니다. 또한 LOCK_NB 옵션을 생략하면 flock 호출은 현재 실행중인 프로세스가 종료 될 때까지 차단됩니다. 유스 케이스에 따라 유용 할 수 있습니다.

종료 할 때 파일을 삭제하지 않습니다. 그건 중요하지 않아. 파일의 존재가 라이브 프로세스를 나타내지는 않습니다. 따라서 kill -9으로 프로세스를 종료하더라도 잠금은 계속 해제됩니다.

그러나 경고 메시지가 있습니다. 프로세스가 실행 중일 때 잠금 파일의 연결을 해제하면 프로세스의 다음 인스턴스가 실행될 때 잠금 파일이없는 새 파일이 생성되어 정상적으로 실행됩니다 우리 싱글 톤 디자인을 위반하게 될 것입니다. 연결 해제를 방지하기 위해 디렉터리를 사용하여 영리한 작업을 수행 할 수는 있지만 얼마나 견고한 지 확신 할 수 없습니다.