Doppelstart in Python verhindern (verbesserte Version)

Zuvor habe ich eine Version nur mit der Sperrdatei geschrieben, diese war jedoch unbeliebt (?). Daher habe ich eine Version mit der PID-Datei erstellt. Es ist einfach zu bedienen, da es als Dekorateur definiert ist. Gehen Sie einfach wie folgt vor:

@singleprocess
def main();
    pass

Die Operation ist wie folgt.

  1. Schreiben Sie die PID in die PID-Datei, bevor Sie den Hauptprozess starten. Löschen Sie die PID-Datei, wenn der Vorgang abgeschlossen ist.
  2. Wenn der in diese PID-Datei geschriebene PID-Prozess bereits dieselbe Signatur wie der eigene Prozess hat (er wird als dasselbe Programm erkannt), wird beurteilt, dass dasselbe Programm bereits ausgeführt und gestartet wird TU es nicht.
  3. Verwenden Sie als Signatur für die Beurteilung der Identität des Prozesses den Teil der Befehlszeile, in dem der Verzeichnisname vom ersten Parameter (Python) und vom zweiten Parameter (Python-Dateiname) ausgeschlossen ist.
  4. Allein hier gibt es ein Problem mit der Konsistenz, wenn sich der Zeitpunkt des Lesens und Schreibens der PID-Datei überschneidet, sodass beim Lesen und Schreiben der PID-Datei ein Sperrmechanismus enthalten ist. Es verwendet eine normale Herde.
  5. Wenn die PID-Datei beim Lesen oder Schreiben abnormal beendet wird, wird sie möglicherweise erst gestartet, wenn die PID-Datei manuell gelöscht wurde. Sie ist jedoch nicht von der abnormalen Beendigung des Hauptprozesses betroffen. Ein abnormales Beenden beim Lesen und Schreiben der PID-Datei tritt nicht so häufig auf, sodass dies in der Praxis kein Problem darstellt.

Die PID-Datei wird unter / tmp abgelegt, und die Sicherheit wird nicht berücksichtigt. Um es in der Produktion verwenden zu können, müssen der getSignature-Algorithmus und der Speicherort der PID-Datei je nach Anwendung möglicherweise geändert werden.

def singleprocess(func):
    def basenameWithoutExt(path):
        return os.path.splitext(os.path.basename(path))[0]

    def getSignature(pid):
        processDirectory = '/proc/%d/' % (pid,)
        if os.path.isdir(processDirectory):
            args = open(processDirectory + 'cmdline').read().split("\x00")
            return [os.path.basename(args[0]), os.path.basename(args[1])]
        return None

    @contextmanager
    def filelockingcontext(path):
        open(path, "a").close() #ensure file to exist for locking
        with open(path) as lockFd:
            fcntl.flock(lockFd, fcntl.LOCK_EX)
            yield
            fcntl.flock(lockFd, fcntl.LOCK_UN)

    def wrapper(*args, **kwargs):
        pidFilePath = tempfile.gettempdir() + '/' + basenameWithoutExt(sys.argv[0]) + '.pid'
        with filelockingcontext(pidFilePath):
            runningPid = ""
            with open(pidFilePath) as readFd:
                runningPid = readFd.read()
            if runningPid != "" and getSignature(int(runningPid)) == getSignature(os.getpid()) is not None:
                print("process already exists", file=sys.stderr)
                exit()
            with open(pidFilePath, "w") as writeFd:
                writeFd.write(str(os.getpid()))
        try:
            func(*args, **kwargs)
        finally:
            with filelockingcontext(pidFilePath):
                os.remove(pidFilePath)
    return wrapper

Recommended Posts

Doppelstart in Python verhindern (verbesserte Version)
Verhindern Sie den doppelten Start von cron in Python
Verhindern Sie den doppelten Start des Befehls django
Python-Start
So überprüfen Sie die Version von opencv mit Python
Starten Sie eine Flask-App in Python Anywhere
Doppelte Pendelbewegungsgleichung in Python
Quadtree in Python --2
CURL in Python
Metaprogrammierung mit Python
Python 3.3 mit Anaconda
Geokodierung in Python
SendKeys in Python
Setzen Sie Python xgboost in max osx (llvm Version)
Metaanalyse in Python
Unittest in Python
Zwietracht in Python
DCI in Python
Quicksort in Python
nCr in Python
N-Gramm in Python
Programmieren mit Python
Plink in Python
[Verbesserte Version] Skript zur Überwachung der CPU mit Python
Konstante in Python
FizzBuzz in Python
SQLite in Python
Schritt AIC in Python
LINE-Bot [0] in Python
CSV in Python
Reverse Assembler mit Python
Reflexion in Python
PYTHON2.7 64-Bit-Version
Konstante in Python
nCr in Python.
Format in Python
Scons in Python 3
Puyopuyo in Python
Python in Virtualenv
PPAP in Python
Quad-Tree in Python
Reflexion in Python
Chemie mit Python
Hashbar in Python
DirectLiNGAM in Python
LiNGAM in Python
In Python reduzieren
In Python flach drücken
"Lineare Regression" und "Probabilistische Version der linearen Regression" in Python "Bayes lineare Regression"
Web Scraping für Anfänger in Python (1) Verbesserte Version
[Internal_math version (2)] Dekodieren der AtCoder Library ~ Implementierung in Python ~
Sortierte Liste in Python
Täglicher AtCoder # 36 mit Python
Clustertext in Python
AtCoder # 2 jeden Tag mit Python
Täglicher AtCoder # 32 in Python
Täglicher AtCoder # 6 in Python
Bearbeiten Sie Schriftarten in Python