我正在使用popen
来读取第三方程序的输出。如果子程序失败,我想检测并重新启动。
我该怎么做?如果孩子死亡,则该过程不会正常退出,因此无法使用WEXITSTATUS
进行检查。
还有其他方法吗?
这是一个简单的例子:
PINGER.C
#include <string.h>
#include <stdio.h>
#include <unistd.h>
int
main(int argc, char **argv)
{
int i = 0;
while (1)
{
//fprintf(stderr, "StdErr %d\n", i);
printf("stdout %d\n", i++);
fflush(stdout);
if (i == 5)
i = i / 0; // Die a horrible death
sleep(1);
}
}
WATCHER.C
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
int
main(int argc, char **argv)
{
char *cmd = "./pinger";
printf("Running '%s'\n", cmd);
FILE *fp = popen(cmd, "r");
if (!fp)
{
perror("popen failed:");
exit(1);
}
char inLine[1024];
int bytesRead = 0;
int i = 0;
while (fgets(inLine, sizeof(inLine), fp) != NULL)
{
int len = strlen(inLine);
if (inLine[len-1] == '\n')
inLine[len-1] = '\0';
printf("Received: '%s'\n", inLine);
}
printf("feof=%d ferror=%d: %s\n", feof(fp), ferror(fp), strerror(errno));
int rc = pclose(fp);
printf("pclose returned: %d. IFEXITED=%d\n", rc, WIFEXITED(rc));
}
以下是输出:
$ ./popenTest
calling popen
Running './pinger'
pipe open
Received: 'stdout 0'
Received: 'stdout 1'
Received: 'stdout 2'
Received: 'stdout 3'
Received: 'stdout 4'
feof=1 ferror=0: Success
pclose returned: 8. IFEXITED=0 EXITSTATUS=0
({According to this post,如果命令没有正常退出,您实际上不能使用WEXITSTATUS
,但我还是尝试过>
答案 0 :(得分:0)
一个进程通过从其main()返回退出代码或调用_exit(statuscode)来返回退出状态。如果该过程异常终止(例如,由于信号或故障),则该过程将永远没有机会进行任何此类操作,因此不会有退出状态。
在这种情况下,您所能知道的是该过程因错误而终止。
如果要在程序因错误终止的所有情况下重新启动,则需要同时检查WIFEXITED和WEXITSTATUS:
do {
rc = run_your_child_process();
} while (!WIFEXITED(rc) || WEXITSTATUS(rc) == 0);
// child terminated without error
答案 1 :(得分:0)
阅读pclose()
(和popen()
的POSIX规范)。它说:
返回值
成功返回后,
pclose()
将返回命令语言解释器的终止状态。否则,pclose()
将返回-1并设置errno
来指示错误。
因此,您可以通过pclose()
的返回值间接获取进程的退出状态。那将是一个介于0到255之间的数字。Shell经常通过返回值128 + signal_number
来报告“信号死亡的孩子”。该规范概述了状态可能不可用的情况(例如,您的程序名为wait()
,并在您调用popen()
之前获得了pclose()
打开的进程的信息)。阅读popen()
的规范说明了pclose()
的规范中“命令语言解释器”的使用。