Shell脚本中read命令获取的$choice变量始终为空问题排查
问题原因与解决方法
问题根源
脚本中while循环通过<"$conf_file"将整个循环的标准输入重定向为配置文件backup_ips.txt,导致循环内的read命令默认从该配置文件读取内容,而非终端获取用户输入。当配置文件内容被读完后,read命令会读取到EOF(文件结束符),最终$choice变量始终为空。
此外,脚本中case分支的结尾存在语法错误:&;;;多了一个分号,正确写法应为&;;,这也可能引发脚本执行异常。
修复方案
- 让
read命令从终端读取输入:修改循环内的read命令,明确指定从终端设备/dev/tty读取用户输入,避免受脚本标准输入重定向的影响。 - 修正
case分支的语法错误:将&;;;改为&;;。
修改后的完整脚本
#!/bin/sh conf_file="backup_ips.txt" # read the input file line by line while IFS= read -r line;do IFS='|' read -ra fields <<< "$line" DB=${fields[0]} IP=${fields[1]} USER=${fields[2]} PWD=${fields[3]} FILE=$DB.sql # start to backup echo "Backup DB instance Name:'$DB'('$IP,$USER,$PWD') to file:'$FILE'" # check file exists if [ -e "$FILE" ]; then # 从终端读取用户输入 read -p "File '$FILE' already exists. Do you want to overwrite it?(y/n)" choice </dev/tty echo $choice case "$choice" in y|Y ) echo "Overwriting file '$FILE'..." nohup mysqldump --single-transaction --no-tablespaces --set-gtid-purged=OFF -u$USER -p$PWD -h $IP --all-databases > $FILE &;; n|N ) echo "Skipping file '$FILE'...";; * ) echo "Invalid choice. Skipping file '$FILE'...";; esac else nohup mysqldump --single-transaction --no-tablespaces --set-gtid-purged=OFF -u$USER -p$PWD -h $IP --all-databases > $FILE & fi done <"$conf_file" # 循环外的read同样需要指定从终端读取 read -p "File '$FILE' already exists. Do you want to overwrite it?(y/n)" choice </dev/tty echo $choice case "$choice" in # 补充你原本的case分支内容 esac
额外说明
/dev/tty是当前进程关联的终端设备文件,直接从这里读取输入可以绕过脚本的标准输入重定向,确保获取到用户的终端输入。- 循环外的
read命令同样需要添加</dev/tty,避免因之前的循环重定向残留影响(虽然循环结束后标准输入会恢复,但为了兼容性和明确性,建议统一处理)。
内容的提问来源于stack exchange,提问作者user538051
相关产品推荐
相关产品推荐

