为何我的自定义Shell代码仅执行第一条命令,后续命令无法运行?
问题分析与解决
你的shell只执行第一条命令,核心是代码存在几个关键逻辑错误:
1. strtok仅遍历未实际处理命令
你用strtok拆分了换行分隔的命令,但只是单纯移动指针跳过所有token,完全没对每个token执行命令逻辑。当前代码在strtok循环后,依然用getline读取的原始buff调用execve,而第一次getline读取的是第一行内容,后续循环即使读取到其他行,也重复了同样的无效操作。
2. execve参数配置错误
arg数组的第一个元素是空字符串,而execve要求argv[0]必须是程序的名称(通常是命令路径本身),参数错误会直接导致命令执行失败。
3. 未处理输入中的无效字符
- 后续行的命令带前导空格,你仅跳过第一个字符,剩余空格会被当作路径的一部分,系统找不到
" /bin/ls"这类路径 getline读取的内容包含换行符,会让路径变成"/bin/ls\n",同样无法被系统识别
4. 缺失错误反馈
execve执行失败后没有任何提示,你无法直观看到后续命令未执行的原因。
修改后的代码示例
#include "O_X.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/wait.h> char **environ; /** * main - simple shell * Return: 0 on success, -1 on failure */ int main(void) { char *buff = NULL; char *token = NULL; int size; pid_t kiddo; int stat; size_t len = 0; // 让getline自动分配缓冲区,避免固定长度溢出 while (1) { size = getline(&buff, &len, stdin); if (size == -1) { free(buff); exit(EXIT_SUCCESS); } // 按换行符拆分所有命令 token = strtok(buff, "\n"); while (token != NULL) { // 跳过命令前的所有空格 while (*token == ' ') token++; // 处理空行情况 if (*token == '\0') { token = strtok(NULL, "\n"); continue; } kiddo = fork(); if (kiddo == -1) { perror("fork error"); token = strtok(NULL, "\n"); continue; } if (kiddo == 0) { // 修正execve的argv参数:第一个元素为命令路径 char *arg[] = {token, NULL}; execve(token, arg, environ); // 若execve返回,说明执行失败 perror("execve failed"); exit(EXIT_FAILURE); } else { // 等待子进程执行完毕 wait(&stat); } token = strtok(NULL, "\n"); } } free(buff); return EXIT_SUCCESS; }
关键修改说明
- 让
getline自动分配缓冲区,避免固定长度导致的溢出问题 - 真正遍历每个拆分出的命令token,对每个token执行fork+execve逻辑
- 处理命令前的所有空格,确保传递给execve的是有效路径
- 修正execve的argv参数,符合系统调用要求
- 添加错误提示,方便调试命令执行失败的情况
- 完善内存释放与退出逻辑
内容的提问来源于stack exchange,提问作者Rashad Malikov
相关产品推荐
相关产品推荐

