mysql 客户端在 运行 使用脚本时打印帮助消息,但 运行 直接在 shell 中就可以了

mysql client prints help message when run with script, but runs fine directly in shell

我遇到了一个奇怪的 shell 脚本问题。我正在尝试 运行 来自 shell 的 mysql 命令针对本地 docker 实例,或者通过 ssh 针对不可公开访问的数据库。我有这个:

#!/bin/bash

# 0: Check DB status
# 1: Query MySql for latest migration
# 2: Check sql dir for migrations newer than query result
# 3..: Execute newer sql *in order*
 
################################################################################
# script and sql calls
################################################################################

DB_HOST=
DB_USER=
DB_PASSWORD=
DB_NAME=

if [[ -z $REMOTE_HOST ]]; then
    SSH_PREFIX=""
else
    SSH_PREFIX="ssh -o StrictHostKeyChecking=no -i sshkey ${REMOTE_USER}@${REMOTE_HOST}"
fi

MYSQL_CLIENT="mysql --protocol=tcp -h ${DB_HOST} -u ${DB_USER} --password=${DB_PASSWORD}"

#checking mysql connection
mysql_db_statuscheck(){
    echo "`date` :Checking DB connectivity...";
    echo "`date` :Trying to connect to the ODU MySQL Database..."
    EXEC_SQL="-e 'SELECT 1;'"
    cmd="${SSH_PREFIX} ${MYSQL_CLIENT} ${EXEC_SQL} ${DB_NAME}"
    echo $cmd
    $cmd
    if [[ $? -eq 0 ]]
    then
        DB_STATUS="UP"
        export DB_STATUS
        echo "`date` :Status: ${DB_STATUS}. Able to Connect..."
    else
        DB_STATUS="DOWN"
        export DB_STATUS
        echo "`date` :Status: DOWN . Not able to Connect."
        echo "`date`:Not able to connect to database with Username:
        "${DB_USER}" HostName: ""${DB_HOST}" " SID: "${DB_NAME}"."
        echo "`date` :Exiting Script Run..."
        exit 1
    fi
}

# run mysql function
runmysqls() {
    echo "`date` :Checking DB and table status..."

    mysql_db_statuscheck

    echo "`date` :DB status check completed"
    echo "`date` :Connecting To ${DB_USER}/******@${DB_NAME}";
    if [[ $DB_STATUS == "UP" ]]
    then
        # latest_migration will be an int
        EXEC_SQL='--execute="SELECT MAX(version) FROM migrations;"'
        latest_migration=`$SSH_PREFIX $MYSQL_CLIENT ${EXEC_SQL} ${DB_NAME} 2>&1`
        if [[ `echo "${latest_migration}" |cut -c 1-10` == "ERROR 1146" ]]; then
            echo "`date` :Running initial migration"
            latest_migration=0
        fi
        
        for file in `ls ./sql`; do
            file_migration_no=`echo "$file" |cut -c1-3`
            if [[ $latest_migration -lt $file_migration_no ]]; then
                echo "`date` :Executing migration $file_migration_no from file $file...";
                echo "`date` :__________________________________________";
                echo "`date` :SQL OUTPUT:";
                echo "`date` :__________________________________________";
                TAIL="-se '`cat ./sql/${file}`'"
                sqlout=`$SSH_PREFIX $MYSQL_CLIENT ${TAIL} 2>&1`
                if [[ $? -eq 0 ]]; then 
                    TAIL="-se 'INSERT INTO migrations (version) VALUES (${file_migration_no});'"
                    `$SSH_PREFIX $MYSQL_CLIENT ${TAIL}`
                else
                    echo ${sqlout}
                    exit 1
                fi
            fi
        done
    else
        echo "`date` :Either the DB is down or the exit status returned by
        the script shows ERROR."
        echo "`date` :Exiting ..."
        exit
    fi
}

# main function
Main() {
    echo "`date` :Starting sql auto run script."
    runmysqls
    echo "`date` :sql auto run script execution completed."
}
Main

当我针对远程数据库 运行 时,它 运行 没问题。但是当我 运行 针对本地实例时,它只是打印出 mysql 帮助消息。

我打印的命令是运行、$ mysql --protocol=tcp -h localhost -u root --password=hotdog99 -e 'SELECT 1;' cooldb

但如果我将脚本输出中的内容复制并粘贴到终端中,运行没问题!

如果我设置

EXEC_SQL=""

它让我进入 mysql shell,但是一旦插入 -e 'SELECT 1;'--execute='SELECT 1;',它就会返回打印 usage/help 消息.

当您 运行 它针对远程数据库时,您将 'SELECT 1;' 传递给 ssh,后者将它作为命令行参数传递给 shell ,并且 shell 按预期去除了单引号 ('')。

当你在本地 运行 时,你只是在取消引用一个变量。您没有将它作为参数传递给 shell,因此它按原样扩展,这意味着您传递给 mysql 的参数是 'SELECT 1;',即带有引号。

您应该改用 sh -c "$cmd"

演示:

$ ARG="'hello'"
$ cmd="echo ${ARG}"
$ echo $cmd
echo 'hello'
$ $cmd
'hello'
$ sh -c "$cmd"
hello
$ cmd="ssh 0 echo ${ARG}"
$ $cmd
hello