我有一个调用shell脚本myScript.sh的小型C程序。ret的值是256。请帮我了解系统调用出了什么问题?
int main()
{
int ret;
ret = system (myScript.sh);
ret >>= ret;
if (ret != 0)
{
printf("ret is [%d]",ret);
}
}
在使用ksh shell的64位UNIX操作系统上工作
man system
的输出如下:
The system() function returns the exit status of the shell as returned by waitpid(2), or -1 if an error occurred when invoking fork(2) or waitpid(2). A return value of 127 means the execution of the shell failed.
waitpid
手册描述了一组宏,例如WEXITSTATUS()
,它们从返回值中提取实际的退出码。
我不太确定你打算用ret >>= ret
做什么,但那肯定是不对的。
system
函数的工作方式是调用fork
函数,然后子进程使用/bin/sh -c
中的一个exec
函数,再加上您传递给system
函数的字符串,将子进程变成/bin/sh
程序的实例,从而运行命令。父进程调用其中之一的wait
函数,等待/bin/sh
退出,它与shell脚本具有相同的退出状态,然后system
函数也返回该值。wait
系统调用的手册页:main 3 wait
WIFEXITED(stat_val)
宏可用于测试程序是否正常退出而不是使用信号退出。正常退出涉及调用 exit
系统调用。如果此函数返回非零值,则可以使用 WEXITSTATUS(stat_val)
宏获取实际返回的值。
WIFSIGNALED(stat_val)
宏可用于测试程序是否被信号终止,如果是,则 WTERMSIG(stat_val)
宏将返回导致终止的信号编号。fork
调用失败,则 system
将能够返回-1并设置 errno
反映错误。如果 fork
没有失败,则错误可能发生在子进程中,并且更难定位。在您的平台上,可能会在分叉之前进行一些测试,以确保您有权限执行适当的文件并设置 errno
反映该问题,但也可能不会。perror
函数以在设置了 errno
的情况下打印出错误消息。fork
之后且在子进程中,则需要让 shell 告诉您更多有关正在发生的事情,或者让 shell 脚本告诉您。这可以通过在脚本中包含类似于在 C 程序中使用打印语句的 echo
语句来实现。access
函数以测试是否具有读取和/或执行文件的权限。strace -o my_program.strace -f ./my_program
或者
ltrace -o my_program.ltrace -f -S ./my_program
-o
之后)以查看程序和内核相互交流的内容。 ltrace
查看程序如何与库函数通信,而 strace 则查看系统调用,但是 -S
告诉 ltrace 也要查看系统调用。 -f
参数告诉它们两个都要跟踪创建的程序子进程。
正如我提到的,在 Posix 系统下,system
应该使用 /bin/sh
或兼容的 shell。这并不意味着 /bin/sh
不会运行 /bin/ksh
来运行您的脚本(或者内核不会使用脚本文件开头的 #!
行来执行此操作),但这可能会成为一个问题。有一些方法可以运行 shell 脚本,使得不需要使用此行来知道应该使用哪个 shell。其中最显著的是:
. myshell.sh
period(.)和空格实际上是将文件文本转储到当前的shell会话中,而不是在另一个进程中运行它(这对于设置环境非常有用)。 如果您正在执行以下操作:
int x = system(". myshell.sh");
该命令的退出状态由两个字节编码:
由于0x0100等于256的十进制,因此您的Shell脚本以状态1退出。请检查您的Shell脚本,并确保在成功时以状态0退出。
ret
的打印值为 256,则实际(未移位)的返回值为 512 --> 0x0200,shell 以状态 2 退出。大体上是相同的事情。 - Conrad Meyer从标准中可以看到:
6.5.7/3 如果右操作数的值为负数或大于或等于左操作数,且升级后的左操作数的宽度,则结果未定义。
因此,当您执行以下操作时:
ret >>= ret;
system
函数的返回值在出现错误时可能为-1。
如果你的调用返回了这样一个负数,接下来的操作ret >>= ret;
(等同于ret = -1 >> -1;
)会得到一个没有意义的结果:你不能将位数右移一个负数位。
当你试图进行没有意义的操作时,C语言可以做任何事情……任何事情(包括什么都不做、按照你的预期执行、重新格式化你的硬盘、将你的银行账户转移到我的名下、让恶魔从你的鼻子里飞出来,......)。
没有出错。你有阅读文档吗?请参见:
返回值
如果出错(例如 fork(2) 失败),则返回值为-1;否则为命令的返回状态,格式如 wait(2) 中所指定的格式。 因此,命令的退出代码将是 WEXITSTATUS(status)。如果无法执行 /bin/sh,则退出状态将是一个调用 exit(127) 的命令的状态。
由于256不等于-1,因此调用未失败。
system()
返回一个int。在大多数平台上,无符号int -1是0xffffffff。 - Conrad Meyerwaitpid(2)
状态代码中具有某种含义...这与shell脚本的退出状态有什么关系? - Conrad Meyer我正在使用Linux,使用system("sh script.sh")调用脚本非常有帮助。
myScript.sh; echo $?
- khachikret
的值,那么他肯定不是那么蠢了。 - Conrad Meyer