我正在运行一个python脚本,可能需要或可能不需要几个小时才能完成。
在我的python脚本的开头,我想检查这个python脚本是否已经运行。
如果它已经在运行,我想退出我刚刚开始的当前python。
例如:
python在凌晨1点开始运行直到凌晨3点 在凌晨2点开始另一个,却不知道它已经在运行。 我希望我的2AM python检查并退出,因为它已经在运行。
我怎么写这个python?
这是我试图锁定的内容..
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
答案 0 :(得分:2)
您可以尝试使用带有r
标志的lockfile-create命令重试指定的次数来捕获CalledProcessError
并退出,-p
标记将存储{ {1}}过程:
pid
运行带有上述代码的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
选项强>
-q, - quiet
取消任何输出。成功或失败仅由退出状态指示。
-v, - verbose
启用诊断输出。
-l, - lock-name
不要将.lock附加到文件名。此选项适用于lockfile-create,lockfile-remove,lockfile-touch或lockfile-check。
-p, - use-pid
每当创建一个锁文件时,将当前进程ID(PID)写入lockfile,并在检查锁的有效性时使用该pid。有关更多信息,请参见lockfile_create(3)联机帮助页。此选项适用于lockfile-create,lockfile-remove,lockfile-touch和lockfile-check。
-o,--oneshot
触摸锁定并立即退出。此选项适用于lockfile-touch和mail-touchlock。如果没有提供,这些命令将永远运行,每分钟触摸一次,直到被杀死。
-r retry-count, - retry retry-count
尝试在放弃之前锁定文件名重试次数。每次尝试都会比最后一次尝试延迟一点(以5秒为增量),直到重试之间达到最大延迟一分钟。如果未指定retry-count,则默认值为9,如果所有9次锁定尝试都失败,则会在180秒(3分钟)后放弃。
<强>描述强>
lockfile_create函数以NFS安全方式创建锁文件。
如果flags设置为L_PID,则lockfile_create不仅会检查现有的锁文件,还会读取内容以查看它是否包含ASCII中的进程ID。如果是,则锁定文件仅在该进程仍然存在时才有效。
如果lockfile位于共享文件系统上,则它可能是由远程主机上的进程创建的。因此,进程ID检查是无用的,不应设置L_PID标志。在这种情况下,没有好的方法来查看锁定文件是否过时。因此,如果锁定文件超过5分钟,它将被删除。这就是提供lockfile_touch函数的原因:在持有锁时,需要通过调用lockfile_touch()定期刷新(每分钟左右)。
lockfile_check函数检查是否已存在有效的锁文件而不尝试创建新的锁文件。
最后,lockfile_remove函数删除了锁文件。
用于以原子方式创建锁文件的算法,即使是通过NFS,也是如下:
1
创建一个唯一文件。在printf格式中,文件名是.lk%05d%x%s。第一个参数(%05d)是当前进程ID。第二个参数(%x)由time(2)返回的值的4个次要位组成。最后一个参数是系统主机名。
2
然后使用link(2)创建lockfile。链接的返回值被忽略。
3
现在锁文件是stat()ed。如果统计失败,我们转到第6步。
4
将lockfile的stat值与临时文件的stat值进行比较。如果它们是相同的,我们就有锁。删除临时文件,并将值0(成功)返回给调用者。
5
检查现有的锁文件是否有效。如果它无效,则删除陈旧的锁定文件。
6
在重试之前,我们睡了n秒钟。 n最初为5秒,但在每次重试后,额外增加5秒,最多为60秒(增量退避)。然后我们转到第2步重试次数。
在 redhat 上似乎有一个名为lockfile-progs的等效包。
在Mac上,您可以使用lockfile并执行以下操作:
$ python lock.py
lock.py is already running
4
在您的情况下,使用套接字可能会起作用:
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"])