检查python脚本中正在运行的python脚本 [英] Checking running python script within the python script

查看:143
本文介绍了检查python脚本中正在运行的python脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在运行一个python脚本,它可能要花几个小时才能完成.

I am running a python script that may or may not take few hours to complete.

在我的python脚本的开头,我要检查此python脚本是否已在运行.

In the beginning of my python script, I want to check if this python script is already running or not.

如果它已经在运行,我想退出我刚启动的当前python.

If it is already running, I want to exit my current python that I just started.

例如:

python从1AM开始,一直运行到3AM 在凌晨2点启动了另一个,却不知道它已经在运行. 我想让我的2AM python检查并退出,因为它已经在运行.

python started 1AM and keeps on running until 3AM started another one at 2AM without knowing it is already running. I want my 2AM python to check and exit since it is already running.

如何编写此python?

How can I write this python?

这就是我试图锁定的东西.

This is what I tried for locking..

try:
    l = lock.lock("/home/auto.py", timeout=600) # wait at most 10 minutes

except error.LockHeld:
    e = sys.exc_info()[0]
    logging.error("Error: " + str(e) + " at main gatering Stats")
    smtpObj.sendmail(sender, receivers, message + "Error: " + str(e) + " at main gatering stats")
    exit("Fail: " + str(e) + " at main gathering Stats")
else:
    l.release()

所以我认为这将等待10分钟,如果它仍在运行,然后退出..如果它不再在运行,则运行当前的python

so I thought this will wait for 10 minutes if it is still running then exit.. if it is not running anymore, then run the current python

推荐答案

您可以尝试使用 lockfile-create 命令并带有r标志,以重试指定的次数以捕获CalledProcessError并退出,-p标志将存储进程的pid:

You can try using the lockfile-create command with the r flag to retry a specified amount of times catching a CalledProcessError and exiting, the -p flag will store the pid of the process :

import os
import sys
from time import sleep

from subprocess import check_call, CalledProcessError

try:
    check_call(["lockfile-create", "-q","-p", "-r", "0", "-l", "my.lock"])
except CalledProcessError as e:
    print("{} is already running".format(sys.argv[0]))
    print(e.returncode)
    exit(1)


# main body

for i in range(10):
    sleep(2)
    print(1)

check_call(["rm","-f","my.lock"])

在已运行上述代码的情况下运行test.py脚本会输出以下内容:

Running a test.py script with the code above while one is already running outputs the following:

$ python  lock.py 
lock.py is already running
4

选项

-q,--quiet

禁止任何输出.成功或失败仅由退出状态指示.

Suppress any output. Success or failure will only be indicated by the exit status.

-v,--verbose

启用诊断输出.

Enable diagnostic output.

-l,--lock-name

请勿将.lock附加到文件名中.此选项适用于创建锁文件,删除锁文件,触摸锁文件或检查锁文件.

Do not append .lock to the filename. This option applies to lockfile-create, lockfile-remove, lockfile-touch, or lockfile-check.

-p,--use-pid

每当创建锁文件时,将当前进程ID(PID)写到锁文件,并在检查锁的有效性时使用该pid.有关更多信息,请参见lockfile_create(3)联机帮助页.此选项适用于创建锁文件,删除锁文件,触摸锁文件和检查锁文件.

Write the current process id (PID) to the lockfile whenever a lockfile is created, and use that pid when checking a lock's validity. See the lockfile_create(3) manpage for more information. This option applies to lockfile-create, lockfile-remove, lockfile-touch, and lockfile-check.

-o,--oneshot

触摸锁并立即退出.此选项适用于lockfile-touch和mail-touchlock.如果不提供这些命令,它们将永远运行,每分钟触摸一次锁直到被杀死.

Touch the lock and exit immediately. This option applies to lockfile-touch and mail-touchlock. When not provided, these commands will run forever, touching the lock once every minute until killed.

-r重试计数,--retry重试计数

在放弃之前尝试锁定文件名重试计数时间.每次尝试将比上一次延迟更长的时间(以5秒为增量),直到重试之间的最大延迟达到一分钟.如果未指定retry-count,则默认值为9,如果9次锁定尝试均失败,它将在180秒(3分钟)后放弃.

Try to lock filename retry-count times before giving up. Each attempt will be delayed a bit longer than the last (in 5 second increments) until reaching a maximum delay of one minute between retries. If retry-count is unspecified, the default is 9 which will give up after 180 seconds (3 minutes) if all 9 lock attempts fail.

说明

lockfile_create函数以NFS安全的方式创建锁定文件.

The lockfile_create function creates a lockfile in an NFS safe way.

如果将标志设置为L_PID,则lockfile_create不仅将检查现有的锁定文件,还将读取内容,以查看其是否包含ASCII进程ID.如果是这样,则只有在该进程仍然存在的情况下,锁定文件才有效.

If flags is set to L_PID then lockfile_create will not only check for an existing lockfile, but it will read the contents as well to see if it contains a process id in ASCII. If so, the lockfile is only valid if that process still exists.

如果锁定文件位于共享文件系统上,则它可能是由远程主机上的进程创建的.因此,进程ID检查是无用的,并且不应设置L_PID标志.在这种情况下,没有好的方法来查看锁文件是否陈旧.因此,如果锁定文件的时间早于5分钟,它将被删除.这就是为什么提供lockfile_touch函数的原因:按住锁时,需要定期(每分钟左右)通过调用lockfile_touch()刷新它.

If the lockfile is on a shared filesystem, it might have been created by a process on a remote host. Thus the process-id checking is useless and the L_PID flag should not be set. In this case, there is no good way to see if a lockfile is stale. Therefore if the lockfile is older then 5 minutes, it will be removed. That is why the lockfile_touch function is provided: while holding the lock, it needs to be refreshed regularly (every minute or so) by calling lockfile_touch ().

lockfile_check函数检查是否已经存在有效的锁定文件,而无需尝试创建新的锁定文件.

The lockfile_check function checks if a valid lockfile is already present without trying to create a new lockfile.

最后,lockfile_remove函数将删除锁定文件.

Finally the lockfile_remove function removes the lockfile.

算法

即使在NFS上,也可以通过原子方式创建锁定文件的算法如下:

The algorithm that is used to create a lockfile in an atomic way, even over NFS, is as follows:

1

已创建唯一文件.以printf格式,文件名是.lk%05d%x%s.第一个参数(%05d)是当前进程ID.第二个参数(%x)由time(2)返回的值的4个次要位组成.最后一个参数是系统主机名.

A unique file is created. In printf format, the name of the file is .lk%05d%x%s. The first argument (%05d) is the current process id. The second argument (%x) consists of the 4 minor bits of the value returned by time(2). The last argument is the system hostname.

2

然后使用link(2)创建锁定文件.链接的返回值将被忽略.

Then the lockfile is created using link(2). The return value of link is ignored.

3

现在,锁定文件已启用stat().如果统计信息失败,请转到步骤6.

Now the lockfile is stat()ed. If the stat fails, we go to step 6.

4

将锁定文件的stat值与临时文件的stat值进行比较.如果它们相同,那么我们有锁.临时文件将被删除,并将0(成功)值返回给调用方.

The stat value of the lockfile is compared with that of the temporary file. If they are the same, we have the lock. The temporary file is deleted and a value of 0 (success) is returned to the caller.

5

进行检查以查看现有的锁定文件是否有效.如果无效,则会删除陈旧的锁定文件.

A check is made to see if the existing lockfile is a valid one. If it isn't valid, the stale lockfile is deleted.

6

在重试之前,我们会睡n秒钟. n最初为5秒,但每次重试后又增加了5秒,最长为60秒(增量退避).然后我们进入第2步,重试时间.

Before retrying, we sleep for n seconds. n is initially 5 seconds, but after every retry 5 extra seconds is added up to a maximum of 60 seconds (an incremental backoff). Then we go to step 2 up to retries times.

似乎有一个等效的软件包,叫做

There seems to be an equivalent package called lockfile-progs on redhat.

在Mac上,您可以使用 lockfile 并执行类似的操作:

On mac you could use lockfile and do something like:

import os
import sys
from time import sleep
import os
from subprocess import Popen, CalledProcessError, check_call


p = Popen(["lockfile", "-r", "0", "my.lock"])
p.wait()
if p.returncode == 0:
    with open("my.pid", "w") as f:
        f.write(str(os.getpid()))
else:
    try:
        with open("my.pid") as f:
            # see if process is still running or lockfile
            # is left over from previous run.
            r = f.read()
            check_call(["kill", "-0", "{}".format(r)])
    except CalledProcessError:
        # remove old lock file and create new
        check_call(["rm", "-f", "my.lock"])
        check_call(["lockfile", "-r", "0", "my.lock"])
        # update pid
        with open("my.pid", "w") as out:
            out.write(str(os.getpid()))
        print("Deleted stale lockfile.")
    else:
        print("{} is already running".format(sys.argv[0]))
        print(p.returncode)
        exit(1)
# main body

for i in range(10):
    sleep(1)
    print(1)
check_call(["rm", "-f", "my.lock"])

在您的情况下,使用套接字可能会起作用:

In your case maybe using a socket would work:

from socket import socket, gethostname, error, SO_REUSEADDR, SOL_SOCKET
from sys import argv
import  errno



sock = socket()

# Create a socket object
host = gethostname()  
# /proc/sys/net/ipv4/ip_local_port_range is  32768  61000 on my Ubuntu Machine
port = 60001  
# allow connection in TIME_WAIT
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)

try:
    sock.bind((host, port))
    sock.connect((host, port))
except error as e:
    # [Errno 99] Cannot assign requested address
    if e.errno == errno.EADDRNOTAVAIL:
        print("{} is already running".format(argv[0]))
        exit(1)
    # else raise the error
    else:
        raise e

# main body
from time import sleep

while True:
    print(1)
    sleep(2)

sock.close()

这篇关于检查python脚本中正在运行的python脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆