我有一堆運行的迷你服務器進程。它們與我需要停止的FastCGI服務器位於同一個進程組中。 FastCGI服務器將終止其進程組中的所有內容,但我需要這些迷你服務器繼續運行。我可以設置現有流程的流程組嗎?
我可以更改正在運行的非子進程(它們是PID 1的子進程)的進程組嗎? setpgid()
失敗,「沒有這樣的過程」,雖然我積極的那裏。
這是在Fedora Core 10
注意的過程已經運行。新服務器做setsid()
。這些是由舊代碼產生的某些服務器產生的。
我有一堆運行的迷你服務器進程。它們與我需要停止的FastCGI服務器位於同一個進程組中。 FastCGI服務器將終止其進程組中的所有內容,但我需要這些迷你服務器繼續運行。我可以設置現有流程的流程組嗎?
我可以更改正在運行的非子進程(它們是PID 1的子進程)的進程組嗎? setpgid()
失敗,「沒有這樣的過程」,雖然我積極的那裏。
這是在Fedora Core 10
注意的過程已經運行。新服務器做setsid()
。這些是由舊代碼產生的某些服務器產生的。
你可以嘗試的一件事是在miniservers中做setsid()。這將使他們的會話和進程組負責人。
另外,請記住,您無法將進程組ID從另一個會話更改爲一個,並且必須執行調用以更改進程組,以便從要更改組的進程中或來自過程的父母。
我最近編寫了一些測試代碼來定期更改一組進程的進程組,以執行非常類似的任務。您不需要定期更改組標識,這只是我認爲我可能會逃避某個腳本,該腳本會定期檢查運行時間超過一定時間的組。它也可以幫助你追蹤你與setpgid(領)錯誤:喜歡你真的想daemonise的過程,而不是移動過程組
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
void err(const char *msg);
void prn(const char *msg);
void mydaemon();
int main(int arc, char *argv[]) {
mydaemon();
if (setsid() < 0)
err("setsid");
int secs = 5*60;
/* creating a pipe for the group leader to send changed
group ids to the child */
int pidx[2];
if (pipe(pidx))
err("pipe");
fcntl(pidx[0], F_SETFL, O_NONBLOCK);
fcntl(pidx[1], F_SETFL, O_NONBLOCK);
prn("begin");
/* here the child forks, it's a stand in for the set of
processes that need to have their group ids changed */
int child = fork();
switch (child) {
case -1: err("fork3");
case 0:
close(pidx[1]);
while(1) {
sleep(7);
secs -= 7;
if (secs <= 0) { prn("end child"); exit(0); }
int pid;
/* read new pid if available */
if (read(pidx[0], &pid, sizeof pid) != sizeof pid) continue;
/* set new process group id */
if (setpgid(getpid(), pid)) err("setpgid2");
prn("child group changed");
}
default: break;
}
close(pidx[0]);
/* here the group leader is forked every 20 seconds so that
a new process group can be sent to the child via the pipe */
while (1) {
sleep(20);
secs -= 20;
int pid = fork();
switch (pid) {
case -1: err("fork2");
case 0:
pid = getpid();
/* set process group leader for this process */
if (setpgid(pid, pid)) err("setpgid1");
/* inform child of change */
if (write(pidx[1], &pid, sizeof pid) != sizeof pid) err("write");
prn("group leader changed");
break;
default:
close(pidx[1]);
_exit(0);
}
if (secs <= 0) { prn("end leader"); exit(0); }
}
}
void prn(const char *msg) {
char buf[256];
strcpy(buf, msg);
strcat(buf, "\n");
write(2, buf, strlen(buf));
}
void err(const char *msg) {
char buf[256];
strcpy(buf, msg);
strcat(buf, ": ");
strcat(buf, strerror(errno));
prn(buf);
exit(1);
}
void mydaemon() {
int pid = fork();
switch (pid) {
case -1: err("fork");
case 0: break;
default: _exit(0);
}
close(0);
close(1);
/* close(2); let's keep stderr */
}
聽起來。 (注:一個可以移動的過程組,但我相信你需要在同一會話和目標需要已經成爲一個進程組。)
但首先,看看是否daemonising工程給你:
#include <unistd.h>
#include <stdio.h>
int main() {
if (fork() == 0) {
setsid();
if (fork() == 0) {
printf("I'm still running! pid:%d", getpid());
sleep(10);
}
_exit(0);
}
return 0;
}
顯然你應該在實際代碼中檢查錯誤等,但上面的內容應該可以工作。
即使主進程退出,內部進程也將繼續運行。看着從/proc
內部過程的狀態,我們發現,它確實是的init
孩子:
Name: a.out
State: S (sleeping)
Tgid: 21513
Pid: 21513
PPid: 1
TracerPid: 0
經過一番研究,我想通了。 Inshalla得到的基本問題,「你不能改變進程組ID爲另一個會話」這解釋了爲什麼我的setpgid()
失敗(帶有誤導性消息)。但是,你似乎可以改變它從組中的任何其他進程(不一定是父)。
由於這些進程是由FastCGI服務器啓動的,並且該FastCGI服務器仍在運行且處於相同進程組中。因此,這個問題不能重新啓動FastCGI服務器而不殺死它產生的服務器。我寫了一個新的CGI程序,在運行的服務器上執行setpgid()
,通過Web請求執行它並解決問題!
setpgid(2)中的錯誤值:'ESRCH ...對於setpgid([pid,pgid]):pid不是調用進程,也不是調用進程的子進程。「有趣的是,要了解可以從組內調用。 – Inshallah 2009-08-23 17:49:46
是的,我得到的ESRCH在這種情況下很差,因爲「沒有這樣的過程」。 – Schwern 2009-08-24 03:52:29