execlp execl execvp error:permission denied

本文介绍了如何通过调用/bin/sh来执行Shell脚本,并强调了为脚本添加执行权限的重要性。通过一个C语言示例程序展示了如何使用fork()和execl()系统调用来执行指定的Shell脚本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   上面那几个函数在路径里找到一个可执行文件,这个文件不是连接编译器产生的可执行文件,就认为这是一个shell脚本  调用/bin/sh执行   apue:200

  这里也就明确说明了,想执行shell脚本还需要给shell脚本增加执行权限  chmod +x filename           

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<errno.h>
  4 #include<sys/types.h>
  5 #include<string.h>
  6 void sys_err(char *s)
  7 {
  8         fprintf(stderr , "%s : %s\n" , s , strerror(errno));
  9 }
 10 int main(void)
 11 {
 12         pid_t pid;
 13         
 14         if((pid = fork())< 0)
 15                 sys_err("fork error:");
 16         else  if(pid == 0){
 17                 if(execl("/root/apue/p208/test" , "test" , "myarg1" ,"MY ARG2" , (char*)0) < 0)
 18                         sys_err("execl error:");
 19         }
 20         if(waitpid(pid , NULL ,0 ) < 0 )
 21                sys_err("waitpid error:");
 22         exit(0);        
 23 }


<think>我们正在讨论execlexecvp函数的区别。这两个函数都属于exec家族,用于在进程中执行新的程序。它们的主要区别在于参数传递的方式和搜索路径的处理。1.execl函数:-函数原型:intexecl(constchar*path,constchar*arg0,...,(char*)0);-参数说明:-path:要执行的可执行文件的完整路径(绝对路径或相对路径)。-arg0,...:参数列表,以NULL指针结束。第一个参数通常是程序名(即argv[0]),然后是命令行参数。-特点:需要提供完整的路径,不会使用PATH环境变量来搜索可执行文件。参数是逐个列出的。2.execvp函数:-函数原型:intexecvp(constchar*file,char*constargv[]);-参数说明:-file:要执行的文件名(不包含路径)。函数会在PATH环境变量指定的目录中搜索该文件。-argv:参数数组,以NULL指针结束。数组的第一个元素通常是程序名,后续元素是命令行参数。-特点:使用环境变量PATH来搜索可执行文件,因此只需提供文件名即可。参数通过数组传递。总结区别:-路径处理:execl需要完整的路径,而execvp只需要文件名(它会搜索PATH)。-参数传递:execl使用可变参数列表(逐个参数),execvp使用字符串数组。-使用场景:如果知道程序的完整路径,可以使用execl;如果只想通过程序名执行(类似于在shell中直接输入命令),则使用execvp更方便。示例代码:使用execl执行/bin/ls:```c#include<unistd.h>#include<stdio.h>intmain(){//使用execl执行ls-l/,注意第一个参数是路径,然后依次是程序名,参数,最后用NULL结束。execl("/bin/ls","ls","-l","/",(char*)NULL);//如果execl返回,说明调用失败perror("execlfailed");return1;}```使用execvp执行ls:```c#include<unistd.h>#include<stdio.h>intmain(){//准备参数数组char*args[]={"ls","-l","/",NULL};//第一个参数是程序名(文件名),execvp会在PATH中查找lsexecvp("ls",args);//如果execvp返回,说明调用失败perror("execvpfailed");return1;}```注意:两个函数如果执行成功,都不会返回(因为原进程已经被替换),只有失败时才返回-1。另外,关于exec家族的其他函数,如execlp、execv等,也有类似的区别。参考引用:[^1]:在exec()系列函数中,当前进程被转换为另一个进程。这意味着当进程调用exec()函数时,该进程停止运行当前程序并开始运行另一个程序。进程ID不会改变,但该进程已经变成了另一个程序。关于进程中的线程会发生什么,我们将在讨论fork()时再回来。[^2]:图8.21展示了/usr/local/bin/awkexample(一个解释器文件)的例子。如果路径前缀之一是/usr/local/bin,我们可以执行图8.21中的程序(假设我们已经为该文件打开了执行位)为:$awkexamplefile1FILENAME2f3,此时参数为:ARGV[0]=awk,ARGV[1]=file1,ARGV[2]=FILENAME2,ARGV[3]=f3。根据上述引用,我们知道exec函数会替换当前进程的代码段、数据段等,但进程ID不变。同时,引用[2]中的例子展示了通过解释器文件执行程序时参数传递的情况,这与exec函数传递参数的方式类似。相关问题:1.exec函数执行成功后,原进程的代码和数据会怎样?2.除了execlexecvp,exec家族还有哪些函数?它们之间有何区别?3.如何在C程序中同时使用fork和exec来创建新进程并执行新程序?</think>### execlexecvp函数的区别 在C编程中,`execl`和`execvp`都属于`exec`函数家族,用于**将当前进程替换为新的程序**(进程ID不变,但运行全新的代码)[^1]。它们的主要区别体现在参数传递方式和路径搜索行为上: #### 1. **参数传递方式** | 函数 | 参数格式 | 示例 | |----------|--------------------------------------|--------------------------------------| | `execl` | **逐个参数列表**<br>以`NULL`结尾 | `execl("/bin/ls", "ls", "-l", NULL);` | | `execvp` | **参数数组**<br>以`NULL`结尾的指针数组 | `char *args[] = {"ls", "-l", NULL};`<br>`execvp("ls", args);` | #### 2. **路径搜索行为** | 函数 | 路径要求 | 是否搜索`PATH`环境变量 | |----------|----------------------------------------|------------------------| | `execl` | **需完整路径**<br>(如`"/bin/ls"`) | ❌ 不搜索 | | `execvp` | **只需文件名**<br>(如`"ls"`) | ✅ 自动搜索`PATH` | #### 3. **典型使用场景** - **`execl`适用场景** 已知可执行文件的绝对路径时: ```c #include <unistd.h> execl("/usr/bin/gcc", "gcc", "main.c", "-o", "app", NULL); ``` 若路径错误或文件不存在,返回`-1`。 - **`execvp`适用场景** 执行环境变量`PATH`中的命令(类似Shell行为): ```c #include <unistd.h> char *cmd[] = {"python", "script.py", NULL}; execvp("python", cmd); // 自动搜索/bin/python /usr/bin/python等 ``` #### 4. **关键特性对比表** | 特性 | `execl` | `execvp` | |--------------|------------------|-------------------| | 参数传递 | 变长参数列表 | 指针数组 | | 路径处理 | 必须指定完整路径 | 自动搜索`PATH` | | 错误处理 | 失败返回`-1` | 失败返回`-1` | | 进程替换效果 | 完全相同:原进程代码/数据被完全替换[^1] | | #### 示例代码分析 ```c // execl示例:执行/bin/date命令 execl("/bin/date", "date", "+%Y-%m-%d", NULL); // execvp等效实现 char *argv[] = {"date", "+%Y-%m-%d", NULL}; execvp("date", argv); ``` > ⚠️ **注意**:若`execvp`在`PATH`中找不到`date`,会返回错误;而`execl`必须确保路径正确。 #### 设计哲学差异 - `execl`:强调**精确控制**(明确路径) - `execvp`:模拟**Shell行为**(依赖环境变量) 实际编程中,`execvp`更常用于需要灵活执行系统命令的场景(如构建简易Shell),而`execl`适合嵌入固定路径的程序调用。 --- ### 相关问题 1. `exec`函数执行成功后,原进程的内存布局会发生什么变化? 2. 如何结合`fork()`和`execvp()`实现类似Shell的子进程命令执行? 3. 如果`execvp`在`PATH`中找不到目标程序,有哪些错误处理策略? 4. 在解释器文件(如Shell脚本)中调用`execl`会有什么特殊行为[^2]? [^1]: `exec()`系列函数将当前进程转换为另一个程序,进程ID不变,但原程序代码被完全替换。 [^2]: 解释器文件(如`#!/bin/sh`)通过`exec`执行时,内核会解析首行解释器路径并传递参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值