C程序调用shell脚本

我有一个小的C程序调用shell脚本myScript.sh。 我得到ret的值为256.请帮助我知道系统调用出了什么问题?

int main() { int ret; ret = system (myScript.sh); ret >>= ret; if (ret != 0) { printf("ret is [%d]",ret); } } 

使用64位UNIX操作系统并使用ksh shell

system函数通常在* nix上运行的方式是它调用fork然后子进程调用其中一个exec函数和/bin/sh -c然后调用你传递给子进程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没有失败,则可能在孩子身上发生错误并且更难以找到。 您可能有可能在您的平台system执行某些测试,然后才能确保您有权执行相应的文件并设置errno以反映该情况,但可能不会。

errno的情况下,您应该查看perror函数以打印出错误消息。

如果失败发生在fork之后和子fork内,那么你需要让shell告诉你更多关于发生了什么,或者获取shell脚本。 这可以通过在脚本中包含echo语句,类似于在C程序中使用print语句。

您还应该查看access函数以测试您是否有权读取和/或执行文件。

如果您使用的是Linux,那么您应该可以:

 strace -o my_program.strace -f ./my_program 

要么

 ltrace -o my_program.ltrace -f -S ./my_program 

然后检查跟踪文件(在-o )以查看程序和内核之间相互说明的内容。 ltrace查看程序如何与库函数进行通信,而strace查看系统调用,但-S告诉ltrace也查看系统调用。 -f参数告诉他们在创建程序时跟踪程序的子项。

我刚刚注意到你说你正在使用ksh

正如我所提到的,Posix system下的系统应该使用/bin/sh或兼容的shell。 这并不意味着/bin/sh不会运行/bin/ksh来运行你的脚本(或者内核不会使用脚本文件开头的#!行来执行此操作),但它可以是个问题。 有一些方法可以运行shell脚本,以便不使用此行来知道要使用哪个shell。 最值得注意的是:

 . myshell.sh 

句点和空间实质上是尝试将文件的文本转储到当前的shell会话中,而不是在另一个进程中运行它(这对于设置环境很有用)。 如果你要这样做:

 int x = system(". myshell.sh"); 

那可能是个问题。

在我的系统上, 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做什么,但那不可能是正确的。

命令的退出状态编码为两个字节:

  • 高位字节包含退出状态。
  • 低位字节包含杀死它的信号(如果有的话)。

由于0x0100是256十进制,因此shell脚本退出状态1.检查shell脚本并确保它在成功时以状态0退出。

从标准(重点是我的):

6.5.7 / 3如果[操作符]的右操作数的值为负或大于或等于提升的左操作数的宽度, 则行为未定义

所以,当你这样做的时候

 ret >>= ret; 

并且ret < 0ret >= CHAR_BIT * sizeof (int) ......任何事情都会发生


错误时, system函数的返回值可以为-1。

如果你的呼叫以这样的负值返回,则下一步操作ret >>= ret; (与ret = -1 >> -1; )会产生一些没有意义的东西:你不能右移一个负数位。

当你尝试做没有意义的事情时,C可以做任何事情...... 任何事情 (包括什么都不做,做你期望的事情,重新格式化你的硬盘,把你的银行账户转移到我的,让恶魔飞出你的鼻子,......,......,...)

确保您的脚本在路径中是可执行的,或者使用完整路径。

什么都没有出错。 你看过文件了吗? 看到:

返回值
错误时返回的值为-1(例如fork(2)失败),否则返回命令的返回状态。 后一种返回状态采用wait(2)中指定的格式。 因此,命令的退出代码将是WEXITSTATUS(状态)。 在无法执行/ bin / sh的情况下,退出状态将是退出(127)的命令的退出状态。

由于256不是-1,因此呼叫没有失败。

为什么要改变结果呢? 只需删除行ret >> = ret,它就可以了。

我正在使用linux,它帮助用系统调用脚本(“sh script.sh”)