精华内容
下载资源
问答
  • C语言system函数使用

    万次阅读 多人点赞 2019-11-08 19:09:18
    函数原型 包含在头文件 “stdlib.h” 中 int system(const char * command) 函数功能 执行 dos(windows系统) 或 shell(Linux/Unix...说明:在windows系统中,system函数直接在控制台调用一个command命令。 在L...

    函数原型
    包含在头文件 “stdlib.h” 中

    int system(const char * command)


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

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

    函数返回值
    命令执行成功返回0,执行失败返回-1。

    举个栗子

    实现关机小程序

    #include <stdio.h>
    #include<string.h>
    #include<stdlib.h>
    int main(void)
    {
        char input[100];
        system("shutdown -s -t 60");
        //这是Windows系统下的一个关机命令
        flag:
    	printf("你的电脑将在一分钟后关机,如果输入“我是猪”,就会取消关机!\n请输入: ");
        scanf("%s",input);
        if(0==strcmp(input,"我是猪"))
    	{
            system("shutdown -a");//取消关机命令
    	}
        else
    	{
            goto flag;
    	}
        return 0;
    }
    

     

    我们今天来看看在windows操作系统下system () 函数详解(主要是在C语言中的应用)
    注意:在windows下的system函数中命令可以不区别大小写!
    函数名: system
    功 能: 发出一个DOS命令
    用 法: int system(char *command);

    system函数已经被收录在标准c库中,可以直接调用。
    例如:

    # include <stdio.h>
    # include<stdlib.h>
    void main() {
    
    	//printf("锄禾日当午,写C代码真是苦,传智播客");
    	system("Nslookup");
    	//getchar();
    
    }

    又如:
    system(“PAUSE”)可以实现冻结屏幕,便于观察程序的执行结果;
    system(“CLS”)可以实现清屏操作。
    而调用color函数可以改变控制台的前景色和背景,具体参数在下面说明。

    例如:
    用 system(“color 0A”); 其中color后面的0是背景色代号,A是前景色代号。各颜色代码如下:

    0=黑色 1=蓝色 2=绿色 3=湖蓝色 4=红色 5=紫色 6=黄色 7=白色 8=灰色 9=淡蓝色 A=淡绿色 B=淡浅绿色 C=淡红色 D=淡紫色 E=淡黄色 F=亮白色

     

    参数	功能	说明
    ASSOC	显示或修改文件扩展名关联	
    ATTRIB	显示或更改文件属性	
    BREAK	设置或清除扩展式 CTRL+C 检查	
    BCDEDIT	设置启动数据库中的属性以控制启动加载	
    CACLS	显示或修改文件的访问控制列表(ACL)	
    CALL	从另一个批处理程序调用这一个	
    CD	显示当前目录的名称或将其更改	
    CHCP	显示或设置活动代码页数	
    CHDIR	显示当前目录的名称或将其更改	
    CHKDSK	检查磁盘并显示状态报告	
    CHKNTFS	显示或修改启动时间磁盘检查	
    CLS	清除屏幕	*
    CMD	打开另一个 Windows 命令解释程序窗口	*
    COLOR	设置默认控制台前景和背景颜色	*
    COMP	比较两个或两套文件的内容	
    COMPACT	显示或更改 NTFS 分区上文件的压缩	
    CONVERT	将 FAT 卷转换成 NTFS 你不能转换当前驱动器	
    COPY	将至少一个文件复制到另一个位置	
    DATE	显示或设置日期	后面加 /t 表示显示日期
    DEL	删除至少一个文件	
    DIR	显示一个目录中的文件和子目录	
    DISKPART	显示或配置磁盘分区属性	
    DOSKEY	编辑命令行、撤回 Windows 命令并创建宏	
    DRIVERQUERY	显示当前设备驱动程序状态和属性	
    ECHO	显示消息,或将命令回显打开或关闭	
    ENDLOCAL	结束批文件中环境更改的本地化	
    ERASE	删除一个或多个文件	*
    EXIT	退出 CMD.EXE 程序(命令解释程序)	*
    FC	比较两个文件或两个文件集并显示它们之间的不同	*
    FIND	在一个或多个文件中搜索一个文本字符串	*
    FINDSTR	在多个文件中搜索字符串	*
    FOR	为一组文件中的每个文件运行一个指定的命令	
    FORMAT	格式化磁盘,以便用于 Windows	
    FSUTIL	显示或配置文件系统属性	
    FTYPE	显示或修改在文件扩展名关联中使用的文件类型	
    GOTO	将 Windows 命令解释程序定向到批处理程序中某个带标签的行	
    GPRESULT	显示计算机或用户的组策略信息	
    GRAFTABL	使 Windows 在图形模式下显示扩展字符集	*
    HELP	提供 Windows 命令的帮助信息	
    ICACLS	显示、修改、备份或还原文件和目录的 ACL	
    IF	在批处理程序中执行有条件的处理操作	
    LABEL	创建、更改或删除磁盘的卷标	
    MD	创建一个目录	
    MKDIR	创建一个目录	
    MKLINK	创建符号链接和硬链接	
    MODE	配置系统设备	
    MORE	逐屏显示输出	*
    MOVE	将一个或多个文件从一个目录移动到另一个目录	
    OPENFILES	显示远程用户为了文件共享而打开的文件	
    PATH为	可执行文件显示或设置搜索路径	
    PAUSE	暂停批处理文件的处理并显示消息	
    POPD	还原通过 PUSHD 保存的当前目录的上一个值	
    PRINT	打印一个文本文件	
    PROMPT	更改 Windows 命令提示	
    PUSHD	保存当前目录,然后对其进行更改	
    RD	删除目录	
    RECOVER	从损坏的或有缺陷的磁盘中恢复可读信息	*
    REM	记录批处理文件或 CONFIG.SYS 中的注释(批注)	
    REN	重命名文件	
    RENAME	重命名文件	
    REPLACE	替换文件	*
    RMDIR	删除目录	
    ROBOCOPY	复制文件和目录树的高级实用工具	
    SET	显示、设置或删除 Windows 环境变量	
    SETLOCAL	开始本地化批处理文件中的环境更改	
    SC	显示或配置服务(后台进程)	
    SCHTASKS	安排在一台计算机上运行命令和程序	
    SHIFT	调整批处理文件中可替换参数的位置	
    SHUTDOWN	允许通过本地或远程方式正确关闭计算机	
    SORT	对输入排序	
    START	启动单独的窗口以运行指定的程序或命令	
    SUBST	将路径与驱动器号关联	
    SYSTEMINFO	显示计算机的特定属性和配置	
    TASKLIST	显示包括服务在内的所有当前运行的任务	
    TASKKILL	中止或停止正在运行的进程或应用程序	
    TIME	显示或设置系统时间	后面加 /t 表示显示时间
    TITLE	设置 CMD.EXE 会话的窗口标题	“TITLE 你想改成啥”
    TREE	以图形方式显示驱动程序或路径的目录结构	“TREE D:”
    TYPE	显示文本文件的内容	“TYPE D:\\文本.txt”
    VER	显示 Windows 的版本	
    VERIFY	告诉 Windows 是否进行验证,以确保文件正确写入磁盘	
    VOL	显示磁盘卷标和序列号	
    XCOPY	复制文件和目录树	
    WMIC	在交互式命令 shell 中显示 WMI 信息	
    


     

     

    举例
    看了下面实例,相信你会对学到更多system在C程序设计中的应用。
    示例一:
    我们来试一试用C语言调用DOS命令实现定时关机,想想也很有趣,嘿嘿:大家可以给你朋友电脑上弄一个哦 让他输入我是猪才能不关机否则就关机了 。想弄其他字段的话自己去修改下程序中你给的字就可以了哦。可是大家别玩过火了哦。小心自己也解决不了哦。

    #include<stdio.h>     //标准输入输出库函数
    
    #include<stdlib.h>    //可以输入system用以键入DOS管理窗口界面下的cmd中的命令
    
    #include<string.h>    //字符串,数组定义的库函数
    
    int main()
    
    {
    
        char a[10];    //定义一个字符类型的数组,便于玩家从键盘键入各类字符信息
    
    flag:
    
        printf("请输入\"我是猪\",否则电脑将在两分钟后关闭\n");  //“我是猪”此语句可由制定者自由更改,不过后面相应的位置也要记得改动
    
        system("shutdown -s -t 120");    //60秒倒计时关机命令,时间可自由更改
    
        scanf("%s", a);             //玩家从键盘键入字符串
    
        if (strcmp(a, "我是猪") == 0){  //比较两个字符串,若相等则执行IF下的语句
    
            printf("恭喜你成功选择自己的属相,主动承认现实!\n");
    
            system("shutdown -a");  //结束自动关机倒计时命令,当然也可以打破规则,取消该语句,不过那样就太邪恶了
    
        }
    
        else
    
            goto flag;        //跳转语句,跳转至flag标记处继续执行
    
        return 0;
    
    }
    

    这个程序可以实现的是定时关机大家可以去试试哦

    #include<stdio.h>     //标准输入输出库函数
    #include<stdlib.h>    //可以输入system用以键入DOS管理窗口界面下的cmd中的命令
    #include<string.h>    //字符串,数组定义的库函数
    int print()
    {
        printf("****************关机程序****************\n");
        printf("****1.实现在十分钟内的定时关闭计算机****\n");
        printf("************2.立即关闭计算机************\n");
        printf("***************3.注销计算机*************\n");
        printf("****************4.退出系统**************\n");
        return 0;
    
    }
    void main()
    {
        system("title C语言关机程序");//设置cmd窗口宽度
        system("mode con cols=48 lines=25");//窗口宽度高度
        system("color 0B");//设置默认控制台前景个背景色
        system("date /T");
        system("TIME /T");
        char cmd[20] = "shutdown -s -t";
        char t[5] = "0";
        print();
        int c;
        scanf("%d", &c);
        getchar();
        switch (c)
        {
        case 1:
            printf("您想在多少秒后自动关闭计算机?(0~600)\n");
            scanf("%s", t);
            system(strcat(cmd, t));
            break;
        case 2:
            system("shutdown -p");
            break;
        case 3:
            system("shutdown -1");
            break;
        case 0:
            break;
        default:
            printf("Error!\n");
        }
        system("pause");
        exit(0);
    
    }
    

     

    示例二:
    用C语言删除文件,例如文件的位置是d:\123.txt
    用system()函数执行windows命令。

    #include<stdio.h>
    #include<stdlib.h>
    int main()
    {
        system("del d:\123.txt");
        return 0;
    }

     

     

    展开全文
  • C语言system函数

    万次阅读 多人点赞 2018-01-04 10:53:44
    注意:在windows下的system函数中命令可以不区别大小写! 函数名: system 功 能: 发出一个DOS命令 用 法: int system(char *command);system函数已经被收录在标准c库中,可以直接调用。例如:#include #...

    我们今天来看看在windows操作系统下system () 函数详解(主要是在C语言中的应用)
    注意:在windows下的system函数中命令可以不区别大小写!
    函数名: system
    功 能: 发出一个DOS命令
    用 法: int system(char *command);

    system函数已经被收录在标准c库中,可以直接调用。

    例如:

    #include<stdio.h>
    #include<stdlib.h>
    int main()
    {
        printf("About to spawn and run a DOS command\n");
        system("dir");
    return 0;
    }

    又如:
    system(“PAUSE”)可以实现冻结屏幕,便于观察程序的执行结果;
    system(“CLS”)可以实现清屏操作。
    而调用color函数可以改变控制台的前景色和背景,具体参数在下面说明。

    例如:
    用 system(“color 0A”); 其中color后面的0是背景色代号,A是前景色代号。各颜色代码如下:

    0=黑色 1=蓝色 2=绿色 3=湖蓝色 4=红色 5=紫色 6=黄色 7=白色 8=灰色 9=淡蓝色 A=淡绿色 B=淡浅绿色 C=淡红色 D=淡紫色 E=淡黄色 F=亮白色
    拿走不谢,我叫雷锋!


    在前面的第一个博客中我也写过一些DOS操作命令了大家想去了解的就去了解下。以下再给大家一些;

    这里写图片描述


    举例
    看了下面实例,相信你会对学到更多system在C程序设计中的应用。
    示例一:
    我们来试一试用C语言调用DOS命令实现定时关机,想想也很有趣,嘿嘿:大家可以给你朋友电脑上弄一个哦 让他输入我是猪才能不关机否则就关机了 。想弄其他字段的话自己去修改下程序中你给的字就可以了哦。可是大家别玩过火了哦。小心自己也解决不了哦。


    #include<stdio.h>     //标准输入输出库函数
    
    #include<stdlib.h>    //可以输入system用以键入DOS管理窗口界面下的cmd中的命令
    
    #include<string.h>    //字符串,数组定义的库函数
    
    int main()
    
    {
    
        char a[10];    //定义一个字符类型的数组,便于玩家从键盘键入各类字符信息
    
    flag:
    
        printf("请输入\"我是猪\",否则电脑将在两分钟后关闭\n");  //“我是猪”此语句可由制定者自由更改,不过后面相应的位置也要记得改动
    
        system("shutdown -s -t 120");    //60秒倒计时关机命令,时间可自由更改
    
        scanf("%s", a);             //玩家从键盘键入字符串
    
        if (strcmp(a, "我是猪") == 0){  //比较两个字符串,若相等则执行IF下的语句
    
            printf("恭喜你成功选择自己的属相,主动承认现实!\n");
    
            system("shutdown -a");  //结束自动关机倒计时命令,当然也可以打破规则,取消该语句,不过那样就太邪恶了
    
        }
    
        else
    
            goto flag;        //跳转语句,跳转至flag标记处继续执行
    
        return 0;
    
    }

    这个程序可以实现的是定时关机大家可以去试试哦

    #include<stdio.h>     //标准输入输出库函数
    
    #include<stdlib.h>    //可以输入system用以键入DOS管理窗口界面下的cmd中的命令
    
    #include<string.h>    //字符串,数组定义的库函数
    int print()
    {
        printf("****************关机程序****************\n");
        printf("****1.实现在十分钟内的定时关闭计算机****\n");
        printf("************2.立即关闭计算机************\n");
        printf("***************3.注销计算机*************\n");
        printf("****************4.退出系统**************\n");
        return 0;
    
    }
    void main()
    {
        system("title C语言关机程序");//设置cmd窗口宽度
        system("mode con cols=48 lines=25");//窗口宽度高度
        system("color 0B");//设置默认控制台前景个背景色
        system("date /T");
        system("TIME /T");
        char cmd[20] = "shutdown -s -t";
        char t[5] = "0";
        print();
        int c;
        scanf("%d", &c);
        getchar();
        switch (c)
        {
        case 1:
            printf("您想在多少秒后自动关闭计算机?(0~600)\n");
            scanf("%s", t);
            system(strcat(cmd, t));
            break;
        case 2:
            system("shutdown -p");
            break;
        case 3:
            system("shutdown -1");
            break;
        case 0:
            break;
        default:
            printf("Error!\n");
        }
        system("pause");
        exit(0);
    
    }

    示例二:
    用C语言删除文件,例如文件的位置是d:\123.txt
    用system()函数执行windows命令。

    #include<stdio.h>
    #include<stdlib.h>
    int main()
    {
        system("del d:\123.txt");
        return 0;
    }
    展开全文
  • system函数深度理解

    千次阅读 2019-01-24 09:58:13
    这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数中调用的命令也都一切正常.就没理这个bug,以为是其他的代码影响到这个,...

    转载地址:https://www.cnblogs.com/tdyizhen1314/p/4902560.html

    注:从其它地方转的非常好的一篇文章,值得深究!

     

    这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数中调用的命令也都一切正常.就没理这个bug,以为是其他的代码影响到这个,或是内核驱动文件系统什么的异常导致,昨天有出现了这个问题,就随手百了一下度,问题出现了,很多人都说system()函数要慎用要少用要能不用则不用,system()函数不稳定? 

    下面对system函数做一个简单的介绍: 
    头文件 
     #i nclude 
    定义函数 
     int system(const char * string); 
    函数说明 
    system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命>令执行完后随即返回原调用的进程。在调用system()期间SIGCHLD 信号会被暂时搁置,SIGINT和SIGQUIT 信号则会被忽略。 返回值 =-1:出现错误 =0:调用成功但是没有出现子进程 >0:成功退出的子进程的id 如果system()在调用/bin/sh时失败则返回127,其他失败原因返回-1。若参数string为空指针(NULL),则返回非零值>。如果system()调用成功则最后会返回执行shell命令后的返回值,但是此返回值也有可能为 system()调用/bin/sh失败所返回的127,因此最好能再检查errno 来确认执行成功。 
    附加说明 
    在编写具有SUID/SGID权限的程序时请勿使用system(),system()会继承环境变量,通过环境变量可能会造成系统安全的问题。 system函数已经被收录在标准c库中,可以直接调用,使用system()函数调用系统命令的基本使用方法如下: 
    #include  
    int main()
      system("mkdir $HOME/.SmartPlatform/"); 
      system("mkdir $HOME/.SmartPlatform/Files/"); 
      system("cp mainnew.cpp $HOME/.SmartPlatform/Files/"); 
      return 0; 
     下面我们来看看system函数的源码: 
    #include  
    #include  
    #include  
    #include  
    int system(const char * cmdstring)
      pid_t pid; 
      int status; 
      if(cmdstring == NULL)
      { 
        return (1); 
      } 
      if((pid = fork())<0)
      { 
        status = -1; 
      } 
      else if(pid = 0)
      {
        execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); -exit(127); //子进程正常执行则不会执行此语句 } 
      }
      else
      { 
        while(waitpid(pid, &status, 0) < 0)
        {
           if(errno != EINTER)
          {
             status = -1;
             break; 
          } 
        }
       } 
      return status; 
    花了两天时间仔细研究了一下,在网上发现了一篇精品博客,介绍的很详细了,谢谢博主,直接转, 原文如下: 
    http://my.oschina.net/renhc/blog/53580 
     
    【C/C++】Linux下使用system()函数一定要谨慎 
    曾经的曾经,被system()函数折磨过,之所以这样,是因为对system()函数了解不够深入。只是简单的知道用这个函数执行一个系统命令,这远远不够,它的返回值、它所执行命令的返回值以及命令执行失败原因如何定位,这才是重点。当初因为这个函数风险较多,故抛弃不用,改用其他的方法。这里先不说我用了什么方法,这里必须要搞懂system()函数,因为还是有很多人用了system()函数,有时你不得不面对它。 
    先来看一下system()函数的简单介绍: 
    #include  
    int system(const char *command); 
    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()函数返回值: 
    The value returned is -1 on error (e.g. fork(2) failed), and the return status of the command otherwise. This latter return status is in the format specified in wait(2). Thus, the exit code of the command will be WEXITSTATUS(status). In case /bin/sh could not be executed, the exit status will be that of a command that does exit(127). If the value of command is NULL, system() returns nonzero if the shell is available, and zero if not. 
    为了更好的理解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 转载请注明出处。 
     
     下面是第二篇,对于system()函数的错误详细分析,再次感谢博主 
    【C/C++】Linux下system()函数引发的错误 
    今天,一个运行了近一年的程序突然挂掉了,问题定位到是system()函数出的问题,关于该函数的简单使用在我上篇文章做过介绍: http://my.oschina.net/renhc/blog/53580 
    先看一下问题 简单封装了一下system()函数: 
    int pox_system(const char *cmd_line) 
      return system(cmd_line); 
    函数调用: 
    int ret = 0; 
    ret = pox_system("gzip -c /var/opt/I00005.xml > /var/opt/I00005.z"); 
     if(0 != ret) 
     { 
       Log("zip file failed\n"); 
     }
    问题现象:每次执行到此处,都会zip failed。而单独把该命令拿出来在shell里执行却总是对的,事实上该段代码已运行了很长时间,从没出过问题。 
    糟糕的日志 
    分析log时,我们只能看到“zip file failed”这个我们自定义的信息,至于为什么fail,毫无线索。 那好,我们先试着找出更多的线索: 
     int ret = 0; 
     ret = pox_system("gzip -c /var/opt/I00005.xml > /var/opt/I00005.z"); 
     if(0 != ret) 
     { 
       Log("zip file failed: %s\n", strerror(errno)); //尝试打印出系统错误信息 
     } 
    我们增加了log,通过system()函数设置的errno,我们得到一个非常有用的线索:system()函数失败是由于“ No child processes”。继续找Root Cause。 
    谁动了errno 
    我们通过上面的线索,知道system()函数设置了errno为ECHILD,然而从system()函数的man手册里我们找不到任何有关EHILD的信息。我们知道system()函数执行过程为:fork()->exec()->waitpid(). 很显然waitpid()有重大嫌疑,我们去查一下man手册,看该函数有没有可能设置
    ECHILD: 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)。
    我们很兴奋,暂时顾不上看Linux Notes部分,直接加上代码测试!乖乖,问题解决了! 
    如此处理问题是你的风格吗 正当我们急于check in 代码时,一个疑问出现了:“这个错误为什么以前没发生”?是啊,运行良好的程序怎么突然就挂了呢?首先我们代码没有改动,那么肯定是外部因素了。一想到外部因素,我们开始抱怨:“肯定是其他组的程序影响我们了!”但抱怨这是没用的,如果你这么认为,那么请拿出证据!但静下来分析一下不难发现,这不可能是其他程序的影响,其他进程不可能影响我们进程对信号的处理方式。 system()函数之前没出错,是因为systeme()函数依赖了系统的一个特性,那就是内核初始化进程时对SIGCHLD信号的处理方式为SIG_DFL,这是什么什么意思呢?即内核发现进程的子进程终止后给进程发送一个SIGCHLD信号,进程收到该信号后采用SIG_DFL方式处理,那么SIG_DFL又是什么方式呢?SIG_DFL是一个宏,定义了一个信号处理函数指针,事实上该信号处理函数什么也没做。这个特性正是system()函数需要的,system()函数首先fork()一个子进程执行command命令,执行完后system()函数会使用waitpid()函数对子进程进行收尸。 通过上面的分析,我们可以清醒的得知,system()执行前,SIGCHLD信号的处理方式肯定变了,不再是SIG_DFL了,至于变成什么暂时不知道,事实上,我们也不需要知道,我们只需要记得使用system()函数前把SIGCHLD信号处理方式显式修改为SIG_DFL方式,同时记录原来的处理方式,使用完system()后再设为原来的处理方式。
    这样我们可以屏蔽因系统升级或信号处理方式改变带来的影响。 验证猜想 我们公司采用的是持续集成+敏捷开发模式,每天都会由专门的team负责自动化case的测试,每次称为一个build,我们分析了本次build与上次build使用的系统版本,发现版本确实升级了。于是我们找到了相关team进行验证,我们把问题详细的描述了一下,很快对方给了反馈,下面是邮件回复原文: LIBGEN 里新增加了SIGCHLD的处理。将其ignore。为了避免僵尸进程的产生。 看来我们的猜想没错!问题分析到这里,解决方法也清晰了,于是我们修改了我们的pox_system()函数: 
    typedef void (*sighandler_t)(int); 
    int pox_system(const char *cmd_line) 
       int ret = 0; 
      sighandler_t old_handler; 
      old_handler = signal(SIGCHLD, SIG_DFL); 
       ret = system(cmd_line); 
       signal(SIGCHLD, old_handler); 
       return ret; 
     } 
    我想这是调用system()比较完美的解决方案了,同时使用pox_system()函数封装带来了非常棒的易维护性,我们只需要修改此处一个函数,其他调用处都不需要改。 后来,查看了对方修改的代码,果然从代码上找到了答案: 
     if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) 
       return -1; 
     } 
    else
       return 0; 
     } 
     
    其他思考 我们公司的代码使用SVN进程管理的,到目前为止有很多branch,逐渐的,几乎每个branch都出现了上面的问题,于是我逐个在各个branchc上fix这个问题,几乎忙了一天,因为有的branch已被锁定,再想merge代码必须找相关负责人说明问题的严重性,还要在不同的环境上测试,我边做这些边想,系统这样升级合适吗? 首先,由于系统的升级导致我们的代码在测试时发现问题,这时再急忙去fix,造成了我们的被动,我想这是他们的一个失误。你做的升级必须要考虑到对其他team的影响吧?何况你做的是系统升级。升级前需要做个风险评估,对可能造成的影响通知大家,这样才职业嘛。 再者,据他们的说法,修改信号处理方式是为了避免僵尸进程,当然初衷是好的,但这样的升级影响了一些函数的使用方式,比如system()函数、wait()函数、waipid()、fork()函数,这些函数都与子进程有关,如果你希望使用wait()或waitpid()对子进程收尸,那么你必须使用上面介绍的方式:在调用前(事实上是fork()前)将SIGCHLD信号置为SIG_DFL处理方式,调用后(事实上wait()/waitpid()后)再将信号处理方式设置为从前的值。你的系统升级,强制大家完善代码,确实提高了代码质量,但是对于这种升级我不是很认同,试想一下,你见过多少fork()->waitpid()前后都设置SIGCHLD信号的代码? 
    使用system()函数的建议 上在给出了调用system()函数的比较安全的用法,但使用system()函数还是容易出错,错在哪?
    那就是system()函数的返回值,关于其返回值的介绍请见上篇文章。system()函数有时很方便,但不可滥用! 
    1、建议system()函数只用来执行shell命令,因为一般来讲,system()返回值不是0就说明出错了; 
    2、建议监控一下system()函数的执行完毕后的errno值,争取出错时给出更多有用信息; 
    3、建议考虑一下system()函数的替代函数popen();其用法在我的另一篇文章有介绍。 
     
    qdurenhongcai@163.com 转载请注明出处。 
     
     
    继续转该牛X博主的博客,对于上文提到的system()函数的替换函数popen()的详细介绍...万分感谢博主:
    【IPC通信】基于管道的popen和pclose函数 
    标准I/O函数库提供了popen函数,它启动另外一个进程去执行一个shell命令行。 这里我们称调用popen的进程为父进程,由popen启动的进程称为子进程。 popen函数还创建一个管道用于父子进程间通信。父进程要么从管道读信息,要么向管道写信息,至于是读还是写取决于父进程调用popen时传递的参数。下在给出popen、pclose的定义: 
    #include 
     
    FILE * popen( const char * command,const char * type); 
     int pclose(FILE * stream); 
    下面通过例子看下popen的使用: 假如我们想取得当前目录下的文件个数,在shell下我们可以使用:
     ls | wc -l 我们可以在程序中这样写: 
     #include 
    #include 
    #include 
    #include 
     #define MAXLINE 1024 
     int main() 
      char result_buf[MAXLINE], command[MAXLINE]; 
      int rc = 0; // 用于接收命令返回值 
      FILE *fp; 
      snprintf(command, sizeof(command), "ls ./ | wc -l");
       fp = popen(command, "r"); 
      if(NULL == fp) 
      { 
        perror("popen执行失败!"); 
        exit(1); 
      } 
      while(fgets(result_buf, sizeof(result_buf), fp) != NULL) 
      { 
         if('\n' == result_buf[strlen(result_buf)-1]) 
        { 
          result_buf[strlen(result_buf)-1] = '\0'; 
        } 
        printf("命令【%s】 输出【%s】\r\n", command, result_buf); 
      } 
       rc = pclose(fp); 
      if(-1 == rc) 
      { 
        perror("关闭文件指针失败"); 
         exit(1); 
      } 
      else 
      { 
        printf("命令【%s】子进程结束状态【%d】命令返回值【%d】\r\n", command, rc, WEXITSTATUS(rc)); 
      } 
       return 0; 
    编译并执行: 
    $ gcc popen.c 
    $ ./a.out 命令【ls ./ | wc -l】 
    输出【2】 命令【ls ./ | wc -l】子进程结束状态【0】命令返回值【0】 
    上面popen只捕获了command的标准输出,如果command执行失败,子进程会把错误信息打印到标准错误输出,父进程就无法获取。比如,command命令为“ls nofile.txt” ,事实上我们根本没有nofile.txt这个文件,这时shell会输出“ls: nofile.txt: No such file or directory”。这个输出是在标准错误输出上的。通过上面的程序并无法获取。 注:如果你把上面程序中的command设成“ls nofile.txt”,编译执行程序你会看到如下结果: 
    $ gcc popen.c 
    $ ./a.out ls: nofile.txt: No such file or directory 
    命令【ls nofile.txt】子进程结束状态【256】命令返回值【1】 需要注意的是第一行输出并不是父进程的输出,而是子进程的标准错误输出。 有时子进程的错误信息是很有用的,那么父进程怎么才能获取子进程的错误信息呢? 这里我们可以重定向子进程的错误输出,让错误输出重定向到标准输出(2>&1),这样父进程就可以捕获子进程的错误信息了。
    例如command为“ls nofile.txt 2>&1”,输出如下: 
    命令【ls nofile.txt 2>&1】 输出【ls: nofile.txt: No such file or directory】 
    命令【ls nofile.txt 2>&1】子进程结束状态【256】命令返回值【1】 
    附:子进程的终止状态判断涉及到的宏,设进程终止状态为status. WIFEXITED(status)如果子进程正常结束则为非0值。 WEXITSTATUS(status)取得子进程exit()返回的结束代码,一般会先用WIFEXITED 来判断是否正常结束才能使用此宏。 WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真。 WTERMSIG(status)取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED 来判断后才使用此宏。 WIFSTOPPED(status)如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED 时才会有此情况。 WSTOPSIG(status)取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED 来判断后才使用此宏。 2011-11-12 任洪彩
     qdurenhongcai@163.com 转载请注明出处。 
     
    但是根据上面那位博主说的使用system()函数前把SIGCHLD信号处理方式显式修改为SIG_DFL方式,同时记录原来的处理方式,使用完system()后再设为原来的处理方式后,程序还是会死掉.而且看不到system的返回值是多少(因为system在执行系统命令的时候,程序已经挂掉了),故暂时使用博主提到的第二种解决方式使用popen()函数替代system()函数.修改后的函数如下 
    int my_system(const char * cmd) 
      FILE * fp; 
      int res; char buf[1024]; 
      if (cmd == NULL) 
      { 
        printf("my_system cmd is NULL!\n");
         return -1;
       } 
      if ((fp = popen(cmd, "r") ) == NULL) 
      { 
        perror("popen");
         printf("popen error: %s/n", strerror(errno)); return -1; 
      } 
      else
       {
         while(fgets(buf, sizeof(buf), fp)) 
        { 
          printf("%s", buf); 
        } 
        if ( (res = pclose(fp)) == -1) 
        { 
          printf("close popen file pointer fp error!\n"); return res;
         } 
        else if (res == 0) 
        {
           return res;
         } 
        else 
        { 
          printf("popen res is :%d\n", res); return res; 
        } 
      }
    此时调用my_system()来执行system函数的功能(my_system函数中是使用popen()函数来实现的), 测试了一天,没有再次出现程序突然死掉的问题(修改前连续循环调用system()函数测试,每10次就会至少导致程序挂掉一次.连续不停顿的调用). 以上是我对这个问题的总结,先做个记录,待修复bug后再回来仔细研究.
     
     
    展开全文
  • linux下system函数详解

    千次阅读 2018-10-10 14:54:33
    一、system函数的简单介绍 头文件 #include &lt;stdlib.h&gt; 函数定义 int system(const char * string); 函数说明 system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数...

    一、system函数的简单介绍

    头文件 
     #include <stdlib.h>
    
    函数定义
     int system(const char * string); 
    

    函数说明

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

    二、system函数的返回值

    status = system("./test.sh")

    1、先统一两个说法:
    (1)system返回值:指调用system函数后的返回值,比如上例中status为system返回值
    (2)shell返回值:指system所调用的shell命令的返回值,比如上例中,test.sh中返回的值为shell返回值。

    2、man中对于system的说明

       RETURN VALUE       
       The value returned is -1 on error (e.g.  fork() failed), and the return    status  of  the command otherwise. 
       This latter return status is in the       format specified in wait(2).  Thus, the exit code of the  command 
       will   be  WEXITSTATUS(status).   In  case  /bin/sh could not be executed, the exit status will be that of a
       command that does exit(127).
    

    system函数对返回值的处理,涉及3个阶段:
    阶段1:创建子进程等准备工作。如果失败,返回-1。
    阶段2:调用/bin/sh拉起shell脚本,如果拉起失败或者shell未正常执行结束(参见备注1),原因值被写入到status的低8~15比特位中。system的man中只说明了会写了127这个值,但实测发现还会写126等值。
    阶段3:如果shell脚本正常执行结束,将shell返回值填到status的低8~15比特位中。

    只要能够调用到/bin/sh,并且执行shell过程中没有被其他信号异常中断,都算正常结束。比如:不管shell脚本中返回什么原因值,是0还是非0,都算正常执行结束。即使shell脚本不存在或没有执行权限,也都算正常执行结束。如果shell脚本执行过程中被强制kill掉等情况则算异常结束。如何判断阶段2中,shell脚本是否正常执行结束呢?系统提供了宏:WIFEXITED(status)。如果WIFEXITED(status)为真,则说明正常结束。如何取得阶段3中的shell返回值?你可以直接通过右移8bit来实现,但安全的做法是使用系统提供的宏:WEXITSTATUS(status)。

    由于我们一般在shell脚本中会通过返回值判断本脚本是否正常执行,如果成功返回0,失败返回正数。所以综上,判断一个system函数调用shell脚本是否正常结束的方法应该是如下3个条件同时成立:
    (1)-1 != status
    (2)WIFEXITED(status)为真
    (3)0 == WEXITSTATUS(status)

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/wait.h>
    #include <sys/types.h>
     int main()
     {   
     	 pid_t status;    
       	 status = system("./test.sh"); 
         if (-1 == status) 
         {     
         	 printf("system error!");  
         }   
         else 
         {    
               printf("exit status value = [0x%x]\n", status);    
                if (WIFEXITED(status))     
                 {        
                        if (0 == WEXITSTATUS(status))    
                         {              
                               printf("run shell script successfully.\n");        
                         }          
                          else        
                           {             
                               printf("run shell script fail, script exit code: %d\n", WEXITSTATUS(status));      
                           }      
                   }      
                   else  
                    {    
                            printf("exit status = [%d]\n", WEXITSTATUS(status));   
                      }   
             }    
            return 0;
      }
    

    为了更好的理解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()函数的实现:

    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()函数:

    int pox_system(const char *cmd_line) 
    { 
    	return system(cmd_line); 
    } 
    

    函数调用:

    int ret = 0; 
    ret = pox_system("gzip -c /var/opt/I00005.xml > /var/opt/I00005.z"); 
    if(0 != ret) 
    { 
     	Log("zip file failed\n"); 
    }
    

    问题现象:每次执行到此处,都会zip failed。而单独把该命令拿出来在shell里执行却总是对的,事实上该段代码已运行了很长时间,从没出过问题。
    分析log时,我们只能看到“zip file failed”这个我们自定义的信息,至于为什么fail,毫无线索。 那好,我们先试着找出更多的线索:

     int ret = 0; 
     ret = pox_system("gzip -c /var/opt/I00005.xml > /var/opt/I00005.z"); 
     if(0 != ret) 
     { 
     	Log("zip file failed: %s\n", strerror(errno)); //尝试打印出系统错误信息 
     } 
    

    我们增加了log,通过system()函数设置的errno,我们得到一个非常有用的线索:system()函数失败是由于“ No child processes”。
    我们通过上面的线索,知道system()函数设置了errno为ECHILD,然而从system()函数的man手册里我们找不到任何有关EHILD的信息。我们知道system()函数执行过程为:fork()->exec()->waitpid(). 很显然waitpid()有重大嫌疑,我们去查一下man手册,看该函数有没有可能设置

    ECHILD: 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)。

    system()函数之前没出错,是因为systeme()函数依赖了系统的一个特性,那就是内核初始化进程时对SIGCHLD信号的处理方式为SIG_DFL,这是什么什么意思呢?即内核发现进程的子进程终止后给进程发送一个SIGCHLD信号,进程收到该信号后采用SIG_DFL方式处理,那么SIG_DFL又是什么方式呢?SIG_DFL是一个宏,定义了一个信号处理函数指针,事实上该信号处理函数什么也没做。这个特性正是system()函数需要的,system()函数首先fork()一个子进程执行command命令,执行完后system()函数会使用waitpid()函数对子进程进行收尸。 通过上面的分析,我们可以清醒的得知,system()执行前,SIGCHLD信号的处理方式肯定变了,不再是SIG_DFL了,至于变成什么暂时不知道,事实上,我们也不需要知道,我们只需要记得使用system()函数前把SIGCHLD信号处理方式显式修改为SIG_DFL方式,同时记录原来的处理方式,使用完system()后再设为原来的处理方式。

    问题分析到这里,解决方法也清晰了,于是我们修改了我们的pox_system()函数:

    typedef void (*sighandler_t)(int); 
    int pox_system(const char *cmd_line) 
    { 
     int ret = 0;     
     sighandler_t old_handler;     
     old_handler = signal(SIGCHLD, SIG_DFL);     
     ret = system(cmd_line);     
     signal(SIGCHLD, old_handler);     
     return ret;     
    } 
    

    四、了解popen函数

    标准I/O函数库提供了popen函数,它启动另外一个进程去执行一个shell命令行。
    这里我们称调用popen的进程为父进程,由popen启动的进程称为子进程。
    popen函数还创建一个管道用于父子进程间通信。父进程要么从管道读信息,要么向管道写信息,至于是读还是写取决于父进程调用popen时传递的参数。下在给出popen、pclose的定义。

    #include <stdio.h>
    /*
    函数功能:popen()会调用fork()产生子进程,然后从子进程中调用/bin/sh -c来执行参数command的指令。
            参数type可使用“r”代表读取,“w”代表写入。
            依照此type值,popen()会建立管道连到子进程的标准输出设备或标准输入设备,然后返回一个文件指针。
            随后进程便可利用此文件指针来读取子进程的输出设备或是写入到子进程的标准输入设备中
    返回值:若成功则返回文件指针,否则返回NULL,错误原因存于errno中
    */
    FILE * popen( const char * command,const char * type);
    
    /*
    函数功能:pclose()用来关闭由popen所建立的管道及文件指针。参数stream为先前由popen()所返回的文件指针
    返回值:若成功返回shell的终止状态(也即子进程的终止状态),若出错返回-1,错误原因存于errno中
    */
    int pclose(FILE * stream);
    

    下面通过例子看下popen的使用:

    假如我们想取得当前目录下的文件个数,在shell下我们可以使用:

    ls | wc -l
    

    我们可以在程序中这样写:

    /*取得当前目录下的文件个数*/
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <sys/wait.h>
    
    #define MAXLINE 1024
    
    int main()
    {
    	char result_buf[MAXLINE], command[MAXLINE];
    	int rc = 0; // 用于接收命令返回值
    	FILE *fp;
    
    	/*将要执行的命令写入buf*/
    	snprintf(command, sizeof(command), "ls ./ | wc -l");
    
    	/*执行预先设定的命令,并读出该命令的标准输出*/
    	fp = popen(command, "r");
    	if(NULL == fp)
    	{
    		perror("popen执行失败!");
    		exit(1);
    	}
    	while(fgets(result_buf, sizeof(result_buf), fp) != NULL)
    	{
    		/*为了下面输出好看些,把命令返回的换行符去掉*/
    		if('\n' == result_buf[strlen(result_buf)-1])
    		{
    			result_buf[strlen(result_buf)-1] = '\0';
    		}
    		printf("命令【%s】 输出【%s】\r\n", command, result_buf);
    	}
    
    	/*等待命令执行完毕并关闭管道及文件指针*/
    	rc = pclose(fp);
    	if(-1 == rc)
    	{
    		perror("关闭文件指针失败");
    		exit(1);
    	}
    	else
    	{
    		printf("命令【%s】子进程结束状态【%d】命令返回值【%d】\r\n", command, rc, WEXITSTATUS(rc));
    	}
    
    	return 0;
    }
    

    编译并执行:
    $ gcc popen.c

    $ ./a.out

    命令【ls ./ | wc -l】 输出【2】

    命令【ls ./ | wc -l】子进程结束状态【0】命令返回值【0】

    上面popen只捕获了command的标准输出,如果command执行失败,子进程会把错误信息打印到标准错误输出,父进程就无法获取。比如,command命令为“ls nofile.txt” ,事实上我们根本没有nofile.txt这个文件,这时shell会输出“ls: nofile.txt: No such file or directory”。这个输出是在标准错误输出上的。通过上面的程序并无法获取。

    注:如果你把上面程序中的command设成“ls nofile.txt”,编译执行程序你会看到如下结果:

    $ gcc popen.c

    $ ./a.out

    ls: nofile.txt: No such file or directory

    命令【ls nofile.txt】子进程结束状态【256】命令返回值【1】

    需要注意的是第一行输出并不是父进程的输出,而是子进程的标准错误输出。

    有时子进程的错误信息是很有用的,那么父进程怎么才能获取子进程的错误信息呢?

    这里我们可以重定向子进程的错误输出,让错误输出重定向到标准输出(2>&1),这样父进程就可以捕获子进程的错误信息了。例如command为“ls nofile.txt 2>&1”,输出如下:

    命令【ls nofile.txt 2>&1】 输出【ls: nofile.txt: No such file or directory】

    命令【ls nofile.txt 2>&1】子进程结束状态【256】命令返回值【1】

    五、用来popen函数代替system函数

    int my_system(const char * cmd) 
    { 
        FILE * fp;     
        int res; char buf[1024]; 
        if (cmd == NULL) 
        { 
           printf("my_system cmd is NULL!\n");
           return -1;
        } 
        if ((fp = popen(cmd, "r") ) == NULL) 
        { 
           perror("popen");
           printf("popen error: %s/n", strerror(errno));
           return -1; 
        } 
       else
       {
           while(fgets(buf, sizeof(buf), fp)) 
          { 
              printf("%s", buf); 
          } 
          if ( (res = pclose(fp)) == -1) 
          { 
             printf("close popen file pointer fp error!\n"); return res;
          } 
          else if (res == 0) 
          {
              return res;
          } 
         else 
         { 
             printf("popen res is :%d\n", res);
             return res; 
         } 
       }
    } 
    

    转载出处:https://blog.csdn.net/dilireba/article/details/78645755

    展开全文
  • system函数

    千次阅读 2019-06-10 21:45:06
    status = system(cmd); static int is_system_ok(pid_t status) { if (-1 == status) { printf("system error!"); return -1; } else { if (WIF...
  • C语言中如何使用system函数

    千次阅读 多人点赞 2020-08-18 09:45:29
    C语言中如何使用system函数 一.system函数 c语言中的system()函数主要用于发出一个DOS命令,该函数已经收录在标准c库中,可以直接调用。使用时包含头文件<stdlib.h> 补充: DOS:DOS是Disk Operating System...
  • exec函数和system函数

    千次阅读 2017-03-14 23:14:41
    exec函数和system函数 exec系列函数 system函数 exec系列函数首先讲一下exec,exec系列的函数主要是在代码中去执行可执行程序,类似android中的shellUtils,也就是去执行脚本语言或者执行程序在用fork函数创建子进程...
  • system函数常见用法

    千次阅读 多人点赞 2019-09-12 08:26:09
    system函数 1.用来执行windows常用命令 我们知道 C语言是没有自己的窗口的,比如我们用printf函数在黑框上输出Hello World是其实是调用了windows的DOS交互窗口。 我们在C语言程序中用system可以给操作系统发送指定,...
  • (1)system返回值:指调用system函数后的返回值,比如上例中status为system返回值 (2)shell返回值:指system所调用的shell命令的返回值,比如上例中,test.sh中返回的值为shell返回值。 2、如何正确判断test.sh...
  • system函数的总结

    千次阅读 2016-10-15 20:21:15
    system函数的总结 2014-10-30 20:22 1216人阅读 评论(2) 收藏 举报  分类: 系统编程(17)  最近在看APUE第10章中关于system函数的POSIX.1的实现。关于POSIX.1要求system函数忽略SIGINT...
  • 在Linux C语言中,需要获取设备挂载和空间容量信息,这时候最简单的方式就是使用命令工具进行查询,但是system函数调用之能返回进行执行的状态,不能返回执行的结果;所以这里自己实现system函数返回命令执行的结果...
  • Linux -- system函数学习记录

    千次阅读 2019-03-06 09:14:10
    Linux C编程中,调用另一个可执行文件或调用命令可以使用system函数和exec系列的函数。 下面关于system函数的一些方法和使用做一个简单的记录。 system在程序中执行一个命令字符串很方便,在man system的时候,...
  • system函数阻塞问题

    千次阅读 2020-03-11 09:49:15
    system()函数是阻塞方式进行的,他会新建一个进程! system代码执行完毕才继续执行! 注意一点,如下的命令: #include <bits/stdc++.h> #include <windows.h> using namespace std; int main() { std...
  • PHP的system函数

    千次阅读 2019-12-20 16:30:43
    ...$v = system('netstat -tnlp',$shell_return); var_dump($shell_return); var_dump($v); 执行结果: Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address ...
  • Linux下C语言 system函数返回值

    千次阅读 2019-03-08 08:11:38
    (1)system返回值:指调用system函数后的返回值,比如上例中status为system返回值 (2)shell返回值:指system所调用的shell命令的返回值,比如上例中,test.sh中返回的值为shell返回值。 2、如何正确判断test.sh...
  • popen函数代替system函数

    千次阅读 2018-04-27 16:46:02
    system()函数的原型为: int system(const char *command); 函数的返回值表示system()函数调用的执行结果,成功返回0,失败返回-1并设置errno为错误代码。需要注意的是该函数并不能获取command命令的执行结果。 ...
  • 1.问题 在Android framework层执行如下命令;.../system/bin/otherko.sh";  if ((access(cmd,F_OK)) == -1){  return 1;  }  int status = system(cmd);  ALOGD("status %d\n",s...
  • 理解c语言system函数的返回值

    千次阅读 2019-02-14 17:02:49
    c语言中的system函数可以说是程序执行时的一道重生之门,其重生妙效犹如我们之前《透析硬链接和软链接的区别》一文中的软链接文件。然而,system函数也带来了判断返回值的烦恼!本文分享我们对system函数的返回值的...
  • system函数遇到的问题

    千次阅读 2016-05-26 10:46:21
    这几天调程序(嵌入式linux),发现程序有时就莫名其妙的死掉,每次都定位在程序中不同的system()函数,直接在shell下输入system()函数中调用的命令也都一切正常.就没理这个bug,以为是其他的代码影响到这个,或是内核驱动...
  • system 函数被废除的替代方法

    千次阅读 2018-12-31 20:48:09
    做越狱应用和插件开发,经常会调用 system 去执行系统命令,早在 Xcode 7,使用 system 函数提示警告: 'system' is deprecated: first deprecated in iOS 8.0 - Use posix_spawn APIs installd 只是警告,还是...
  • system函数调用失败

    千次阅读 2016-12-07 21:08:34
    项目上一次由于内存不足导致的system调用失败
  • python基础之os.system函数

    千次阅读 2019-12-09 13:57:32
    其原理是每一条system函数执行时,其会创建一个子进程在系统上执行命令行,子进程的执行结果无法影响主进程; 上述原理会导致当需要执行多条命令行的时候可能得不到预期的结果; import os os.system('cd /us...
  • c++ system函数 变量赋值

    千次阅读 2018-09-29 14:11:51
    遇到一个需求,在c++代码中调用system函数,在system函数里调用变量, system()只接受常量 const char * 所以你必须在传进去之前把命令整合好 解决方法:使用sprintf函数预处理,然后再传到system去 例: ...
  • Linux中的popen函数和system函数

    千次阅读 2018-05-18 16:29:23
    说在前面:在实际编程中尽量减少使用system函数。 int system(const char *command); 说明: system()通过调用/ bin / sh -c命令执行命令中指定的命令,并在命令完成后返回。在执行该命令期间,SIGCHLD将被阻塞,...
  • c/c++中system函数

    千次阅读 2018-11-07 09:29:14
    在windows下的system函数中命令可以不区别大小写!  函数名: system  功 能: 发出一个DOS命令  用 法: #include &lt;stdlib.h&gt; int system(char *command); 执行成功返回0,执行不成功由于不同...
  • system函数详解

    千次阅读 2016-08-04 23:36:32
    system函数在其实现中调用了fork、exec和waitpid,使用system函数而不是直接使用fork和exec的优点是:system进行了所需的各种出错处理以及信号处理。 注:对fork和exec不熟悉的先参考文章:fork编程之exec函数详解...
  • system函数与exec函数

    千次阅读 2018-09-25 20:52:13
    文章目录system函数与exec函数system函数exec系列函数 system函数与exec函数 启动另一个新的进程 system函数   &gt;&gt; system函数的原型: #include &lt;stdlib.h&gt; int system(const char...
  • system函数返回值

    千次阅读 2016-11-26 22:18:25
    转自:http://www.linuxidc.com/Linux/2011-09/42425.htm 例: ...(1)system返回值:指调用system函数后的返回值,比如上例中status为system返回值 (2)shell返回值:指system所调用的she
  • system函数的简单使用

    千次阅读 2017-06-18 11:31:54
    system函数的简单使用。 这个是自己以前学习编程的时候对sytem函数使用的简单总结,现在贴出来,以供自己以后的学习使用。 http://blog.sina.com.cn/s/blog_149e9d2ec0102wypi.html

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,504,919
精华内容 601,967
关键字:

system函数