通过Bash重启进程

时间:2014-09-30 12:51:26

标签: python bash

我正在处理一个本应重启的Python脚本。

这就是我在Python脚本中所做的事情

os.execl('run.sh', '')

我的run.sh看起来像这样

#!/bin/bash
sudo fuser -ku 8000/tcp
python /home/app.py

我使用sudo fuser -ku 8000/tcp的原因是因为它很容易,因为我的python脚本是唯一使用端口8000的脚本。

当我运行python脚本时,它会执行此操作并停止。

8000/tcp:             7587(pi)  7596(pi)  7597(pi)  7605(pi)  7606(root)
./run.sh: line 3:  7587 Killed                  python /home/app.py

它永远不会重启python脚本。

3 个答案:

答案 0 :(得分:2)

根据os.execl()文档,此函数替换当前的Python进程,永不返回。所以你有这个:

  • Python正在运行,调用execl(run.sh),现在不再运行
  • run.sh正在运行,使用sudo是因为一些不道德的原因(同一个用户,可以在没有sudo的情况下杀死!),尝试使用其端口号(?!)查找Python程序,然后杀死它(或者不是,因为你根本不处理shell脚本中的错误。
  • run.sh(如果它在所有杀戮之后仍然存在)尝试启动Python脚本。

这是一种非常令人费解的做事方式。相反,您应该简单地用自己替换Python进程:

os.execlp('python', '/home/app.py')

对于奖励积分,你可以获得当前的Python和脚本(例如使用sys.argv)并使用它们而不是硬编码它们。有关详细信息,请参阅此处:Restarting a self-updating python script

答案 1 :(得分:0)

执行python代码时,会创建sys.argv

when Python is invoked, it sets sys.argv to everything but it's own executable.

所以你需要像os.execlp('python', 'the_directory')

一样使用

请参阅here了解其工作中的详细答案。

答案 2 :(得分:0)

这并不能完全回答您的问题,但如果您想要实现的是一项服务,该服务能够以零停机时间回复TCP请求并且能够更新它,那么唯一合适的解决方案是通过跨进程传递文件描述符一个UNIX套接字。

代码的骨架可能是这样的:

  • python脚本启动并尝试绑定某个unix套接字。套接字的名称应以零字节开头,因为这将确保套接字在进程执行时死亡。 (这被称为Linux抽象套接字命名空间)
    • 如果成功则意味着没有先前运行的服务器实例。将TCP服务器绑定到端口8000并接受连接并处理这些请求。在UNIX套接字上监听下一个python实例到达。当一个连接在该UNIX套接字上时,停止接受TCP服务器套接字上的传入连接,然后将该文件描述符传递给下一个实例,然后传递其他客户端的所有文件描述符(或者如果请求很快就完成处理它们)。然后死。
    • 如果失败,则表示存在先前正在运行的实例。然后连接到它,打招呼并通过它获取所有文件描述符。第一个是TCP服务器套接字,因此开始接受它上面的新连接。其他文件描述符是已连接的客户端...

使用该方法可以构建服务器的真正透明重启。 您需要一个额外的库来将文件描述符从一个进程传递到另一个进程,如下所示:http://code.google.com/p/python-passfd/