【问题标题】:How to get pid of process executed with system() command in c++如何在c ++中使用system()命令执行进程的pid
【发布时间】:2014-05-13 05:33:28
【问题描述】:

当我们使用system() 命令时,程序等待它完成,但我正在使用system() 执行process 并使用负载平衡服务器,因为该程序在执行系统命令后进入下一行。请注意,process 可能不完整。

system("./my_script");

// after this I want to see whether it is complete or not using its pid.
// But how do i Know PID?
IsScriptExecutionComplete();

【问题讨论】:

  • 不确定我是否了解负载平衡服务器。您是否正在调用在远程服务器上启动命令的东西?
  • @jsantander 我们正在使用 Platform LSF 。只要我们调用system(),就会返回主程序。但这个过程可能并不完整。
  • 恐怕我在平台 LSF 方面没有经验(考虑将其添加到您问题的标签中)。但是,如果我理解正确,您是在远程计算资源中安排作业。这个remote job与你的local进程ID无关......所以我的建议是你在Platform LSF API中寻找一个API或命令,让你通过 Platform LSF API 监控计划作业的状态。

标签: c++ process pid


【解决方案1】:

简单的回答:你不能。

system() 的目的是在命令执行时进行阻塞。

但你可以这样“作弊”:

pid_t system2(const char * command, int * infp, int * outfp)
{
    int p_stdin[2];
    int p_stdout[2];
    pid_t pid;

    if (pipe(p_stdin) == -1)
        return -1;

    if (pipe(p_stdout) == -1) {
        close(p_stdin[0]);
        close(p_stdin[1]);
        return -1;
    }

    pid = fork();

    if (pid < 0) {
        close(p_stdin[0]);
        close(p_stdin[1]);
        close(p_stdout[0]);
        close(p_stdout[1]);
        return pid;
    } else if (pid == 0) {
        close(p_stdin[1]);
        dup2(p_stdin[0], 0);
        close(p_stdout[0]);
        dup2(p_stdout[1], 1);
        dup2(::open("/dev/null", O_RDONLY), 2);
        /// Close all other descriptors for the safety sake.
        for (int i = 3; i < 4096; ++i)
            ::close(i);

        setsid();
        execl("/bin/sh", "sh", "-c", command, NULL);
        _exit(1);
    }

    close(p_stdin[0]);
    close(p_stdout[1]);

    if (infp == NULL) {
        close(p_stdin[1]);
    } else {
        *infp = p_stdin[1];
    }

    if (outfp == NULL) {
        close(p_stdout[0]);
    } else {
        *outfp = p_stdout[0];
    }

    return pid;
}

这里不仅可以有进程的PID,还可以有STDINSTDOUT。玩得开心!

【讨论】:

  • 我认为在上面的函数_exit(1) 永远不会调用,因为在执行execl 之后它会从那里返回。对吗?
  • @Vinay 它可能... execl() 可能由于例如内存不足而失败。
  • 不,即使 execl 会成功执行,即使 _exit(1) 也不会调用。作为The exec() family of functions replaces the current process image with a new process image
  • 你可以在execl下面写cout语句来测试它cout不会调用。
  • @Vinay 为什么不考虑execl() 在替换图像之前可能会失败的情况?例如,当您尝试执行文本文件时...
【解决方案2】:

我自己不是这方面的专家,但如果你看看man page for system

system()通过调用/bin/sh -c命令执行command中指定的命令,命令完成后返回

您可以在您正在执行的命令/脚本中进入后台(并立即返回),但我认为系统中没有针对这种情况的具体规定。

我能想到的想法是:

  1. 您的命令可能会通过返回码返回 pid。
  2. 您的代码可能希望在活动进程中查找命令的名称(例如,类 unix 环境中的 /proc API)。
  3. 您可能希望使用fork/exec 自己启动命令(而不是通过 SHELL)

【讨论】:

    【解决方案3】:

    您可以通过以下代码检查命令的退出状态:

    int ret = system("./my_script");
    
    if (WIFEXITED(ret) && !WEXITSTATUS(ret))
    {
        printf("Completed successfully\n"); ///successful 
    }
    else
    {
        printf("execution failed\n"); //error
    }
    

    【讨论】:

    【解决方案4】:

    正如其他答案所说,std::system 无论如何都会阻塞直到完成。但是,如果您想异步运行子进程并且可以使用 boost,您可以使用 boost.process (ref):

    #include <boost/process.hpp>
    
    namespace bp = boost::process;
    
    bp::child c(bp::search_path("echo"), "hello world");
    
    std::cout << c.id() << std::endl;
    // ... do something with ID ...
    
    c.wait();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-04
      • 2021-02-27
      • 1970-01-01
      • 1970-01-01
      • 2010-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多