popen 与system函数笔记
2015-09-10 14:28
477 查看
文章大部分为摘抄,有些没有标明出处,请谅解。
通过popen查看selinux是否打开:
注意:这里cmd只要执行成功,则errno就为success;
奇怪的ls /data/test.log命令,如果文件不存在errno居然也是success,此时 No such file or directory 信息似乎打印不出来,buf为空。如果存在则buf为正常,为/data/test.log
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()会继承环境变量,通过环境变量可能会造成系统安全的问题。
通过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() 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()会继承环境变量,通过环境变量可能会造成系统安全的问题。
相关文章推荐
- nginx_keepalived
- Nginx配置文件的基本说明与基本操作命令
- [转][技巧]linux命令行解压小技巧一例
- tomcat的配置详解:[1]tomcat绑定域名
- selenium firefoxdriver:org.openqa.selenium.firefox.NotConnectedException: Unable to connect to host
- Docker容器与仓库
- Linux编译提速
- opencv实例二:缩放一张图片
- linux SVN常见问题解决
- nginx上设置禁止通过ip访问服务器,只能通过域名访问
- 网站推广新趋向:以词带量,思路至上
- 三张图看遍Linux性能监控、测试、优化工具
- hadoop常用命令
- Linux和windows下内核socket优化项
- 12个学习编程的网站
- linux命令备份和还原mysql数据库
- Openlayers发布谷歌离线地图
- Open source memory test tool:Memtester
- nginx
- Linux Valgrind命令