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;
}