如何编写脚本逐个向C语言实现的自定义Shell程序输入测试指令?
问题分析与解决方案
首先,你的自定义Shell程序和here-doc配合失效的问题,主要出在**read()的处理逻辑**以及程序的循环结构上,我们一步步拆解解决:
1. 原C代码的核心问题
你的shell()函数里有几个关键逻辑漏洞:
while((r = read(0, cmd, 200)) == 0);:这个循环会在read()返回0(到达EOF)时无限卡死,因为此时条件为真,会反复调用read(),而EOF状态下read()始终返回0,程序无法继续执行后续逻辑。- 递归调用
shell():每次处理完一个命令就递归调用自身,不仅有栈溢出风险,还会在EOF到来时无法正常退出。 - 命令匹配不严谨:输入的指令会包含换行符(比如
hello\n),虽然strncmp能匹配前几个字符,但如果输入helloworld也会误触发hello函数,逻辑不够精准。
2. 修改后的健壮版C代码
我们调整循环结构,正确处理read()的所有返回值,同时去除输入中的换行符,让命令匹配更准确:
#include <stdio.h> #include <string.h> #include <unistd.h> void hello(){ write(1,"hello\n",strlen("hello\n")); } // 加换行符让输出更清晰 void bye(){ write(1,"bye\n",strlen("bye\n")); } void shell(){ int r; char cmd[200]; while(1) { memset(cmd,'\0',sizeof(cmd)); // 用sizeof更适配数组长度变化 r = read(0, cmd, sizeof(cmd)-1); // 留1字节给终止符,避免溢出 if(r == -1 || r == 0) { // 读取错误或到达EOF,直接退出循环 break; } // 去除输入末尾的换行符(如果存在) cmd[strcspn(cmd, "\n")] = '\0'; // 精准匹配命令 if(strcmp(cmd,"hello") == 0){ hello(); } else if(strcmp(cmd,"bye") == 0){ bye(); } else if(strcmp(cmd,"cd folder1") == 0){ write(1,"changed to folder1\n", strlen("changed to folder1\n")); } else if(strcmp(cmd,"ls") == 0){ write(1,"file1 file2\n", strlen("file1 file2\n")); } } } int main(int argc, char **argv) { shell(); return 0; }
3. 可用的Bash测试脚本
修改完C代码后,以下几种方式都能正常向你的Shell程序批量输入测试指令:
方式一:Here-Document(你最初尝试的方法)
./myownshell.o <<'EOF' cd folder1 ls hello bye EOF
方式二:管道输入
echo -e "cd folder1\nls\nhello\nbye" | ./myownshell.o
方式三:用printf精准控制换行
printf "cd folder1\nls\nhello\nbye\n" | ./myownshell.o
为什么之前的代码无法正常工作?
在你原来的代码中,当Here-Document发送完所有指令后,输入流会触发EOF,此时read()返回0,你的while((r = read(...)) == 0)会进入无限循环,程序既无法处理后续指令,也无法正常退出。修改后的代码会在read()返回0或-1时直接终止循环,避免卡死;同时改成while(1)的循环结构,比递归调用更健壮。
内容的提问来源于stack exchange,提问作者Shewol
相关产品推荐
相关产品推荐

