system的调用和返回

首先引用另外一篇blog里对system的分析:

例:
1.status = system("./test.sh");  

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

2、如何正确判断test.sh是否正确执行?
仅判断status是否==0?或者仅判断status是否!=-1?

都错!

3、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比特位中。
备注1:
只要能够调用到/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)

注意:
根据以上分析,当shell脚本不存在、没有执行权限等场景下时,以上前2个条件仍会成立,此时WEXITSTATUS(status)为127,126等数值。
所以,我们在shell脚本中不能将127,126等数值定义为返回值,否则无法区分中是shell的返回值,还是调用shell脚本异常的原因值。shell脚本中的返回值最好多1开始递增。

判断shell脚本正常执行结束的健全代码如下:
#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;
}
WIFEXITED(stat_val) Evaluates to a non-zero value if status
was returned for a child process that
terminated normally.

WEXITSTATUS(stat_val) If the value of WIFEXITED(stat_val) is
non-zero, this macro evaluates to the
low-order 8 bits of the status argument
that the child process passed to _exit()
or exit(), or the value the child
process returned from main().
言归正传,下面这段代码则会导致程序system调用总是返回-1

 
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

int main(int argc ,char *argv[])
{
    signal(SIGCHLD,SIG_IGN);
    int status = system("ls -l");
    if(status == -1) 
    {   
        printf("system fork faild !\n");
    }   
    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;
}

只是为什么呢?原来父进程将SIGCHLD信号ignore之后,system则总是返回-1。


 

在C语言中,system函数的主要功能是发出一个DOS命令,其原型为`int system(char *command);`,该函数已被收录在标准C库中,可以直接调用。以下是其使用方法及示例: ### 使用方法 - **头文件包含**:使用`system`函数需要包含`<stdlib.h>`头文件。 - **函数调用**:调用`system`函数时,传入一个指向字符串的指针,该字符串为要执行的DOS命令。函数返回值为命令执行后的返回状态。 ### 示例 #### 示例1:显示文件目录 ```c #include <stdlib.h> #include <stdio.h> int main(void) { printf("About to spawn and run a DOS command\n"); system("dir"); return 0; } ``` 此示例中,调用`system("dir")`来显示当前目录下的文件文件夹信息[^2][^5]。 #### 示例2:冻结屏幕 ```c #include <stdlib.h> #include <stdio.h> int main(void) { // 执行一些操作 printf("This is a test.\n"); system("pause"); return 0; } ``` `system("pause")`可以实现冻结屏幕,便于观察程序的执行结果[^2][^5]。 #### 示例3:清屏操作 ```c #include <stdlib.h> #include <stdio.h> int main(void) { printf("Before clear screen.\n"); system("CLS"); printf("After clear screen.\n"); return 0; } ``` `system("CLS")`可以实现清屏操作,注意在Windows下命令不区分大小写[^1][^2][^5]。 #### 示例4:改变控制台颜色 ```c #include <stdlib.h> #include <stdio.h> int main(void) { system("color 0A"); printf("The console color has been changed.\n"); return 0; } ``` `system("color 0A")`中,`color`后面的`0`是背景色代号(黑色),`A`是前景色代号(淡绿色)。各颜色代码如下:`0=黑色 1=蓝色 2=绿色 3=湖蓝色 4=红色 5=紫色 6=黄色 7=白色 8=灰色 9=淡蓝色 A=淡绿色 B=淡浅绿色 C=淡红色 D=淡紫色 E=淡黄色 F=亮白色`[^2][^5]。 #### 示例5:显示当前时间日期 ```c #include <stdlib.h> #include <stdio.h> int main(void) { system("time /T"); system("date /T"); return 0; } ``` `system("time /T")`显示当前时间,`system("date /T")`显示当前日期[^4]。 ### 注意事项 - 在Windows下的`system`函数中命令可以不区别大小写[^1]。 - 不同的操作系统对`system`函数执行的命令支持可能不同,上述示例主要适用于Windows操作系统。 - 使用`system`函数时要注意命令的合法性,避免执行危险或非法的命令。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值