Linux下C程序用execv启动sh终端报错,求解决方案
用execv替代system("sh")启动终端的正确姿势
咱们先拆解下你遇到的问题:你那行无法运行的代码里,argv数组的写法踩了坑——你把/bin/bash作为要执行的程序,然后把/bin/sh直接当成参数传给bash,但bash会把这个参数当作要执行的脚本文件,而/bin/sh是二进制可执行文件,不是纯文本脚本,所以才会报错/bin/sh: cannot execute binary file。
下面分两种场景给你正确的实现方式:
场景1:直接用execv启动sh(和system("sh")等价)
system("sh")的本质是让系统调用/bin/sh -c "sh",也就是启动一个sh交互进程。如果你想用execv直接实现这个效果,代码应该这么写:
#include <unistd.h> #include <stdio.h> int main() { // 第一个参数是要执行的程序路径,第二个参数是argv数组(argv[0]通常是程序名,后续是参数) int ret = execv("/bin/sh", (char*[]){"sh", NULL}); // 只有execv执行失败时才会走到这里 printf("execv失败,返回值: %d\n", ret); return 1; }
⚠️ 注意:execv系列函数会替换当前进程的代码段,如果执行成功,printf和后面的代码永远不会运行。如果你想保留原进程(比如主程序还要继续做其他事),必须先fork出子进程,在子进程里调用execv:
#include <unistd.h> #include <stdio.h> #include <sys/wait.h> #include <stdlib.h> int main() { pid_t pid = fork(); if (pid == -1) { perror("fork失败"); return 1; } else if (pid == 0) { // 子进程:执行sh execv("/bin/sh", (char*[]){"sh", NULL}); // 如果execv走到这里,说明执行失败 perror("execv启动sh失败"); exit(1); } else { // 父进程:等待子进程结束 wait(NULL); printf("sh进程已退出\n"); } return 0; }
场景2:通过bash间接启动sh(修正你原来的思路)
如果你确实想通过bash来启动sh(其实没必要,但可以修正你原来的错误写法),需要用bash的-c参数来指定要执行的命令,这样bash才会把sh当成命令执行,而不是当成脚本文件:
#include <unistd.h> #include <stdio.h> int main() { int ret = execv("/bin/bash", (char*[]){"bash", "-c", "sh", NULL}); printf("execv失败,返回值: %d\n", ret); return 1; }
为什么system("sh")能成功?
system函数帮你做了三件事:
- 自动fork一个子进程
- 在子进程里调用
/bin/sh -c "你的命令" - 父进程等待子进程结束
所以它不需要你手动处理fork和参数的细节,而execv需要你自己明确指定程序路径和参数数组,这也是你之前出错的核心原因。
内容的提问来源于stack exchange,提问作者Omer Anisfeld
相关产品推荐
相关产品推荐

