Linux下使用system()函数(一定要谨慎)

函数原型

包含在头文件 “stdlib.h” 中

int system(const char *command)

函数功能

执行 dos(windows系统) 或 shell(Linux/Unix系统) 命令,参数字符串command为命令名。另,在windows系统下参数字符串不区分大小写。

说明:在windows系统中,system函数直接在控制台调用一个command命令。 在Linux/Unix系统中,system函数会调用fork函数产生子进程,由子进程来执行command命令,命令执行完后随即返回原调用的进程。

system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命令执行完后随即返回原调用的进程。在调用system()期间SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被忽略。

函数返回值

如果fork()失败 返回-1:出现错误
如果exec()失败,表示不能执行Shell,返回值相当于Shell执行了exit(127)
如果执行成功则返回子Shell的终止状态
如果system()在调用/bin/sh时失败则返回127,其他失败原因返回-1。若参数string为空指针(NULL),仅当命令处理程序可用时,返回非零值,可以通过这一特征判断在一个给定的操作系统上是否支持system函数(当system函数返回值为0时,表明system函数无效,在UNIX系统中,system函数总是可用的);。如果system()调用成功则最后会返回执行shell命令后的返回值,但是此返回值也有可能为 system()调用/bin/sh失败所返回的127,因此最好能再检查errno 来确认执行成功。

附加说明

在编写具有SUID/SGID权限的程序时请勿使用system(),system()会继承环境变量,通过环境变量可能会造成系统安全的问题。system函数已经被收录在标准c库中,可以直接调用。

以下内容转载至:https://my.oschina.net/renhc/blog/53580

先来看一下system()函数的简单介绍:
曾经的曾经,被system()函数折磨过,之所以这样,是因为对system()函数了解不够深入。只是简单的知道用这个函数执行一个系统命令,这远远不够,它的返回值、它所执行命令的返回值以及命令执行失败原因如何定位,这才是重点。当初因为这个函数风险较多,故抛弃不用,改用其他的方法。这里先不说我用了什么方法,这里必须要搞懂system()函数,因为还是有很多人用了system()函数,有时你不得不面对它。

system()函数调用/bin/sh来执行参数指定的命令,/bin/sh 一般是一个软连接,指向某个具体的shell,比如bash,-c选项是告诉shell从字符串command中读取命令;
在该command执行期间,SIGCHLD是被阻塞的,好比在说:hi,内核,这会不要给我送SIGCHLD信号,等我忙完再说;
在该command执行期间,SIGINT和SIGQUIT是被忽略的,意思是进程收到这两个信号后没有任何动作。

再来看一下system()函数返回值:

为了更好的理解system()函数返回值,需要了解其执行过程,实际上system()函数执行了三步操作:
1.fork一个子进程;
2.在子进程中调用exec函数去执行command;
3.在父进程中调用wait去等待子进程结束。
对于fork失败,system()函数返回-1。
如果exec执行成功,也即command顺利执行完毕,则返回command通过exit或return返回的值。
(注意,command顺利执行不代表执行成功,比如command:“rm debuglog.txt”,不管文件存不存在该command都顺利执行了)
如果exec执行失败,也即command没有顺利执行,比如被信号中断,或者command命令根本不存在,system()函数返回127.
如果command为NULL,则system()函数返回非0值,一般为1.

看一下system()函数的源码

看完这些,我想肯定有人对system()函数返回值还是不清楚,看源码最清楚,下面给出一个system()函数的实现:

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成功,则返回子进程的返回状态
}

仔细看完这个system()函数的简单实现,那么该函数的返回值就清晰了吧,那么什么时候system()函数返回0呢?只在command命令返回0时。

看一下该怎么监控system()函数执行状态
这里给我出的做法:

int status;
if(NULL == cmdstring) //如果cmdstring为空趁早闪退吧,尽管system()函数也能处理空指针
{
    return XXX;
}
status = system(cmdstring);
if(status < 0)
{
    printf("cmd: %s\t error: %s", cmdstring, strerror(errno)); // 这里务必要把errno信息输出或记入Log
    return XXX;
}

if(WIFEXITED(status))
{
    printf("normal termination, exit status = %d\n", WEXITSTATUS(status)); //取得cmdstring执行结果
}
else if(WIFSIGNALED(status))
{
    printf("abnormal termination,signal number =%d\n", WTERMSIG(status)); //如果cmdstring被信号中断,取得信号值
}
else if(WIFSTOPPED(status))
{
    printf("process stopped, signal number =%d\n", WSTOPSIG(status)); //如果cmdstring被信号暂停执行,取得信号值
}

到于取得子进程返回值的相关介绍可以参考另一篇文章:http://my.oschina.net/renhc/blog/35116

system()函数用起来很容易出错,返回值太多,而且返回值很容易跟command的返回值混淆。这里推荐使用popen()函数替代,关于popen()函数的简单使用也可以通过上面的链接查看。

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

这篇文章只涉及了system()函数的简单使用,还没有谈及SIGCHLD、SIGINT和SIGQUIT对system()函数的影响,事实上,之所以今天写这篇文章,是因为项目中因有人使用了system()函数而造成了很严重的事故。现像是system()函数执行时会产生一个错误:“No child processes”。

关于这个错误的分析,感兴趣的朋友可以看一下:http://my.oschina.net/renhc/blog/54582

2012-04-14 qdurenhongcai@163.com

转载请注明出处。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Linux使用system()函数可以执行命令行命令,例如system("ls")可以列出当前目录下的所有文件和文件夹。但是需要注意的是,使用system()函数可能存在一定的安全风险,因为可以通过该函数执行恶意代码。因此,在使用函数时需要谨慎考虑。 ### 回答2: system()是在linux下用来执行系统命令的函数使用起来非常方便。在linux中,所有的命令都可以在终端下通过输入相应的命令来执行,而system()函数可以让我们在程序中调用终端命令。这个函数的定义如下: ```c++ int system(const char *command); ``` 其中,command参数就是我们要执行的命令,系统会把这个命令传递给shell进程执行,然后等待命令执行完毕。系统会返回一个整型值,这个值可以用于判断命令的执行结果。 使用system()函数的过程非常简单。比如,我们要在程序中执行ls命令,只需要调用system("ls")即可。代码如下: ```c++ #include <stdlib.h> int main() { system("ls"); return 0; } ``` 执行这个程序,终端会输出当前目录下的文件列表。 当然,system()函数也可以接受参数,这些参数可以被传递到shell命令中。比如,我们要在程序中创建一个名为"mydir"的目录,只需要调用system()函数,传递相应的参数,代码如下: ```c++ #include <stdlib.h> int main() { system("mkdir mydir"); return 0; } ``` 执行这个程序,会在当前目录下创建一个名为"mydir"的目录。 需要注意的是,在调用system()函数的时候,我们应该保证传递给它的参数是安全的,避免被恶意攻击者利用漏洞来执行危险的命令。 ### 回答3: 在Linux操作系统中,使用system()函数可以执行一个新的进程,该新进程可在当前进程之外运行。该函数需要给定一个要执行的命令,该命令可以是任何可在终端执行的命令。 在使用system()函数时,我们需要包含头文件stdlib.h。此外,我们需要将命令作为参数传递给system()函数。例如,下面的代码将执行ls命令: system("ls"); 如果命令包含空格或其他特殊字符,我们需要使用转义字符处理这些字符。例如: system("grep \"hello world\" file.txt"); 上述代码会在文件file.txt中查找“hello world”这个字符串。 在使用system()函数时,需要注意以下几点: 1. system()函数会阻塞当前进程,直到新进程执行完毕。如果需要在后台执行新进程,可以使用fork()函数创建一个子进程并在子进程中执行新进程。 2. system()函数会返回新进程的退出状态码。如果新进程正常退出,则返回0。否则,返回的值可能是一个负数,表示新进程的异常终止。 3. system()函数可以执行任何可在终端执行的命令。这包括系统命令、外部程序或脚本文件等。 总之,system()函数Linux操作系统中非常常用的一个函数,它可以帮助我们执行各种命令,快速地完成各种任务。但是在使用函数时,需要注意避免安全漏洞和系统资源浪费等问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值