为什么C语言用execl执行bash shell脚本会出现Exec format error?

cmykrgb123 2009-11-04 08:41:56
我遇到一个奇怪的问题,用execl函数执行execl("./a.sh","arg0",NULL);会失败,出现“fail to exec: Exec format error”。而如果用execlp("./a.sh","arg0",NULL);就一切正常。而且如果执行的不是./a.sh而是./a.out(一个二进制可执行文件),两者就都没问题。execl和execlp区别难道不仅仅就是在第一个参数不是完整路径名而是文件名时才会在查找范围上有体现吗?


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
pid_t pid;
pid = fork();
if(pid < 0){
printf("fail to fork\n");
exit(1);
}else if(pid == 0){
if(execl("./a.sh","arg0",NULL) < 0){
perror("fail to exec");
exit(0);
}
}
printf("the parent\n");
return 0;
}
...全文
2904 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
cmykrgb123 2009-11-04
  • 打赏
  • 举报
回复
谢谢楼上,这下对exec几个函数理解更深入了一步。
mymtom 2009-11-04
  • 打赏
  • 举报
回复
#! /bin/sh
开头的文件,知道要调用响应的解释器执行.
b.sh就是这种情况.
====
应该是
====
#! /bin/sh
开头的文件,execve知道要调用/bin/sh作为解释器执行.
例子中的a.sh就是
mymtom 2009-11-04
  • 打赏
  • 举报
回复
1. execl和execlp的区别除了路径搜索方面的不同, execlp在文件格式execve返回不是可执行文(ENOEXEC)(楼主的a.sh是shell脚本就不是可执行文件格式)时,会调用shell执行指定的文件.

2. exeve系统调用认识
#! /bin/sh
开头的文件,知道要调用响应的解释器执行.
b.sh就是这种情况.

EXECLP
Some of these functions have special semantics.

The functions execlp(), execvp(), and execvP() will duplicate the actions
of the shell in searching for an executable file if the specified file
name does not contain a slash ``/'' character. For execlp() and
execvp(), search path is the path specified in the environment by
``PATH'' variable. If this variable is not specified, the default path
is set according to the _PATH_DEFPATH definition in <paths.h>, which is
set to ``/usr/bin:/bin''. For execvP(), the search path is specified as
an argument to the function. In addition, certain errors are treated
specially.

If an error is ambiguous (for simplicity, we shall consider all errors
except ENOEXEC as being ambiguous here, although only the critical error
EACCES is really ambiguous), then these functions will act as if they
stat the file to determine whether the file exists and has suitable exe-
cute permissions. If it does, they will return immediately with the
global variable errno restored to the value set by execve(). Otherwise,
the search will be continued. If the search completes without performing
a successful execve() or terminating due to an error, these functions
will return with the global variable errno set to EACCES or ENOENT
according to whether at least one file with suitable execute permissions
was found.

If the header of a file is not recognized (the attempted execve()
returned ENOEXEC), these functions will execute the shell with the path
of the file as its first argument. (If this attempt fails, no further
searching is done.)

The execve() system call transforms the calling process into a new
process. The new process is constructed from an ordinary file, whose
name is pointed to by path, called the new process file. This file is
either an executable object file, or a file of data for an interpreter.
An executable object file consists of an identifying header, followed by
pages of data representing the initial program (text) and initialized
data pages. Additional pages may be specified by the header to be ini-
tialized with zero data; see elf(5) and a.out(5).

EXECVE

An interpreter file begins with a line of the form:

#! interpreter [arg]
mymtom 2009-11-04
  • 打赏
  • 举报
回复
a.sh第一行加
#! /bin/sh


$ cat a.sh
#! /bin/sh
echo $0
date
echo
$ cat b.sh
echo $0
date
echo
$ cat 077.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
pid_t pid;

pid = fork();
if(pid < 0){
printf("fail to fork\n");
exit(1);
}else if(pid == 0){
if(execl("./a.sh","arg0",NULL) < 0){
perror("fail to exec");
}
}

sleep(1);
pid = fork();
if(pid < 0){
printf("fail to fork\n");
exit(1);
}else if(pid == 0){
if(execl("./b.sh","arg0",NULL) < 0){
perror("fail to exec");
exit(1);
}
}

sleep(1);
pid = fork();
if(pid < 0){
printf("fail to fork\n");
exit(1);
}else if(pid == 0){
if(execlp("./a.sh","arg0",NULL) < 0){
perror("fail to exec");
exit(1);
}
}

sleep(1);
pid = fork();
if(pid < 0){
printf("fail to fork\n");
exit(1);
}else if(pid == 0){
if(execlp("./b.sh","arg0",NULL) < 0){
perror("fail to exec");
exit(1);
}
}

sleep(1);
printf("the parent\n");
return 0;
}

/* 输出 */
/*
$ ./077
./a.sh
Wed Nov 4 21:25:38 CST 2009

fail to exec: Exec format error
./a.sh
Wed Nov 4 21:25:40 CST 2009

./b.sh
Wed Nov 4 21:25:41 CST 2009

the parent
*/

23,125

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧