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

启动时Shell脚本EOF内容被跳过:原因分析及修复方案

问题原因分析与修复方案

问题背景

我在/etc/init.d目录中添加了一段用于修改文件内容的Shell脚本:

#!/bin/bash

set -x

DBMS_ID='testuser'
DBMS_PW1='*****'

CONFIG_EXEC="./some_program"
${CONFIG_EXEC} config <<EOF
yes
127.0.0.1
${DBMS_ID}
${DBMS_PW1}


yes
EOF

cp -f A.txt B.txt

原本预期的执行结果:

DB configuration...

  HOST : 127.0.0.1
  USER : testuser
  PASS : ********
  PORT : 3306
  DB   : mysql
  UNIX_SOCKET : /tmp/mysql.sock

  TESTING CONFIGURATION ... 
  [ERROR] - Mysql connect error[1045] : Access denied for user 'testuser'@'127.0.0.1' (using password: YES)


Do you want to setup database. [yes/no] :   HOST :   USER :   PASS : 
  PORT (Default: 3306) :   DB (Default: mysql) :   UNIX_SOCKET (Default: /var/lib/mysql/mysql.sock) : 

  TESTING CONFIGURATION ... 
  [OK]

Done.

+ cp -f A.txt B.txt

但重启后出现异常,实际执行结果:

DB configuration...

  HOST : 127.0.0.1
  USER : testuser
  PASS : ********
  PORT : 3306
  DB   : mysql
  UNIX_SOCKET : /var/lib/mysql/mysql.sock

  TESTING CONFIGURATION ... 
  [OK]


Do you want to setup database. [yes/no] :   HOST :   USER : + cp -f A.txt B.txt

可见EOF块中的部分内容被跳过,以下是问题原因与修复方案:


问题原因

  1. 执行流程不匹配:重启后数据库权限状态变化,some_program第一次配置测试直接成功(输出[OK]),程序提前结束流程,不再等待后续输入,因此here-document中剩余的两个空行和yes没有被程序读取。
  2. 调试输出干扰:set -x的调试输出会写入标准错误,与程序的最后输出(Do you want to setup database...)混合,造成“输入被跳过”的视觉错觉。
  3. 非终端环境影响:init.d脚本的执行环境中,标准输入并非终端,交互式程序的行为与终端环境下不一致,加剧了输入输出的混乱。

修复方案

方案1:移除或隔离set -x的输出

set -x的调试输出会干扰程序的输入输出流,建议仅在调试时使用,或者将其输出重定向到日志文件:

# 替换原set -x为日志重定向
set -x >> /var/log/init_script_debug.log 2>&1

或者直接移除set -x语句。

方案2:使用动态交互工具(expect)替代here-document

here-document是静态输入,无法根据程序的实时输出调整输入。使用expect可以动态响应程序提示,适配不同执行流程:

#!/bin/bash

DBMS_ID='testuser'
DBMS_PW1='*****'

expect << EOF
spawn ./some_program config
expect "Do you want to setup database.*"
send "yes\r"
expect "HOST :"
send "127.0.0.1\r"
expect "USER :"
send "${DBMS_ID}\r"
expect "PASS :"
send "${DBMS_PW1}\r"
expect {
    "TESTING CONFIGURATION ... *\[ERROR\]" {
        expect "Do you want to setup database.*"
        send "yes\r"
        # 发送空行接受默认配置
        send "\r\r\r"
        expect "TESTING CONFIGURATION ... *\[OK\]"
    }
    "TESTING CONFIGURATION ... *\[OK\]" {
        # 配置直接成功,无需后续输入
    }
}
expect "Done."
EOF

cp -f A.txt B.txt

(注:需确保系统已安装expect工具,可通过apt install expect或yum install expect安装)

方案3:预检查数据库连接状态,动态调整输入

在执行some_program前,先测试数据库连接,根据结果决定发送的输入内容:

#!/bin/bash

DBMS_ID='testuser'
DBMS_PW1='*****'

# 测试数据库连接
mysql -h127.0.0.1 -u${DBMS_ID} -p${DBMS_PW1} -e "SELECT 1" > /dev/null 2>&1
if [ $? -eq 0 ]; then
    # 连接成功,发送基础配置
    INPUT_CONTENT="yes
127.0.0.1
${DBMS_ID}
${DBMS_PW1}
"
else
    # 连接失败,发送完整流程输入
    INPUT_CONTENT="yes
127.0.0.1
${DBMS_ID}
${DBMS_PW1}


yes
"
fi

./some_program config << EOF
${INPUT_CONTENT}
EOF

cp -f A.txt B.txt

内容的提问来源于stack exchange,提问作者DannyPoet

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 05:45:35