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

相关推荐
a未来永远是个未知数4 分钟前
构建机部署之git安装(Linux)
linux·git·elasticsearch
疯狂的rabbit.8 分钟前
Linux防火墙
linux·运维·服务器·云计算·redhat·rhce·openeular
懒大王爱吃狼19 分钟前
【Python自动化】Python实现微信自动回复(简单上手),60行代码轻松搞定!个性化自动回复机器人,零基础可学!
运维·开发语言·python·数据分析·自动化·学习方法
YCyjs25 分钟前
云计算【第一阶段(26)】Linux网络设置
linux·运维·服务器·网络·云计算
真果粒wrdms1 小时前
【在线词典】项目实现
linux·c语言·嵌入式硬件·算法·udp·sqlite3
快乐非自愿1 小时前
Nginx负载配置
运维·nginx
u0109053591 小时前
巴比达内网穿透:重塑企业级数据通信的高效与安全边界
服务器·网络·安全
顧棟1 小时前
【Hive实战】Linux磁盘空间不足导致HiveSession创建失败
linux·hive·hadoop
henan程序媛1 小时前
LVS+Keepalived群集
linux·服务器·lvs·keepalived·双机热备份
会讲英语的码农2 小时前
【计算机网络】第一章 概要
运维·服务器·网络协议