最近,我开始对python脚本进行一些测试。出于某种尴尬的原因,运行python脚本并检查其输出的模块以C语言编写,并添加了其他一些语言。这种方式现在对我来说更方便。
单个测试使用以下代码运行:
FILE *fd = NULL;
fd = popen("cmd", "r");
if(NULL == fd){
fprintf(stderr, "popen: failed\n");
return 1;
}
fprintf(stderr, "res = %d: %s\n", errno, strerror(errno));
int res = pclose(fd);
fprintf(stderr, "res = %d: %s\n", res, strerror(errno));
如您从上面看到的,代码仅在popen
的帮助下运行脚本并检查其退出状态。但是有一天,我遇到了popen
被给出错误论点的情况。这样的事情发生了:
fd = popen("python@$#!", "r");
测试模块已返回:
res = 0: Success
sh: 1: python@0!: not found
res = 32512: Success
因此,popen
会因上述错误而愉快地运行。并且只有pclose
返回了一些退出状态。 errno为zero
。在所有这些之间,shell也输出了它。
这是我的问题。如何检测Shell是否无法执行命令?该失败实际上可能是由于任何原因,但要点是该脚本不会事件启动。
没有标准C或POSIX库函数将errno
设置为零。当errno
不为NULL时,基于fd
打印错误消息是不合适的。错误号不是来自popen()
(或因为popen()
失败而未设置)。 res
确定后打印pclose()
;添加strerror(errno)
会遇到相同的问题(errno
中的信息可能完全不相关)。您可以在调用函数之前将errno
设置为零。如果函数返回故障指示,则可能需要查看errno
(查看函数的规格-是否定义为在故障时设置errno
?)。但是,即使成功,也可以通过函数将errno
设置为非零。即使操作成功,如果输出流未连接到终端,Solaris标准I / O仍将设置errno = ENOTTY
。它可能仍然可以
popen()
和pclose()
popen()
的POSIX规范没有很大帮助。在仅一种情况下,popen()
“必须失败”;其他一切都是“可能失败”。
但是,popen()
的详细信息更为有用,包括:
如果无法执行命令语言解释器,则
pclose()
返回的子终止状态应类似于使用pclose()
或pclose()
终止的命令语言解释器。
和
成功返回后,
exit(127)
应返回命令语言解释器的终止状态。否则,_exit(127)
应返回-1并设置errno以指示错误。
如果将十进制32512解释为十六进制,则会得到0x7F00。并且,如果您使用pclose()
中的pclose()
和WIFEXITED
宏,则会发现退出状态为WEXITSTATUS
(因为<sys/wait.h>
为十进制127
,并且退出状态编码为0x7F
返回的状态的高阶位。
127
告诉你孩子失败了。当然,执行的命令实际上可能以状态127退出自身;这不可避免地会造成混淆,解决该问题的唯一方法是避免退出状态在126至128 +“最大信号数”范围内(如果有63个已识别的信号,则可能意味着126..191)。 POSIX还使用值waitpid()
来报告在shebang中指定的解释器(popen()
)丢失的情况(与要执行的程序不可用相反)。是否由126
返回是一个单独的讨论。而且信号报告由外壳程序完成,因为没有(简便)方法可以报告孩子因信号而死亡。