You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C语言exec()创建的Bash中执行命令?含ls输入方法

解答:在C语言启动的Bash环境中执行命令 & 向登录Shell发送输入

1. 如何在通过exec()创建的Bash环境中执行命令?

有几种实用方式,取决于你是想让Bash执行命令后直接退出,还是启动交互式Shell再动态喂命令:

方式一:直接让Bash执行指定命令(非交互式)

这是最省心的方式——通过bash -c参数直接传递要执行的命令,Bash启动后会立刻执行该命令,完成后自动退出。比如:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>

int main() {
    if (fork() == 0) {
        // 执行ls + 打印当前目录的组合命令,完成后Bash退出
        execlp("bash", "bash", "-c", "ls -l && pwd", NULL);
        perror("execlp failed");
        exit(EXIT_FAILURE);
    }
    wait(NULL);
    return 0;
}

这里-c参数告诉Bash:后面的字符串是要执行的命令脚本,你可以用&&(成功后执行)或;(顺序执行)拼接多个命令。

方式二:给交互式Bash喂输入(适合保留Shell环境的场景)

如果你启动的是交互式Shell(比如bash -l登录Shell),需要通过重定向标准输入的方式给它发送命令,常用两种方法:

  • 重定向到预先写好命令的文件:execlp("bash", "bash", "-l", "<", "commands.txt", NULL);,文件里每行放一个要执行的命令。
  • 使用管道(pipe)在父进程中动态发送命令——这也是解决你第二个问题的核心方案。

2. 向bash -l登录Shell发送ls命令作为输入

你当前的代码只重定向了标准输出,但要给Shell发输入,需要把它的标准输入(stdin)连接到一个可写入的通道,管道是最合适的选择。下面是修改后的完整可运行代码:

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>

int main() {
    int pipefd[2];
    // 打开用于保存Shell输出的文件
    int fileDescriptor = open("bash_output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fileDescriptor == -1) {
        perror("Failed to open output file");
        exit(EXIT_FAILURE);
    }

    // 创建管道:pipefd[0]是读端,pipefd[1]是写端
    if (pipe(pipefd) == -1) {
        perror("Failed to create pipe");
        exit(EXIT_FAILURE);
    }

    pid_t pid = fork();
    if (pid == -1) {
        perror("Fork failed");
        exit(EXIT_FAILURE);
    }

    if (pid == 0) {
        // 子进程:配置Shell的输入输出
        dup2(fileDescriptor, 1);  // 重定向stdout到文件
        close(fileDescriptor);

        dup2(pipefd[0], 0);       // 重定向stdin到管道读端
        close(pipefd[0]);
        close(pipefd[1]);         // 子进程不需要写端,关闭避免资源泄漏

        // 启动登录Shell
        execlp("bash", "bash", "-l", NULL);
        // 如果走到这里说明execlp失败
        perror("Failed to start bash");
        exit(EXIT_FAILURE);
    } else {
        // 父进程:发送命令给Shell
        close(pipefd[0]);  // 父进程不需要读端,关闭

        // 发送ls命令,必须加换行符——Bash需要换行来确认执行
        const char* ls_cmd = "ls\n";
        write(pipefd[1], ls_cmd, strlen(ls_cmd));

        close(pipefd[1]);  // 关闭写端,让Bash知道输入结束,否则会一直等待

        // 等待子进程执行完毕
        wait(NULL);
        close(fileDescriptor);
    }

    return 0;
}

关键细节说明:

  • 管道的作用:管道是父子进程间的单向通信通道,父进程写命令到管道写端,子进程的Shell从管道读端读取输入。
  • 换行符的必要性:Bash作为交互式Shell,需要看到换行符才会执行输入的命令,所以要发送"ls\n"而不是"ls"。
  • 关闭多余文件描述符:管道两端的文件描述符在不用时必须关闭,否则Shell会一直阻塞在等待输入的状态,无法正常退出。

内容的提问来源于stack exchange,提问作者Reshmi Das

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:18:04