2

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

根据this post,如果命令没有正常退出,你实际上是不能使用WEXITSTATUS的,但我还是试过了)

4

2 回答 2

1

阅读pclose()(以及popen())的 POSIX 规范。它说:

返回值

返回成功后,pclose()应返回命令语言解释器的终止状态。否则,pclose()应返回 -1 并设置errno以指示错误。

因此,您可以通过 的返回值间接获取进程的退出状态pclose()。这将是一个介于 0 和 255 之间的数字。Shell 通常通过返回 value 来报告“通过信号导致孩子死亡” 128 + signal_number。该规范概述了状态可能不可用的情况(例如,您的程序调用并获取了在您调用之前wait()打开的进程的信息)。阅读规范解释了规范中“命令语言解释器”的使用。popen()pclose()popen()pclose()

于 2019-06-08T08:03:25.817 回答
0

一个进程通过从它的 main() 返回一个退出代码,或者通过调用 _exit(statuscode) 来返回一个退出状态。如果进程异常终止,例如由于信号或故障,该进程永远没有机会执行任何这些操作,因此没有退出状态。

在这种情况下,您所能知道的只是该过程因错误而终止。

如果要在程序因错误终止的所有情况下重新启动,则需要同时检查 WIFEXITED 和 WEXITSTATUS:

do {
    rc = run_your_child_process();

} while (!WIFEXITED(rc) || WEXITSTATUS(rc) == 0);

// child terminated without error
于 2019-06-08T06:36:14.790 回答