system()函数的返回代码是什么?

10
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int main() {

int res = system("ps ax -o pid -o command | grep sudoku | grep gnome > /dev/null");

printf("res = %d \n", res);

return 0;
}

我想通过检查system()的返回码(或任何其他调用)来查看sudoku是否正在运行。我不希望在任何地方打印输出。

我阅读了man page,但仍无法完全理解system()的返回码。

无论sudoku是否在运行,我都会得到res = 0


1
你尝试过在其他程序(如Firefox或Vi编辑器)运行时运行你的代码吗? - A. K.
是的,我确实尝试了不同的进程。 - hari
8
便利技巧:grep -e"[s]udoku" - nmichaels
如果你想编写一个shell脚本,为什么不直接写一个shell脚本呢?C语言对此任务来说是一个可怕的工具。 - Karl Knechtel
@Karl Knechtel:有时我们需要在程序中执行shell命令。请查看我的帖子以获取答案。 - A. K.
显示剩余2条评论
7个回答

9
首先,您应该使用WEXITSTATUS(res)。标准明确规定:
如果command不是空指针,则system()将以waitpid()指定的格式返回命令语言解释器的终止状态。
我怀疑问题在于命令实际上成功了(grep找到了自己)。请尝试暂时不重定向输出。
[cnicutar@fresh ~]$ ./test
  989 sh -c ps ax -o pid -o command | grep sudoku | grep gnome
res = 0

因此,由于每个命令都成功执行,返回代码将为0 :-). 你可以尝试使用 pgrep 等。


1
谢谢cnicutar,但我不明白你的意思。在ps上使用grep没有成功。我也尝试了不重定向输出,这种情况下,我可以在STDOUT上看到命令,但是res仍然为0。 - hari
1
@hari 你能看到它是因为它实际上成功了(正如我所解释的)。请尝试使用“pgrep sudoku”。 - cnicutar

7
您尝试捕获grep的输出方式可能不起作用。
基于这篇文章:C: Run a System Command and Get Output? 您可以尝试以下方法。此程序使用popen()函数。
#include <stdio.h>
#include <stdlib.h>


int main( int argc, char *argv[] )
{

    FILE *fp;
    int status;
    char path[1035];

    /* Open the command for reading. */
    fp = popen("/bin/ps -x | /usr/bin/grep gnome-sudoku", "r"); 
    if (fp == NULL) {
        printf("Failed to run command\n" );
        exit;
    }
    /* Read the output a line at a time - output it. */
    while (fgets(path, sizeof(path)-1, fp) != NULL) {
      printf("%s", path);
    }
    pclose(fp);
return 0;
}

有关popen()的参考,请参见:

http://linux.die.net/man/3/popen

如果您尝试使用grep,则可以通过重定向grep的输出,并以以下方式读取文件:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main() {

    int res = system("ps -x | grep SCREEN > file.txt");
    char path[1024];
    FILE* fp = fopen("file.txt","r");
    if (fp == NULL) {
      printf("Failed to run command\n" );
      exit;
    }
    // Read the output a line at a time - output it.
    while (fgets(path, sizeof(path)-1, fp) != NULL) {
      printf("%s", path);
    }
    fclose(fp);
    //delete the file
    remove ("file.txt");
    return 0;
}

谢谢,看来您使用popen的解决方案是我必须采用的。 - hari

3
如果您有pgrep,请使用它代替您的shell管道。
system("pgrep -x gnome-sudoku >/dev/null");

当你调用时
system("ps ax -o pid -o command | grep sudoku | grep gnome > /dev/null");

系统执行。
sh -c 'ps ax -o pid -o command | grep sudoku | grep gnome > /dev/null'

这会在 ps 中显示出来,并通过 grep 过滤器。


1
我正在使用 ubuntu 操作系统,但似乎 pgrep 命令无法正常工作: $ ps ax -o pid -o command | grep gnome-sudoku 2638 python /usr/games/gnome-sudoku 2657 grep --color=auto gnome-sudoku $ pgrep -x gnome-sudoku - hari
1
@hari:在Linux上,“pgrep”只能看到进程名称的前15个字符(即/proc/PID/status的“Name”字段)。我认为你想在管道中添加一个“grep -v ps”... - Nemo
@Nemo:谢谢,您是建议将“grep -v ps”添加到“pgrep”中吗?? - hari
@hari: 不,我的建议是放弃 pgrep,使用你的原始解决方案,在管道中加入 grep -v ps(或者也许是 grep -v grep)。 - Nemo

1
尝试使用grep "[s]uduko" 完整的命令是:ps aux | grep [s]uduko 这将不会显示grep本身。

1

解决方法是将输出重定向到文件中,例如:

> /tmp/isRunningSudoku

然后打开文件/tmp/isRunningSudoku并将其存储到您的res变量中。


1

psgrep成功返回;它们进行了forkexec,并且没有返回任何错误状态。这完全无法说明sudoku是否正在运行。

总体而言,你的代码有点粗糙。但是,如果你想继续硬编码这些命令,你可以使用popen并观察这些命令实际打印了什么,而不是查看system是否成功。


0
简而言之,您的命令总是会成功的,因为在解释所有数据之前,它很可能已经被保留在进程空间中。
这意味着您的ps列表中包含它本身,然后grep成功,因为...
grep suduko

会匹配

ps | grep suduko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接