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;
}
相关推荐
FlightYe16 分钟前
音视频修炼之容器与协议(二):HLS和DASH流媒体
android·linux·ffmpeg·音视频·android runtime·dash
承渊政道18 分钟前
Linux网络学习【从深入理解网络层原理到IP分片与重组全过程剖析】
linux·计算机网络·ubuntu·ip分片与重组
橘色的喵18 分钟前
嵌入式Linux编程,如何把硬件中断交给用户态--UIO 的机制
linux·mcu·isr·中断·uio
~城南花已开~40 分钟前
Redfish 事件接收服务搭建指南(Ubuntu Server 实测)
linux·服务器·python·ubuntu
倔强的石头1061 小时前
【Linux指南】进程通信系列(四):命名管道 FIFO —— 让陌生进程按名字见面
linux·服务器·网络
C++ 老炮儿的技术栈1 小时前
机器人的坐标,像 XYZ 的坐标值,是用单精度浮点还是用双精度浮点?
c语言·c++·人工智能·单片机·c
段一凡-华北理工大学1 小时前
高炉能源系统智能化:热风炉、煤气与极致能效~系列文章03:热风炉烧炉与风温的决定因素
大数据·linux·人工智能·能源·热风炉·高炉能源优化
_小许_1 小时前
Linux 常用命令速查:CentOS 与 Ubuntu 双线对照
linux·ubuntu·centos
码农客栈2 小时前
mt7601u移植
linux·运维·服务器
2601_949847752 小时前
io-ts 跨端三方库仓颉适配全流程
linux·运维·ubuntu