Git Hook使用/dev/tty后如何重定向输入实现自动化测试?
解决Git Hook中
exec < /dev/tty的测试输入问题 你的核心问题在于exec < /dev/tty强制脚本的标准输入绑定到真实终端(键盘),而管道输入(echo ... |)是通过另一个文件描述符传递的,根本没进入脚本的输入流——你用tee /dev/tty只是把内容打印到屏幕,但脚本的read依然在等待键盘输入,所以message变量不会被设置。
下面提供几种可行的解决方法:
方法1:用script命令模拟伪终端
script可以创建一个伪终端(PTY),让脚本的/dev/tty指向这个伪终端,同时把管道输入转发进去。直接运行:
echo -e "foo\n" | script -q -c "./target.sh" /dev/null
-q:静默模式,不显示script的启动/结束信息-c "./target.sh":指定要运行的脚本/dev/null:把script的日志输出丢到空设备,避免额外干扰输出
运行后你会看到脚本正确读取到foo,输出The message foo。
方法2:用expect自动化终端交互
如果需要模拟更复杂的多步交互场景,expect是专门用来处理终端交互的工具。写一个简单的expect脚本(比如命名为test_target.exp):
#!/usr/bin/expect spawn bash target.sh expect "Type a message: " # 等待脚本的输入提示符 send "foo\n" # 自动发送输入内容 expect eof # 等待脚本执行结束
给脚本添加执行权限:
chmod +x test_target.exp
然后直接运行脚本即可完成自动化测试:
./test_target.exp
方法3:给脚本增加测试模式(推荐用于Git Hook场景)
如果你不想依赖额外工具,可以修改脚本,增加一个测试开关,让测试时用标准输入,实际运行时保留/dev/tty的交互逻辑:
# file: target.sh # 检查是否处于测试模式 if [[ -n "$GIT_HOOK_TEST" ]]; then read -p "Type a message: " message else exec < /dev/tty read -p "Type a message: " message fi echo "The message ${message}"
测试时通过环境变量开启测试模式,用管道输入测试内容:
GIT_HOOK_TEST=1 echo -e "foo\n" | bash target.sh
实际作为Git Hook运行时,因为没有设置GIT_HOOK_TEST变量,脚本会自动用/dev/tty和用户交互,完全不影响原有功能。
内容的提问来源于stack exchange,提问作者Common Sense
相关产品推荐
相关产品推荐

