2014-09-30 99 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/