我很猶豫要發佈這個問題,因爲我認爲某人已經在某個地方問過它了,但經過很多衝刷之後,我已經空了,所以在這裏。守護進程/背景通過另一個程序的腳本啓動的進程
背景:我正在運行一個本地代理(用C語言編寫,通過TCP監聽),它允許遠程執行少量腳本/命令。 (通過web界面,具體說明)。腳本本身是二進制文件,bash或perl腳本的混合體,只要它們在列表中被允許,代理程序本身並不關心。
(這是一個企業,內部網絡上,這是非常早期的階段,所以請不要在這個時候討論安全性的優點。)
的C代理代碼啓動流程是這樣的:
sprintf(mrun, "%s %s 2>&1", file, args);
mexec = popen(mrun, "r");
[read some returned buffer]
pclose(mexec);
這種方法適用於既有外部bash和Perl腳本,提供的腳本只是執行命令(或者在前臺做的事情)。不過,我最近需要擴展一個腳本以包含重新啓動守護進程,在這種情況下,命名爲。
腳本本身(bash)的方法很簡單:
#!/bin/bash
pkill -9 named
/local/mnt/named/sbin/named -c /local/mnt/named/var/named.conf &
echo "restarted"
我遇到的問題是,該腳本無法完成(即重新啓動的是從來沒有回顯的)時通過C代理運行,所以控制永遠不會返回並且TCP套接字永遠不會被釋放。就代理而言,該流程仍在運行。如果我從終端運行腳本,它可以正常工作,控制權會返回給我。
我是否錯過了一些東西,它允許腳本在從C守護進程分叉時正常執行,而不僅僅是從bash終端調用?
我知道nohup,如果其他所有的都失敗了,我想可以使用它,但是我很好奇是否有其他解決方法。
您的「C代理」是否讀取所有輸出? IOW,它是否在等待它的輸入被對方關閉?如果是這樣,可以預料它永遠不會結束:在後臺啓動的named會將句柄保持爲stdout並且正在運行。因此,即使重新啓動腳本完成,仍然有輸出等待(來自named)。嘗試使用自己的句柄來提供命名:'.../named .../dev/null&'並且看看它是否有幫助 – fork0 2012-07-26 20:42:21
它只讀取一次緩衝區,所以它不會等待輸入。你建議的改變有所幫助。劇本本身似乎完成了,現在我得到了回聲。但是這引發了一個不同的問題:一旦腳本完成,代理程序就不能關閉套接字連接。它只是掛起,直到我殺死命名。所以,現在看起來我在生成進程的過程中遇到了另一個問題,即保持原始TCP連接處於打開狀態,即使它不應該也不會使用相同的端口。 – Randy 2012-07-26 22:03:50
@Randy:在調用'close'之前,嘗試在'SHUT_RDWR'中傳遞'shutdown'來獲取套接字的方式。套接字'fd'可能被複制到子進程。 – jxh 2012-07-26 22:51:44