我有一个可以永远运行的 python 脚本,但我想每天重新启动它,以防它陷入不良状态、关闭等。我每天都用任务计划程序来安排它,这样很好。
问题是我的脚本生成了其他进程,而当任务停止时(例如,当我手动结束任务或运行任务的新实例时),这些子进程不会被终止。主脚本被终止,但子进程没有被终止。我必须通过任务管理器手动终止它们。如果我在命令行上运行主脚本,而不是通过任务调度程序,则关闭控制台会终止所有子进程,正如预期的那样。
我尝试过使用和不使用“最高权限”来运行任务,“如果任务未按要求结束,则强制停止”,“如果任务已在运行,则停止现有实例”等。我尝试过将 taskkill 作为任务的第一个操作运行。我尝试过所有能想到的方法。我以自己的身份运行任务,我是管理员。
问题似乎是任务产生的子进程受到访问保护。我尝试过 taskkill、pskill、python 脚本,如下所示:
import psutil
for process in psutil.process_iter():
cmdline = process.cmdline()
if "myscript.py" in cmdline:
process.terminate()
我总是收到拒绝访问错误。taskkill 的示例:
c:\>taskkill /f /t /im python.exe
ERROR: The process with PID 14436 (child process of PID 7928) could not be terminated.
Reason: Access is denied.
ERROR: The process with PID 7928 (child process of PID 14324) could not be terminated.
Reason: Access is denied.
...
天哪,我甚至尝试让我的主 Python 脚本在终止事件发生时终止其自己的子进程,但无论是否强制终止,我甚至都没有通过任务调度程序获得该事件!同样,在正常的命令行运行中,我得到了预期的终止事件。但再次被任务调度程序阻止了。
这也很容易通过运行 Python 脚本的一行批处理文件来重现。如果任务计划程序运行批处理文件,并且您结束任务,则任务结束时 Python 脚本不会被终止。
知道为什么任务调度程序任务产生的子进程不会被终止以及如何解决这个问题吗?
谢谢!
答案1
如果你可以编辑 python 脚本本身,也许你可以:
- 将其设置为检查信号(例如让调度程序创建一个名为 signal.txt 的文件),如果存在,则删除它并终止进程本身(即永远运行的脚本将具有“Medea”功能,可在自杀前杀死所有孩子)
- 将启动的进程分配给一个作业(参见在 stackoverflow 上回答作者:Nathaniel J. Smith)
- 为每个进程创建一个 23.9 小时的计时器(类似于这个其他的stackoverflow)因此确保它们在调度程序重新启动它们之前“死亡”......
希望能帮助到你...