我正在使用 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);
}
}
守望者.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
,但我还是试过了)
最佳答案
阅读 pclose()
的 POSIX 规范(还有 popen()
)。它说:
Return value
Upon successful return,
pclose()
shall return the termination status of the command language interpreter. Otherwise,pclose()
shall return -1 and seterrno
to indicate the error.
因此,可以通过pclose()
的返回值间接获取进程的退出状态。这将是一个介于 0 和 255 之间的数字。Shell 通常通过返回值 128 + signal_number
来报告“一个 child 因信号死亡”。该规范概述了状态可能不可用的情况(您的程序调用了 wait()
并在调用 之前获取了由
,例如)。阅读 popen()
打开的进程的信息>pclose()popen()
规范解释了在 pclose()
规范中使用“命令语言解释器”。
关于C 检测 popen 子进程中的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56503915/