自定义C语言Shell的提示符输出文件描述符选择问询
自定义Shell:提示符该输出到哪个文件描述符?
我来帮你梳理清楚这个问题——开发自定义Shell时,提示符的文件描述符选择确实有不少实践和隐含规范可以参考,咱们一步步拆解:
先看POSIX标准的态度
POSIX.1-2017并没有强制规定提示符必须输出到哪个FD,但它的Shell Command Language规范里隐含了一个指导:交互式Shell的提示符应该输出到与输入关联的终端设备,而主流实践中,这个输出通常对应STDERR(文件描述符2)。
各经典Shell的实际行为
你已经测试了dash、csh/tcsh,我补充下你没搞定的几个:
- bash & zsh:这俩和dash一样,都是用STDERR输出提示符。你可以用这个命令验证:
进入交互式bash后输入几个命令再退出,打开bash 2>prompt.logprompt.log就能看到所有提示符都在里面。或者更简洁的方式:
这样bash以交互式启动,提示符会被重定向到日志文件,而STDOUT不会有内容。echo test | bash -i 2>prompt.log - BSD sh:和dash行为一致,提示符输出到STDERR,用同样的重定向方法就能验证。
- csh & tcsh:确实是特例,它们把提示符输出到STDOUT(文件描述符1),这是少数派行为。
为什么主流Shell都选STDERR?
核心原因是避免输出混淆:
- STDOUT的设计用途是传递命令的有效业务输出,如果把提示符输出到STDOUT,当用户重定向Shell脚本或命令的输出时(比如
./mycmd.sh > result.txt),提示符会被意外混入结果文件,这显然不符合用户预期。 - STDERR则是专门用于输出诊断信息、交互提示这类非业务输出的,默认情况下它直接关联终端,就算用户重定向了STDOUT,提示符依然会正常显示在终端上,完美适配交互式Shell的使用场景。
关于STDIN的可行性
绝对不要考虑用STDIN!STDIN是输入流,它的作用是从终端或文件读取数据,而非输出内容。强行往STDIN写入不仅不会在终端显示提示符,还会干扰Shell对用户输入的读取逻辑,完全违背文件描述符的基本设计。
总结建议
如果你的自定义Shell想要和绝大多数主流Shell(bash、zsh、dash、BSD sh)保持一致,并且符合POSIX的隐含规范,优先选择STDERR(文件描述符2)输出提示符。除非你有特殊需求要兼容csh/tcsh的小众行为,否则没必要用STDOUT。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

