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;
}
相关推荐
John.Lewis1 小时前
数据结构初阶(13)排序算法-选择排序(选择排序、堆排序)(动图演示)
c语言·数据结构·排序算法
小韩博1 小时前
metasploit 框架安装更新遇到无法下载问题如何解决
linux·网络安全·公钥·下载失败
长臂人猿1 小时前
JVM常用工具:jstat、jmap、jstack
linux·运维·jvm
轻松Ai享生活2 小时前
揭秘 linux:一张图看懂系统配置的核心
linux
wdxylb2 小时前
云原生俱乐部-RH134知识点总结(2)
linux·云原生
_Chipen2 小时前
lazy_vim_cmake_clangd_从零到自动补全与语法检查
linux·编辑器·vim
椰子今天很可爱3 小时前
静态库和动态库
linux
檀越剑指大厂3 小时前
【Linux系列】如何在 Linux 服务器上快速获取公网
linux·服务器·php
共享家95273 小时前
linux-高级IO(上)
java·linux·服务器
丑小鸭是白天鹅4 小时前
嵌入式C语言学习笔记之枚举、联合体
c语言·笔记·学习