2014-09-30 101 views
1

我正在开发一个应该自行重启的Python脚本。通过Bash重新启动进程

这是我在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脚本。

回答

2

根据os.execl()文档,该函数替换当前的Python进程,并且从不返回。所以,你有这样的:

  • Python中运行,调用EXECL(run.sh),现在已不再运行
  • run.sh运行时,使用sudo的一些不敬虔的原因(相同的用户,可以在不须藤杀死!)尝试使用其端口号(?!)查找Python程序,并杀死它(或不是,因为你根本不处理shell脚本中的错误)。
  • run.sh(如果在所有杀戮后它仍然活着)尝试启动Python脚本。

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

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

奖励积分,你可以得到当前的Python脚本和(例如使用sys.argv),只是使用这些而不是硬编码他们。有关详细信息,请参见:Restarting a self-updating python script

+0

谢谢!你的解决方案让我走到一半。它确实会重新启动python脚本,但我在脚本中运行的Flask服务器给了我这个错误:error:[Errno 98] Address already in use – Filip 2014-09-30 13:13:10

+0

查找'SO_REUSEADDR'来解决这个问题。 – 2014-09-30 13:14:44

+0

我似乎无法找到像Flask这样的东西,会以某种方式暴露Flask使用的套接字? – Filip 2014-09-30 13:25:43

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在其工作了详细的解答。

0

这并不能完全回答你的问题,但如果你想要实现的是一个服务,它能够以零停机时间回应TCP请求并能够更新它,唯一适当的解决方案是通过一个UNIX套接字。

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

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

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