首页 文章

使用终端内的mysql抑制警告消息,但用bash脚本编写密码

提问于
浏览
203

当我在终端内尝试在MySQL上运行以下命令时:

mysql -u $user -p$password -e "statement"

执行按预期工作,但它总是发出警告:

警告:在命令行界面上使用密码可能不安全 .

但是,我必须使用存储我的密码的环境变量( $password )来执行上述语句,因为我想在终端内的bash脚本中迭代地运行命令,我绝对不会回答我的问题:

  • 抑制警告是否可行?正如我所说,该命令正常工作,但当我循环并运行命令50或100次时,窗口变得非常混乱 .

  • 我是否应该遵守警告信息并且不在我的脚本中写入密码?如果是这种情况,那么每次提示强制我这样做时,我是否必须输入密码?

运行 man mysql 没有帮助,只说

--show-warnings如果有任何声明,则会在每个声明后显示警告 . 此选项适用于交互式和批处理模式 .

如果我没有遗漏某些东西,并且没有提及如何关闭功能 .

我在OS X 10.9.1 Mavericks上,并使用自制的MySQL 5.6 .

19 回答

  • 9

    如果您的MySQL客户端/服务器版本是5.6.x,则可以使用 mysql_config_editor 工具来避免WARNING消息:

    mysql_config_editor set --login-path=local --host=localhost --user=username --password
    

    然后你可以在你的shell脚本中使用:

    mysql --login-path=local  -e "statement"
    

    代替:

    mysql -u username -p pass -e "statement"
    
  • 145

    我使用类似的东西:

    mysql --defaults-extra-file=/path/to/config.cnf
    

    要么

    mysqldump --defaults-extra-file=/path/to/config.cnf
    

    config.cnf包含的位置:

    [client]
    user = whatever
    password = whatever
    host = whatever
    

    这允许您拥有多个配置文件 - 用于不同的服务器/角色/数据库 . 使用〜/ .my.cnf只允许你有一组配置(虽然它可能是一组有用的默认值) .

    如果您使用的是基于Debian的发行版,并以root身份运行,则可以跳过上述内容并使用/etc/mysql/debian.cnf进入...:

    mysql --defaults-extra-file=/etc/mysql/debian.cnf

  • 199

    一种方便(但同样不安全)的方法是使用:

    MYSQL_PWD=xxxxxxxx mysql -u root -e "statement"
    

    请注意,官方文档建议不要使用它 .
    6.1.2.1 End-User Guidelines for Password Security (Mysql Manual for Version 5.6)

    将您的密码存储在MYSQL_PWD环境变量中这种指定MySQL密码的方法必须被认为是非常不安全的,不应该使用 . 某些版本的ps包含一个显示正在运行的进程环境的选项 . 在某些系统上,如果设置MYSQL_PWD,则密码将暴露给运行ps的任何其他用户 . 即使在没有这种版本的ps的系统上,假设用户没有其他方法可以检查过程环境也是不明智的 .

  • 1

    如果您希望在命令行中使用密码,我发现这适用于过滤掉特定的错误消息:

    mysqlcommand 2>&1 | grep -v "Warning: Using a password"
    

    它基本上将标准错误重定向到标准输出 - 并使用grep删除所有符合“警告:使用密码”的行 .

    这样,您可以看到任何其他输出,包括错误 . 我将它用于各种shell脚本等 .

  • 1

    以下是我为每日mysqldump数据库备份获取bash脚本以更安全地工作的方法 . 这是Cristian Porta伟大答案的扩展 .

    • 首先使用 mysql_config_editor (自带的mysql 5.6)来设置加密的密码文件 . 假设您的用户名是"db_user" . 从shell提示符运行:
    mysql_config_editor set --login-path=local --host=localhost --user=db_user --password
    

    它会提示输入密码 . 输入后,用户/通行证将以加密方式保存在 home/system_username/.mylogin.cnf

    当然,将“system_username”更改为服务器上的用户名 .

    • 从此更改bash脚本:
    mysqldump -u db_user -pInsecurePassword my_database | gzip > db_backup.tar.gz
    

    对此:

    mysqldump --login-path=local my_database | gzip > db_backup.tar.gz
    

    没有更多暴露的密码 .

  • 0

    最简单的方法是

    mysql -u root -pMYPASSWORD -e "show databases" 2>/dev/null
    
  • -2

    您还可以在脚本中运行mysql_config_editor,以在指定登录路径时传入密码

    expect -c "
    spawn mysql_config_editor set --login-path=$mySqlUser --host=localhost --user=$mySqlUser --password
    expect -nocase \"Enter password:\" {send \"$mySqlPassword\r\"; interact}
    "
    

    这将启动一个期望会话,该会话可以在脚本中用于与提示进行交互

    See this post

  • 1

    来自https://gist.github.com/nestoru/4f684f206c399894952d

    # Let us consider the following typical mysql backup script:
    mysqldump --routines --no-data -h $mysqlHost -P $mysqlPort -u $mysqlUser -p$mysqlPassword $database
    
    # It succeeds but stderr will get:
    # Warning: Using a password on the command line interface can be insecure.
    # You can fix this with the below hack:
    credentialsFile=/mysql-credentials.cnf
    echo "[client]" > $credentialsFile
    echo "user=$mysqlUser" >> $credentialsFile
    echo "password=$mysqlPassword" >> $credentialsFile
    echo "host=$mysqlHost" >> $credentialsFile
    mysqldump --defaults-extra-file=$credentialsFile --routines --no-data $database
    
    # This should not be IMO an error. It is just a 'considered best practice'
    # Read more from http://thinkinginsoftware.blogspot.com/2015/10/solution-for-mysql-warning-using.html
    
  • 159
    shell> mysql_config_editor set --login-path=local
         --host=localhost --user=localuser --password
    Enter password: enter password "localpass" here
    shell> mysql_config_editor set --login-path=remote
         --host=remote.example.com --user=remoteuser --password
    Enter password: enter password "remotepass" here
    

    要查看mysql_config_editor写入.mylogin.cnf文件的内容,请使用print命令:

    shell> mysql_config_editor print --all
    [local]
    user = localuser
    password = *****
    host = localhost
    [remote]
    user = remoteuser
    password = *****
    host = remote.example.com
    

    print命令将每个登录路径显示为一组行,以一个组头开头,表示方括号中的登录路径名,后跟登录路径的选项值 . 密码值被屏蔽,不会显示为明文 .

    如前面的示例所示,.mylogin.cnf文件可以包含多个登录路径 . 通过这种方式,mysql_config_editor可以轻松设置多个“个性”以连接到不同的MySQL服务器 . 当您调用客户端程序时,可以稍后使用--login-path选项按名称选择其中任何一个 . 例如,要连接到本地服务器,请使用以下命令:

    shell> mysql --login-path=local
    

    要连接到远程服务器,请使用以下命令:

    shell> mysql --login-path=remote
    
  • 3

    另一种方法是使用sshpass来调用mysql,例如:

    sshpass -p topsecret mysql -u root -p username -e 'statement'
    
  • 0

    这是脚本/ bin / sh中Docker的解决方案:

    docker exec [MYSQL_CONTAINER_NAME] sh -c'exec echo“[client]”> /root/mysql-credentials.cnf'docker exec[MYSQL_CONTAINER_NAME] sh -c'exec echo“user = root”>> /root/mysql-credentials.cnf'pocker exec [MYSQL_CONTAINER_NAME] sh -c'exec echo“password = $ MYSQL_ROOT_PASSWORD”>> / root / mysql-credentials .cnf'docker exec [MYSQL_CONTAINER_NAME] sh -c'exec mysqldump --defaults-extra-file = / root / mysql-credentials.cnf --all-databases'

    替换[MYSQL_CONTAINER_NAME]并确保在容器中设置了环境变量MYSQL_ROOT_PASSWORD .

    希望它会帮助你,它可以帮助我!

  • 4

    您也可以将标准错误STDERR输出重定向到/ dev / null

    所以这样做:

    mysql -u $user -p$password -e "statement" 2> /dev/null

  • -3

    就个人而言,我使用脚本包装器来捕获该错误 . 这是代码示例:

    #!/bin/bash
    
    #echo $@ | cat >> /home/mysqldump.log 2>/dev/null
    ERR_FILE=/tmp/tmp_mdump.err
    
    # Execute dumper
    /usr/bin/mysqldump $@ 2>$ERR_FILE
    
    # Determine error and remove tmp file
    ERROR=`cat $ERR_FILE`
    rm $ERR_FILE
    
    # Handle an error
    if [ "" != "$ERROR" ]; then
    
            # Error occured
            if [ "Warning: Using a password on the command line interface can be insecure." != "$ERROR" ]; then
                    echo $ERROR >&2
                    exit 1
            fi
    fi
    
  • 50

    一个简单的workaroud脚本 . 将此命名为“mysql”,并将其放在“/ usr / bin”之前的路径中 . 其他命令的明显变体,或警告文本不同 .

    #!/bin/sh
    
    (
    (
    (
    (
    (
        /usr/bin/mysql "$@"
    ) 1>&9 
    ) 2>&1
    ) | fgrep -v 'mysql: [Warning] Using a password on the command line interface can be insecure.'
    ) 1>&2 
    ) 9>&1
    
  • -3

    对于PowerShell( pwsh ,而不是 bash ),这是一个非常棒的解决方案......我的第一次尝试是将 mysql 的调用包装在一个 try/catch 函数中,但是由于某些strange behavior in PowerShell error handling,这是不可行的 .

    解决方案是覆盖 $ErrorActionPreference 只需要足够长的时间来组合并捕获 STDERRSTDOUT 并解析单词 ERROR 并根据需要重新抛出 . 我们无法在 "^mysql.*Warning.*password" 上捕获和释放的原因是因为PowerShell处理并将错误提升为一个流,因此您需要 must capture it all 才能过滤和重新抛出 . :/

    Function CallMySQL() {
        # Cache the error action preference
        $_temp = $ErrorActionPreference
        $ErrorActionPreference = "Continue"
    
        # Capture all output from mysql
        $output = (&mysql --user=foo --password=bar 2>&1)
    
        # Restore the error action preference
        $ErrorActionPreference = $_temp
    
        if ($output -match "ERROR") {
            throw $output
        } elseif($output) {
            "   Swallowing $output"
        } else {
            "   No output"
        }
    }
    

    Note: PowerShell适用于Unix,因此该解决方案是跨平台的 . 它可以通过一些小的语法修改来适应 bash .

    Warning: 有几十个边缘情况,这些不起作用,例如非英语错误消息或在输出中的任何地方返回单词 ERROR 的语句,但它足以吞下警告,以便在没有轰炸的情况下对 mysql 进行基本调用整个脚本 . 希望其他人觉得这很有用 .

    如果 mysql 只是添加一个选项来抑制此警告,那就太好了 .

  • 32

    另一种解决方案(例如来自脚本):

    sed -i'' -e "s/password=.*\$/password=$pass/g" ~/.my.cnf
     mysql -h $host -u $user $db_name -e "$sql_cmd"
    

    -i'' 选项用于兼容Mac OS X.标准UNIX操作系统可以直接使用 -i

  • 13

    我遇到的问题是在bash脚本中使用条件输出 .

    这不是很优雅,但在docker env中这应该没关系 . 基本上所有这一切都忽略了最后一行没有的输出 . 您可以使用awk执行类似操作,并更改为返回除第一行之外的所有内容等 .

    这只返回最后一行

    mysql -u db_user -pInsecurePassword my_database ... | sed -e '$!d'
    

    它不会抑制错误,但它会确保您可以在bash脚本中使用查询的输出 .

  • 0

    您可以使用/ dev / null执行mySQL并禁止显示警告和错误消息,例如:

    # if you run just a SQL-command
    mysql -u ${USERNAME} -p${PASSWORD} -h ${HOST} ${DATABASE} -e "${STATEMENT}" &> /dev/null
    
    # Or you can run SQL-script as a file
    mysql -u ${USERNAME} -p${PASSWORD} -h ${HOST} ${DATABASE} < ${FILEPATH} &> /dev/null
    

    哪里:

    ${USERNAME} - existing mysql user
    
    ${PASSWORD} - password
    
    ${HOST}     - ip or hostname, for example 'localhost'
    
    ${DATABASE} - name of database
    
    ${STATEMENT}- SQL command
    
    ${FILEPATH} - Path to the SQL-script
    

    请享用!

  • -2

    它对我有用 - 只需在 $(mysql_command) 之后添加 2> null ,它将仅抑制错误和警告消息 .

相关问题