Linux C 优雅的执行命令

cpp 复制代码
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/resource.h>

void clean_child_environment() {
    // 1. 关闭所有不必要的文件描述符
    struct rlimit rl;
    getrlimit(RLIMIT_NOFILE, &rl);
    
    for (int fd = 3; fd < (int)rl.rlim_cur; fd++) {
        close(fd);
    }
    
    // 2. 重置信号处理为默认
    signal(SIGINT, SIG_DFL);
    signal(SIGQUIT, SIG_DFL);
    signal(SIGTERM, SIG_DFL);
    signal(SIGHUP, SIG_DFL);
    signal(SIGPIPE, SIG_DFL);
    
    // 3. 清除umask
    umask(0);
    
    // 4. 设置新的进程组
    setsid();
}

int execute_command(char *const argv[]) {
    pid_t pid = fork();
    
    if (pid == -1) {
        perror("fork failed");
        return -1;
    } else if (pid == 0) { // 子进程
        clean_child_environment();
        
        // 重定向标准输入输出错误到/dev/null
        int null_fd = open("/dev/null", O_RDWR);
        if (null_fd != -1) {
            dup2(null_fd, STDIN_FILENO);
            dup2(null_fd, STDOUT_FILENO);
            dup2(null_fd, STDERR_FILENO);
            if (null_fd > STDERR_FILENO) {
                close(null_fd);
            }
        }
        
        execvp(argv[0], argv);
        perror("execvp failed");
        _exit(127); // 使用_exit而不是exit,避免刷新stdio缓冲区
    } else { // 父进程
        int status;
        waitpid(pid, &status, 0);
        return WIFEXITED(status) ? WEXITSTATUS(status) : -1;
    }
}

int main() {
    char *const argv[] = {"ls", "-l", NULL};
    int ret = execute_command(argv);
    printf("Command exited with status %d\n", ret);
    return 0;
}

如果系统支持,也可以考虑使用 posix_spawn,它提供了更多控制选项:

cpp 复制代码
#include <spawn.h>
#include <stdio.h>

int main() {
    char *argv[] = {"ls", "-l", NULL};
    pid_t pid;
    
    posix_spawnattr_t attr;
    posix_spawnattr_init(&attr);
    
    // 设置标志:创建新会话、重置信号处理等
    posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSID);
    
    int status = posix_spawn(&pid, "/bin/ls", NULL, &attr, argv, environ);
    posix_spawnattr_destroy(&attr);
    
    if (status != 0) {
        perror("posix_spawn failed");
        return 1;
    }
    
    waitpid(pid, &status, 0);
    printf("Command exited with status %d\n", WEXITSTATUS(status));
    return 0;
}
相关推荐
chlk1231 天前
Linux文件权限完全图解:读懂 ls -l 和 chmod 755 背后的秘密
linux·操作系统
舒一笑1 天前
Ubuntu系统安装CodeX出现问题
linux·后端
改一下配置文件1 天前
Ubuntu24.04安装NVIDIA驱动完整指南(含Secure Boot解决方案)
linux
深紫色的三北六号2 天前
Linux 服务器磁盘扩容与目录迁移:rsync + bind mount 实现服务无感迁移(无需修改配置)
linux·扩容·服务迁移
SudosuBash2 天前
[CS:APP 3e] 关于对 第 12 章 读/写者的一点思考和题解 (作业 12.19,12.20,12.21)
linux·并发·操作系统(os)
哈基咪怎么可能是AI2 天前
为什么我就想要「线性历史 + Signed Commits」GitHub 却把我当猴耍 🤬🎙️
linux·github
十日十行3 天前
Linux和window共享文件夹
linux
木心月转码ing3 天前
WSL+Cpp开发环境配置
linux
祈安_3 天前
C语言内存函数
c语言·后端
崔小汤呀4 天前
最全的docker安装笔记,包含CentOS和Ubuntu
linux·后端