您的位置:首页 > 运维架构

popen 与system函数笔记

2015-09-10 14:28 477 查看
文章大部分为摘抄,有些没有标明出处,请谅解。

 

通过popen查看selinux是否打开:

#include <stdio.h>
#include <stdlib.h>
int main ()   {

char cmd[64] = {0};
char buf[64] = {0};

FILE *fd;
sprintf(cmd,"getenforce\n");
fd = popen(cmd, "r" );
if(NULL == fd) {
LOGD("%s: popen error.\n", __FUNCTION__);
return 0;
}
fread(buf, sizeof(char), sizeof(buf), fd);
LOGD("chenpuo popen buf=%s",buf);
rc= pclose(fd2);
           if(-1==rc){
             ALOGD("getenforce close file failed");
             if(ECHILD==errno) {
                 ALOGD("cyx pclose cannot obtain the child status.\n");
             } else {
                ALOGD( "getenforce Close file failed. %s, with errno %d.\n", strerror(errno), errno);
             }
         }else{
             ALOGD("cmd getenforce child proccess %d status=%d  strerr=%s\r\n", rc, WEXITSTATUS(rc), strerror(errno));
         }
}

注意:这里cmd只要执行成功,则errno就为success;

奇怪的ls /data/test.log命令,如果文件不存在errno居然也是success,此时 No such file or directory 信息似乎打印不出来,buf为空。如果存在则buf为正常,为/data/test.log

 

 

 

#include “stdio.h”

#include “stdlib.h”

  int main()

  {

  FILE *fp;

  char buf[200] = {0};

  if((fp = popen(“cat > test1″, “w”)) == NULL) {

  perror(“Fail to popen\n”);

  exit(1);

  }

  fwrite(“Read pipe successfully !”, 1, sizeof(“Read pipe successfully !”), fp);

  pclose(fp);

  return 0;

  }


 

 

 

int main()  

{  
        FILE * fp;  

        char buf[40] = {0};  
        fp = popen(NULL, "w");  

        if(NULL == fp)  
        {  

                perror("popen error.\n");  
                return -1;  

        }  
        printf("Input command:");  

        fgets(buf, 40, stdin);  
        fputs(buf, fp);  

        pclose(fp);  
        return 0;  

}  

执行结果:

[root@localhost codetest]# ./a.out 

sh: -c: option requires an argument

Input command:pwd

 

 

 

 

 

==============================system函数====================================

 

看到popen就很容易想到system, system这个函数在老的平台里经常看到。现在很少看到使用了。 究其原因:

1)system 缺点:

system()函数执行过程为:fork()->exec()->waitpid()。

system() executes a command specified in command by calling /bin/sh -c command, and returns after the command has been completed. During execution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT will
be ignored.

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

system()函数用起来很容易出错,返回值太多,而且返回值很容易跟command的返回值混淆

 

system的实际问题:

 转自  http://my.oschina.net/renhc/blog/54582     这里自己看后比较有感受,遂简单转述了下。

简单概括就是:系统的同事在LIBGEN 里新增加了SIGCHLD的处理。将其ignore。为了避免僵尸进程的产生。 于是我们调用system就会出错ECHILD 即No child processes 。man手册查找system函数,没有此errno;再看waitpid里正好有此errno。

ECHILD
(for waitpid() or waitid()) The process specified by pid (waitpid()) or idtype and id (waitid()) does not exist or is not a child of the calling process. (This can happen for one's own child if the action for SIGCHLD
is set to SIG_IGN. See also the Linux Notes section about threads.)

果然有料,如果SIGCHLD信号行为被设置为SIG_IGN时,waitpid()函数有可能因为找不到子进程而报ECHILD错误。似乎我们找到了问题的解决方案:在调用system()函数前重新设置SIGCHLD信号为缺省值,即signal(SIGCHLD, SIG_DFL)。
 

最好如下修改可以:

 

这里推荐使用popen()函数替代,关于popen()函数的简单使用也可以通过上面的链接查看。

popen()函数较于system()函数的优势在于使用简单,popen()函数只返回两个值:

成功返回子进程的status,使用WIFEXITED相关宏就可以取得command的返回结果;

失败返回-1,我们可以使用perro()函数或strerror()函数得到有用的错误信息。

 

 

 

 

 

=================================最后PS================================

在特权(setuid、setgid)进程中千万注意不要使用system和popen

popen()、popen()会继承环境变量,通过环境变量可能会造成系统安全的问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: