Bash中实现命令预填充输入后切换至标准输入且无需额外回车的解决方案
解决预输入后自动切回终端交互且无需额外回车的问题
你遇到的额外回车问题,根源在于(echo xxx; cat)里的cat会持续读取终端输入直到收到EOF(比如Ctrl+D),而目标命令结束后cat还在前台运行,所以你需要额外操作来终止它。下面提供几种纯Bash的解决方案,完美解决这个问题:
方法1:使用协程(coproc)
协程可以让我们单独控制目标命令的输入流,先发送预定义内容,再将终端输入直接转发给它,当目标命令结束后,转发输入的进程会自动退出,无需额外操作。
针对你的su+unzip场景:
# 启动su命令作为协程,保存其输入输出描述符 coproc SU_SESSION { su dummyuser -c "unzip pwdprotectedfile.zip"; } # 先发送su的密码到协程的标准输入 echo "dummypassword" >&${SU_SESSION[1]} # 将终端的输入转发给协程,当su结束后,管道关闭,cat自动退出 cat <&0 >&${SU_SESSION[1]} # 等待协程完成,确保命令执行状态正确 wait ${SU_SESSION_PID}
预填充nano内容的场景:
coproc NANO_EDITOR { nano; } echo "blablabla" >&${NANO_EDITOR[1]} cat <&0 >&${NANO_EDITOR[1]} wait ${NANO_EDITOR_PID}
自动确认第一个删除的场景:
touch dummyfile1.txt; touch dummyfile2.txt coproc RM_INTERACTIVE { rm -i dummyfile*.txt; } echo "y" >&${RM_INTERACTIVE[1]} cat <&0 >&${RM_INTERACTIVE[1]} wait ${RM_INTERACTIVE_PID}
方法2:利用文件描述符与进程监测
如果你不想用协程,可以通过保存终端输入的文件描述符,同时监测目标命令的PID,当目标命令结束后自动终止输入转发进程:
# 保存终端标准输入到文件描述符3 exec 3<&0 # 启动目标命令并后台运行,获取其PID su dummyuser -c "unzip pwdprotectedfile.zip" & SU_PID=$! # 先发送预定义密码,再转发终端输入,同时监测SU_PID,结束后杀掉cat (echo "dummypassword"; cat <&3 & CAT_PID=$!; wait $SU_PID; kill $CAT_PID) >&0 # 关闭临时文件描述符 exec 3<&-
为什么原来的方法需要额外回车?
原来的(echo xxx; cat) | command中,cat和command是并行运行的。当command结束后,管道的写端关闭,但cat还在持续读取终端输入,直到你手动输入EOF(回车或Ctrl+D)才能退出,所以需要额外操作。而上面的两种方法都能在目标命令结束后自动终止输入转发进程,避免了这个问题。
内容的提问来源于stack exchange,提问作者Bigjim
相关产品推荐
相关产品推荐

