【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 方案

相关推荐
苏灿烤鱼15 分钟前
一套进程代替八件套,桌面更稳还是单点更大
linux·github·shell
刘梦薇18 分钟前
SSH连接失败connection reset解决办法
linux·运维·ubuntu·ssh·腾讯云
Rsingstarzengjx40 分钟前
stm32m157 U-boot 测试
linux·运维·服务器
月落汀兰1 小时前
Linux Nginx全套实战通关|静态站点/虚拟主机/HTTPS/PHP/反向代理/七层负载均衡,每行命令逐参数拆解
linux·nginx·https
头茬韭菜1 小时前
功能点 1:项目骨架与启动流程 —— 源码阅读笔记
运维·笔记·debian·fluss
workflower1 小时前
智能无人机成低空经济核心赛道
运维·人工智能·机器学习·机器人·云计算·无人机
野生码农AI实战2 小时前
奇耻大辱,我的网站被挂马,服务器已沦陷三个月
服务器
ShineWinsu2 小时前
对于C++:缓冲区管理的详细解析
linux·c++·面试·编程·笔试·io·缓冲区
jason.zeng@15022072 小时前
服务器磁盘读写效率,网络吞吐量查看,mysql性能调优
服务器·网络·mysql
张小姐的猫2 小时前
【Linux】网络编程 —— 传输层协议 TCP(下)
linux·运维·服务器·网络·tcp/ip·http·php