Shell脚本输入'r'重启程序功能失效问题求助
问题:Shell脚本输入'r'重启时程序进入后台,需Ctrl+C才能停止
我编写了一段用于计算一系列数字之和的Shell脚本,希望实现输入'r'时重启程序,就像输入'q'时退出程序一样。我尝试使用$()执行脚本来实现该功能,但并未成功。当前程序运行正常,但当输入'r'时,bash并未重启程序,而是将程序置于后台运行,我需要按下ctrl+c才能停止它。请问有人知道原因吗?以下是我的脚本代码:
#!/bin/bash # Calculate the sum of a series of numbers. SCORE="0" SUM="0" while true; do echo -n "Enter your score [0-10] ('q' to quit): " read SCORE; if (( "$SCORE" < "0" )) || (( "$SCORE" > "10" )); then echo "Try again: " elif [[ "$SCORE" == "q" ]]; then echo "Sum: $SUM." break elif [[ $SCORE == "r" ]]; then echo "Sum: $SUM" sleep 1 $(bash ./aula03e07.sh); break else SUM=$((SUM + SCORE)) fi done echo "Exiting."
解答
问题原因
你用$(bash ./aula03e07.sh)的方式执行脚本时,会创建一个子shell来运行新的脚本实例,并且这个子shell的输出会被捕获(虽然你没用到这个捕获的输出)。关键问题在于:这个子shell的标准输入并没有连接到当前终端,所以当新脚本等待用户输入时,它会在后台挂起;而原脚本执行完break后会输出Exiting.并退出,此时你回到终端,但后台的子shell还在运行,所以需要按下Ctrl+C才能终止它。
修复方案
要实现脚本的重启,正确的做法是使用exec命令,它会直接替换当前的bash进程为新的脚本进程,而不是创建子shell。这样既不会有后台残留进程,重启的脚本也能正常和终端交互。
另外,用"$0"代替硬编码的脚本名(./aula03e07.sh)更灵活,因为$0会自动指向当前脚本的路径,不管脚本在哪里运行都能正确重启。
修改后的代码如下:
#!/bin/bash # Calculate the sum of a series of numbers. score="0" sum="0" while true; do # 用read -p简化echo + read的组合,更简洁 read -p "Enter your score [0-10] ('q' to quit, 'r' to restart): " score; if (( score < 0 )) || (( score > 10 )); then echo "Try again: " elif [[ "$score" == "q" ]]; then echo "Sum: $sum." break elif [[ "$score" == "r" ]]; then echo "Sum: $sum" sleep 1 # 用exec替换当前进程重启脚本,无需break(exec后后续代码不会执行) exec "$0" else sum=$((sum + score)) fi done echo "Exiting."
额外优化说明
- 按照Shell脚本惯例,变量名使用小写(避免和系统环境变量冲突)
- 用
read -p参数直接输出提示信息,替代echo -n+read的组合,代码更简洁 - 去掉了条件判断中变量的引号(在算术表达式
((...))和字符串比较[[...]]中,引号不是必须的,去掉后更清晰)
内容的提问来源于stack exchange,提问作者Marcel de Araújo Santos Souza
相关产品推荐
相关产品推荐

