You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言编写简易shell时execve()报No such file or directory错误

问题根因

你遇到的No such file or directory报错核心原因有3个:

  1. getline()会把输入完成按回车产生的换行符\n一起读到缓冲区里,你以为传入的路径是/bin/ls,实际传入的是/bin/ls\n,系统找不到带换行后缀的可执行文件,自然报错。
  2. 你给execve()传的环境变量数组是空的,就算路径修对了,空环境也可能导致程序执行异常。
  3. 你没有调用fork()创建子进程执行命令:execve会直接替换当前进程的代码段,只要执行成功,你的shell进程本身就会被替换成目标命令进程,命令运行完直接退出,永远不会回到循环打印下一个提示符,不符合shell的运行逻辑。
修复方案

按以下顺序修改代码即可:

  • 读取到输入行后,第一时间去掉末尾的换行符,代码片段:
nread = getline(&line, &len, stdin);
if (nread == -1)
{
  perror("can't read command\n");
  free(line);
  exit(95);
}
// 去掉末尾换行
if (nread > 0 && line[nread - 1] == '\n')
{
  line[nread - 1] = '\0';
}
  • 不要自定义空的env数组,引入全局环境变量表extern char **environ;(头文件<unistd.h>里声明),直接把environ传给execve作为第三个参数即可。
  • 执行命令前先fork()子进程:子进程里调用execve执行命令,父进程调用wait()/waitpid()等待子进程执行结束,再回到循环等待下一个用户输入,不要在主进程里直接调用execve。
  • 打印提示符后加fflush(stdout),因为标准输出是行缓冲模式,没有换行符的话提示符不会立刻刷新显示,用户看不到输入提示。
修复后可运行的核心代码参考
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>

extern char **environ;

int main(void)
{
  char *line = NULL, *argv[] = { NULL, NULL };
  size_t len = 0;
  ssize_t nread;
  pid_t child_pid;
  int wstatus;

  do {
    printf("#cisfun$ ");
    fflush(stdout);
    nread = getline(&line, &len, stdin);
    if (nread == -1)
    {
      perror("can't read command\n");
      free(line);
      exit(95);
    }
    // 去除末尾换行
    if (nread > 0 && line[nread - 1] == '\n')
    {
      line[nread - 1] = '\0';
    }

    if (strlen(line) == 0)
    {
      continue;
    }
    argv[0] = line;

    child_pid = fork();
    if (child_pid == -1)
    {
      perror("fork error:");
      continue;
    }
    if (child_pid == 0)
    {
      // 子进程执行命令
      if (execve(line, argv, environ) == -1)
      {
        perror("Error:");
        exit(1);
      }
    }
    else
    {
      // 父进程等待子进程结束
      waitpid(child_pid, &wstatus, 0);
    }
  } while (1);

  free(line);
  return (0);
}

补充:如果后续要支持带参数的命令(比如ls -l),还需要额外对输入的line做分词切割,把参数依次填到argv数组里,保证argv最后一个元素是NULL即可。

内容的提问来源于stack exchange,提问作者Bayeroabdul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 20:27:20