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;
}
相关推荐
Zach_yuan2 分钟前
自定义协议:实现网络计算器
linux·服务器·开发语言·网络
wdfk_prog18 分钟前
[Linux]学习笔记系列 -- [drivers][I2C]I2C
linux·笔记·学习
VekiSon27 分钟前
Linux内核驱动——杂项设备驱动与内核模块编译
linux·c语言·arm开发·嵌入式硬件
Y1rong39 分钟前
linux之网络
linux
寄存器漫游者1 小时前
Linux 软件编程 - IO 编程
linux·运维·spring
2的n次方_1 小时前
CANN Ascend C 编程语言深度解析:异构并行架构、显式存储层级与指令级精细化控制机制
c语言·开发语言·架构
_别来无恙_1 小时前
TFTP的使用Linux
linux·服务器
Zaralike1 小时前
Linux 服务器网络不通排查 SOP(标准操作流程)
linux·服务器·网络
_F_y2 小时前
C语言重点知识总结(含KMP详细讲解)
c语言·开发语言
getapi2 小时前
注塑件的费用构成
linux·服务器·ubuntu