【Linux】谨慎使用system函数以及对应解决方案

概述

使用system()函数并不是核心,它的返回值、它所执行命令的返回值以及命令执行失败原因如何定位,这才是重点。


system函数剖析

c 复制代码
int system(const char * cmdstring)
{
    pid_t pid;
    int status;

    if(cmdstring == NULL)
    {
        return (1);  //如果cmdstring为空,返回非零值,一般为1
    }

    if((pid = fork())<0)
    {
        status = -1;  //fork失败,返回-1
    }
    else if(pid == 0)
    {
        execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
        _exit(127); // exec执行失败返回127,注意exec只在失败时才返回现在的进程,成功的话现在的进程就不存在
    }
    else //父进程
    {
        while(waitpid(pid, &status, 0) < 0)
        {
            if(errno != EINTR)
            {
                status = -1; //如果waitpid被信号中断,则返回-1
                break;
            }
        }
    }
    return status; //如果waitpid成功,则返回子进程的返回状态
}

(1)系统中的system()函数确实执行了一系列的操作来执行用户指定的命令。

首先,它通过fork()创建一个子进程。

接着,在这个子进程中,它调用exec()系列函数来执行用户提供的命令字符串。

在父进程中,system()会调用wait()来等待子进程结束并收集其退出状态。

(2)在执行过程中,system()会调用/bin/sh来执行命令,通常/bin/sh是指向实际shell程序的符号链接,比如bash。使用-c选项告诉shell从提供的字符串中读取要执行的命令。
在命令执行期间,SIGCHLD信号被忽略,这样内核就不会发送子进程结束的信号给父进程,直到命令执行完成。同时,SIGINT和SIGQUIT信号也被忽略,意味着即使进程接收到这些信号,也不会立即响应。

(3)system()函数返回不同的值以表示不同的执行结果。

如果fork()失败,它返回-1。

如果exec()成功执行,即命令正常执行完毕,system()将返回命令通过exit()或return返回的值。需要注意的是,命令执行成功并不一定意味着命令执行的结果是预期的,例如删除一个不存在的文件,命令仍然会成功执行。

如果exec()执行失败,如命令不存在或被信号中断,system()将返回127。

如果传递给system()的命令参数为NULL,则通常返回非0值,通常为1。

解决方案

方案一、使用execvp函数

execvp()会从环境变量所指的目录中查找符合参数 file 的文件名, 找到后执行该文件, 然后将第二个参数argv 传给该执行的文件。

返回值:如果执行成功则函数不会返回, 执行失败则直接返回-1。

方案二、使用popen()函数替代

控制能力更强:popen()允许你创建一个管道,从而能够读取或写入子进程的输入或输出。而system()只能执行命令,并等待其完成,无法直接与子进程的I/O进行交互。

使用更加灵活:popen()提供了更多的参数,使得你可以更精确地控制子进程的行为。例如,你可以指定子进程的输入和输出文件描述符,或者指定子进程的环境变量等。

安全性更高:popen()函数不会自动执行shell,因此它不容易受到shell注入攻击。而system()函数则需要执行shell,因此更容易受到此类攻击。

返回值更清晰:popen()函数只返回两个值:成功返回子进程的status,使用WIFEXITED相关宏就可以取得command的返回结果;失败返回-1,我们可以使用perro()函数或strerror()函数得到有用的错误信息。

这里小编,将解决方案接口代码奉上,可以直接调用接口使用。
system 方案

相关推荐
HPC_fac130520678161 小时前
以科学计算为切入点:剖析英伟达服务器过热难题
服务器·人工智能·深度学习·机器学习·计算机视觉·数据挖掘·gpu算力
yaoxin5211232 小时前
第二十七章 TCP 客户端 服务器通信 - 连接管理
服务器·网络·tcp/ip
内核程序员kevin2 小时前
TCP Listen 队列详解与优化指南
linux·网络·tcp/ip
sinat_384241096 小时前
使用 npm 安装 Electron 作为开发依赖
服务器
朝九晚五ฺ6 小时前
【Linux探索学习】第十四弹——进程优先级:深入理解操作系统中的进程优先级
linux·运维·学习
自由的dream6 小时前
Linux的桌面
linux
xiaozhiwise7 小时前
Makefile 之 自动化变量
linux
Kkooe7 小时前
GitLab|数据迁移
运维·服务器·git
久醉不在酒8 小时前
MySQL数据库运维及集群搭建
运维·数据库·mysql