You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shell脚本中read命令获取的$choice变量始终为空问题排查

问题原因与解决方法

问题根源

脚本中while循环通过<"$conf_file"将整个循环的标准输入重定向为配置文件backup_ips.txt,导致循环内的read命令默认从该配置文件读取内容,而非终端获取用户输入。当配置文件内容被读完后,read命令会读取到EOF(文件结束符),最终$choice变量始终为空。

此外,脚本中case分支的结尾存在语法错误:&;;;多了一个分号,正确写法应为&;;,这也可能引发脚本执行异常。

修复方案

  1. 让read命令从终端读取输入:修改循环内的read命令,明确指定从终端设备/dev/tty读取用户输入,避免受脚本标准输入重定向的影响。
  2. 修正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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 05:00:23