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;
}
相关推荐
kida_yuan2 分钟前
【Linux】运维实战笔记 — 我常用的方法与命令
linux·运维·笔记
@syh.17 分钟前
【linux】进程控制
linux
请注意这个女生叫小美1 小时前
C语言 斐波那契而数列
c语言
Legendary_0081 小时前
Type-C 一拖二快充线:突破单口限制的技术逻辑
c语言·开发语言
智者知已应修善业1 小时前
【查找字符最大下标以*符号分割以**结束】2024-12-24
c语言·c++·经验分享·笔记·算法
91刘仁德2 小时前
c++类和对象(下)
c语言·jvm·c++·经验分享·笔记·算法
何中应2 小时前
vmware的linux虚拟机如何设置以命令行方式启动
linux·运维·服务器
江畔何人初2 小时前
kubernet与docker的关系
linux·运维·云原生
百炼成神 LV@菜哥3 小时前
Kylin Linux V10 aarch64 安装启动 TigerVNC-Server
linux·服务器·kylin
佑白雪乐3 小时前
<Linux基础11集>电流+二极管+晶体管+存储器
linux