为何execve有时仅设置errno不打印错误?cd与ls行为差异解析
问题解答
为什么会有行为差异?
核心原因是**cd是shell内置命令,ls是外部可执行程序**,而且你当前的代码对cd的处理完全错误:
- 系统里根本不存在
/bin/cd这个可执行文件!所以调用execve("/bin/cd", ...)直接失败,errno被设为2,但因为execve没启动任何程序,自然不会有程序帮你打印错误信息,最后是你自己shell代码里的printf输出了提示。 - 而
/bin/ls是真实存在的外部程序,execve能成功启动它。当你执行ls ls时,是ls程序自身检测到要访问的ls文件不存在,然后向标准错误输出打印了错误信息,这和你的shell代码没有关系。
你的代码存在的问题
- 内置命令不能用
execve执行:cd的作用是改变当前shell的工作目录,要是用execve启动所谓的cd程序,就算存在,也只会改变那个子进程的目录,对你的主shell完全没用。正确做法是直接在shell进程里调用chdir()系统调用。 - 变量未初始化:你的
val变量没有初始化,如果用户输入的命令不在你列出的列表里,val会是随机值,可能导致错误的判断逻辑。
修正示例(处理cd部分)
把cd的处理改成这样:
int val = -1; if(strcmp(tokens[0], "cd") == 0){ if(tokens[1] == NULL){ // 处理无参数的cd,切换到HOME目录 val = chdir(getenv("HOME")); } else { val = chdir(tokens[1]); } if(val == -1){ perror("cd"); // 直接打印对应的错误信息,比如"cd: No such file or directory" } // 内置命令处理完直接返回,不需要走后面的execve逻辑 return; } // 其他外部命令的execve逻辑保持(注意处理execve失败的情况)
内容的提问来源于stack exchange,提问作者www139
相关产品推荐
相关产品推荐

