http://blog.chinaunix.net/uid-24774106-id-3048281.html?page=3
遇到system调用脚本,结果返回了256的情况,那么如何判断脚本是否正常成功调用,即取到脚本的真正返回值
system是个综合的操作,分解开来看就是相当于执行了
1 fork 生成一个子进程。
2 在子进程执行 execl("/bin/sh","sh","-c" command,(char*)0);
3 waitpid
下面进入正题,返回值:
1 如果fork失败了,或者waitpid返回除了EINTR之外的错误,system返回 -1;
2 execl执行失败,其返回值如同shell执行了"exit(127)" 一样。(非法命令)
3 如果上述三步都执行成功,那么,system返回值是shell的终止状态。
如果/bin/sh拉起shell命令失败,或者是shell命令没有正常执行 (比如命令根本就是非法的命令),那么,将原因填入status的8~15位。
这样就比较容易根据system的返回值进行问题定位了:
-1:创建子进程失败
对于其它值,先用返回值除以256,商对应的含义如下:
0:命令运行成功
1:通用未知错误
2:误用shell命令
126:命令不可执行
127:没有找到命令
128:无效退出参数
130:命令通过Ctrl+C终止
255:退出状态码越界
libin@libin:~/program/C/Linux/system$ ./tsys "nosuchcmd"
sh: nosuchcmd: not found
status = 32512
normal termination,exit status = 127
我们看到了,nosuchcmd不是shell支持的命令,所以,shell命令返回了127,对于system函数,返回值为 127*256 = 32512;因为shell的返回值是 system返回值的8~15位。
如果shell顺利执行完毕,那么将shell的返回值填到system返回值的8~15位。
这里需要强调以下,所谓顺利执行完毕,并不是说,命令command执行成功,而是指 /bin/sh顺利调用,执行期间没有被信号异常终止,这都算是顺利执行完毕。
libin@libin:~/program/C/Linux/system$ ./tsys "ls /noexisted"
ls: 无法访问/noexisted: 没有那个文件或目录
status = 512
normal termination,exit status = 2
libin@libin:~/program/C/Linux/system$ ls /noexist
ls: 无法访问/noexist: 没有那个文件或目录
libin@libin:~/program/C/Linux/system$ echo $?
2
libin@libin:~/program/C/Linux/system$
我们看到了,虽然/noexist文件并不存在,ls这条命令执行出了错,但是仍然属于shell顺利执行完毕。 ls /noexist的错误吗是2,所以,system函数的返回值为 2*256 = 512.
所以,对于system函数,返回值是由两部分组成的,低8位值表示所执行的脚本在执行过程中所接收到的信号值,其余的位表示的脚本exit退出时所设置的值,
即脚本内exit退出是的值的低8位,在system返回值的低9-16位
各位可能比较感兴趣的是,如果我知道system的返回值,如何知道我的命令的返回值呢?手册中有这么一句话:
- Thus, the exit code of the command will be WEXITSTATUS(status)
看到了WEXITSTATUS(status),就是command的返回值。当然前提条件是shell命令顺利执行完毕。即:
- WIFEXITED(status) ! =0
#define _XOPEN_SOURCE
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
#include<sys/wait.h>
void pr_exit(int status)
{
printf("status = %d\n",status);
if(WIFEXITED(status))
{
printf("normal termination,exit status = %d\n",WEXITSTATUS(status));
}
else if(WIFSIGNALED(status))
{
printf("abnormal termination,signal number =%d%s\n",
WTERMSIG(status),
#ifdef WCOREDUMP
WCOREDUMP(status)?"core file generated" : "");
#else
"");
#endif
}
}
int main(int argc,char* argv[])
{
int status;
if(argc<2)
{
fprintf(stderr,"usage:tsys cmd\n");
return -1;
}
if((status = system(argv[1]) )<0)
{
fprintf(stderr,"system error\n");
return -2;
}
pr_exit(status);
return 0;
}