在shell程序中调用system()是不好的做法吗?

时间:2016-04-24 02:06:15

标签: c shell posix

我正在编写自定义shell command language interpreter,我发现其他shell使用system()调用来执行管道或高级shell程序。使用execfork执行管道而不是拨打system()是不是更好?例如,如果它是救援shell或其他一些情况,那么您可能无法访问资源system()

/* With the standard output plumbing sorted, execute Nth command */
static void exec_nth_command(int ncmds, char ***cmds) {
    assert(ncmds >= 1);
    if (ncmds > 1) {
        pid_t pid;
        Pipe input;
        if (pipe(input) != 0)
            err_sysexit("Failed to create pipe");
        if ((pid = fork()) < 0)
            err_sysexit("Failed to fork");
        if (pid == 0) {
            /* Child */
            exec_pipe_command(ncmds - 1, cmds, input);
        }
        /* Fix standard input to read end of pipe */
        dup2(input[0], 0);
        close(input[0]);
        close(input[1]);
    }
    execvp(cmds[ncmds - 1][0], cmds[ncmds - 1]);
    err_sysexit("Failed to exec %s", cmds[ncmds - 1][0]);
    /*NOTREACHED*/
}

/* Given pipe, plumb it to standard output, then execute Nth command */
static void exec_pipe_command(int ncmds, char ***cmds, Pipe output) {
    assert(ncmds >= 1);
    /* Fix stdout to write end of pipe */
    dup2(output[1], 1);
    close(output[0]);
    close(output[1]);
    exec_nth_command(ncmds, cmds);
}

/* Execute the N commands in the pipeline */
void exec_pipeline(int ncmds, char ***cmds) {
    assert(ncmds >= 1);
    pid_t pid;
    if ((pid = fork()) < 0)
        err_syswarn("Failed to fork");
    if (pid != 0)
        return;
    exec_nth_command(ncmds, cmds);
}

正如您从上面的代码中看到的那样,我从未在我的shell中调用system(),但这是有充分理由的吗?

2 个答案:

答案 0 :(得分:3)

由于您正在实现一个新shell,因此使用system(3)内部会显得很奇怪,因为system(3)使用系统默认shell,这几乎肯定是与您正在实现的shell不同的shell。 / p>

另外,{{1}}确实会使某些类型的错误处理变得更难 - 您无法完全了解启动子进程后发生的情况。

答案 1 :(得分:1)

它有自己的优点和缺点。实现很可能在其中调用forkexec,因此为了使用fork / exec而放弃它是没有意义的。事实上,如果你想在旅途中运行一个命令,不关心它的输入/输出,退出状态等,那么调用system会很方便。

另一方面,如果你想处理输入/输出重定向,或者为命令添加额外的fds,或者获得准确的退出状态,或者向子进程发送信号等等,你需要做的fork / exec就是你自己。

请注意,system的返回值及其用于运行命令的命令处理器都是实现定义的,因此如果您正在使用便携式shell,则可能需要避免调用它。