【问题标题】:How to correctly handle autorun start & stop on linux with python如何使用python正确处理Linux上的自动启动和停止
【发布时间】:2013-04-05 10:39:59
【问题描述】:

我有两个脚本:“autorun.py”和“main.py”。我将“autorun.py”作为服务添加到我的 linux 系统中的自动运行中。完美运行!

现在我的问题是:当我想从我的自动运行脚本启动“main.py”并且“main.py”将永远运行时,“autorun.py”也永远不会终止!所以当我这样做时

sudo service autorun-test start

命令也永远不会结束!

如何运行“main.py”然后退出,并完成它,当使用参数“stop”启动“autorun.py”时如何停止“main.py”? (这就是我认为所有其他服务的工作方式)

编辑:

解决方案:

if sys.argv[1] == "start":
    print "Starting..."
    with daemon.DaemonContext(working_directory="/home/pi/python"):
        execfile("main.py")
else:
    pid = int(open("/home/pi/python/main.pid").read())
    try:
        os.kill(pid, 9)
        print "Stopped!"
    except:
        print "No process with PID "+str(pid)

【问题讨论】:

  • 嗯,这不是我建议的设计。如果它有效,那很好。但是您不是在创建 pidfile 或 pid lockfile;您依赖main.py 在工作目录中;如果守护程序已经在运行并且您再次启动它,您将启动另一个副本;您的脚本在大多数平台上可能作为 initscript 无效,因此您仍然需要一个包装器(执行状态、在错误时返回非 0 等,以及具有适当的 chkconfig cmets)...

标签: python linux service autorun


【解决方案1】:

首先,如果你想创建一个系统守护进程,你几乎肯定想要关注PEP 3143,并且你几乎肯定想要使用daemon 模块来为你做这件事。

当我想从我的自动运行脚本启动“main.py”,而“main.py”将永远运行时,“autorun.py”也永远不会终止!

你没有说你是如何运行它的。如果您正在做的任何事情都会以孩子的身份启动 main.py 并等待(或者,更糟糕的是,在同一过程中尝试 import/execfile/等),您不能这样做。要么autorun.py 必须启动和分离main.py(或通过一些外部工具间接这样做),要么main.py 必须在启动时进行守护进程。

当使用参数“stop”启动“autorun.py”时如何停止“main.py”?

您需要某种形式的进程间通信 (IPC),以及某种方式让 autorun 找到要使用的正确 IPC 通道。

如果您正在构建网络服务器,正确的答案可能是作为客户端连接到它。但除此之外,最简单的做法是 kill 带有信号的进程。

如果您使用daemon 模块,它可以轻松地将信号映射到回调。或者,如果您不需要任何清理,只需使用SIGTERM,默认情况下它会突然终止。如果这些都不适用,您将不得不设置一个自定义信号处理程序(并在该处理程序中做一些有用的事情——例如,设置一个您的主代码定期检查的标志)。

您如何知道将信号发送到哪个进程?执行此操作的标准方法是让main.py 在启动时将其 PID 记录在 pidfile 中。你读了那个 pidfile,并用信号通知那里指定的任何进程。 (如果您因为没有具有该 PID 的进程而收到错误,那仅表示守护程序已因某种原因退出 - 可能是因为未处理的异常,甚至是段错误。您可能想要记录它,但处理“停止" 否则成功。)同样,如果您使用的是daemon,它会为您执行 pidfile 内容;如果没有,你必须自己做。

您可能想查看计算机附带的守护程序的服务脚本。它们可能都是用 bash 而不是 Python 编写的,但要弄清楚它们在做什么并不难。或者……只使用其中一个作为骨架,在这种情况下,您实际上并不需要 任何 bash 知识;它只是名称上的搜索和替换。

如果你的发行版有 LSB 风格的初始化函数,你可以使用类似this example 的东西。那个比你需要做的要多得多,但它是所有细节的一个很好的例子。或者使用 this example 之类的东西从头开始。这个是从服务脚本进行 pidfile 管理和后台处理(将非守护程序转换为守护程序),如果您正确使用daemon,则不需要这些,它使用的是 SIGHUP 而不是 SIGTERM。您可以自行搜索 init.d 服务脚本的其他示例。

但同样,如果您只是想为自己的系统执行此操作,最好的办法是查看您的发行版上的 /etc/init.d。那里会有几十个示例,其中 90% 的示例除了守护进程的名称外完全相同。

【讨论】:

  • 所以,我必须将该代码放在“autorun.py”中并根据我的需要进行修改,对吧?
  • 像这样:使用 daemon.DaemonContext(working_directory="/home/pi/python"): execfile("main.py")
  • 哪个代码是“那个代码”?如果你问的是with daemon.DaemonContext() 没有。如果您的main.py 只是定义并调用了一个函数,您只需将main() with daemon.DaemonContext(): main() 替换为main.py。如果这是一大堆模块级代码,您可能需要第二个文件作为包装器。但是(如果我理解您的设计)autorun.py 不是 守护进程或那个包装器;它是一个管理守护进程的服务脚本。换句话说,它是获得“开始”或“停止”参数的东西,对吧?
  • 但是,正如我所说,您可能不想将 Python 脚本用于服务脚本。如果您只是要在start 上启动并在stop 上杀死-TERM,那么您只需要一个简单的bash 脚本,就像您的发行版/etc/init.d 中的所有示例一样。对于像 Apache 这样的奇特情况,有时值得拥有守护程序和控制程序(可以启动/停止/等守护程序),并使服务脚本成为控制程序的简单包装器。但是对于您的情况,可能没有必要这样做。
  • 我有一个简单的“main.py”,我只想在电脑启动时运行它,如果可以通过“service ... start”停止和启动它。我不太喜欢守护进程和服务:/ 但我将with daemon.DaemonContext(working_directory="/home/pi/python"): execfile("main.py") 放在“autorun.py”中,它运行良好,但只有“服务...停止”第二次启动它的问题!一个简单的 bash 脚本会更好,是的,我也会尝试...
猜你喜欢
  • 1970-01-01
  • 2022-07-03
  • 1970-01-01
  • 2015-04-12
  • 2017-05-22
  • 2011-07-27
  • 1970-01-01
  • 2022-09-23
  • 2011-10-26
相关资源
最近更新 更多