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

时间:2013-12-23 21:21:14

标签: mysql bash shell

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

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

执行按预期工作,但始终发出警告:

  

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

但是,我必须使用存储我的密码的环境变量($password)来执行上述声明,因为我想在终端内的bash脚本中迭代地运行命令,我绝对不喜欢等待提示出现并强迫我在单个脚本中输入密码50或100次的想法。所以这是我的问题:

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

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

运行man mysql没有帮助,只说

  

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

如果我没有遗漏某些东西,

并没有提及如何关闭功能。

我使用OS X 10.9.1 Mavericks并使用自制程序中的MySQL 5.6。

25 个答案:

答案 0 :(得分:213)

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

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"

答案 1 :(得分:181)

我用的是:

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

答案 2 :(得分:164)

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

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 这种版本的系统上,假设用户没有其他方法可以检查过程环境也是不明智的。

答案 3 :(得分:57)

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

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

它基本上将标准错误重定向到标准输出 - 并使用grep删除所有符合&#34的行;警告:使用密码"。

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

答案 4 :(得分:39)

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

  1. 首先使用 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”更改为服务器上的用户名。

  2. 从此处更改bash脚本:

    mysqldump -u db_user -pInsecurePassword my_database | gzip > db_backup.tar.gz
    

    到此:

    mysqldump --login-path=local my_database | gzip > db_backup.tar.gz
    
  3. 没有更多暴露的密码。

答案 5 :(得分:10)

最简单的方法是

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

答案 6 :(得分:9)

您还可以在脚本中运行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

答案 7 :(得分:4)

这很简单。这对我来说是工作。

export MYSQL_PWD=password; mysql --user=username -e "statement"

MYSQL_PWD是mysql的环境变量之一。这是连接到mysqld时的默认密码。

答案 8 :(得分:4)

来自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

答案 9 :(得分:4)

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

答案 10 :(得分:2)

一个简单的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

答案 11 :(得分:2)

以下是脚本/ 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'

     

docker 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。

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

答案 12 :(得分:2)

好的,没有临时文件或其他任何东西的解决方案:

mysql --defaults-extra-file=<(echo $'[client]\npassword='"$password") -u $user -e "statement"

它与其他人所提到的相似,但是这里您不需要实际的文件,该命令的这一部分会伪造该文件:<(echo ...) (请注意,文件中间没有空格<(

答案 13 :(得分:2)

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

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

答案 14 :(得分:1)

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

那就这样做吧

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

答案 15 :(得分:1)

定义助手:

remove-warning () {
    grep -v 'mysql: [Warning] Using a password on the command line interface can be insecure.'
}

使用它:

mysql -u $user -p$password -e "statement" 2>&1 | remove-warning

Tachaan!您的代码干净而且易于阅读

(通过bash测试)

答案 16 :(得分:1)

如果您碰巧使用Rundeck来安排任务,或在任何其他需要mylogin.cnf文件的平台上使用,则在继续执行sql之前,我已成功使用以下Shell代码为文件提供了新位置通话:

if test -f "$CUSTOM_MY_LOGINS_FILE_PATH"; then
   chmod 600 $CUSTOM_MY_LOGINS_FILE_PATH
   export MYSQL_TEST_LOGIN_FILE="$CUSTOM_MY_LOGINS_FILE_PATH"
fi

...

result=$(mysql --login-path=production -NBA -D $schema -e "$query")

MYSQL_TEST_LOGIN_FILE是一个环境变量,可以将其设置为与默认文件路径不同的文件路径。

如果您正在分叉的进程中运行,并且无法将文件移动或复制到$HOME目录中,则此功能特别有用。

See documentation here.

答案 17 :(得分:0)

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

#!/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

答案 18 :(得分:0)

对于PowerShell(pwsh,而不是bash),这是一个很好的解决方案...我的第一个尝试是将对mysql的调用包装在{{1 }}功能,但是由于某些strange behavior in PowerShell error handling,这是不可行的。

解决方案是重写try/catch足够长的时间以合并并捕获$ErrorActionPreferenceSTDERR并解析单词STDOUT并根据需要重新抛出。我们无法在ERROR上捕获和释放的原因是因为PowerShell将错误作为一个流处理并引发该错误,因此您必须捕获所有错误以进行过滤和重新抛出。 :/

"^mysql.*Warning.*password"

注意:PowerShell适用于Unix,因此该解决方案是跨平台的。只需进行一些小的语法修改即可使其适应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" } }

警告::有许多边缘情况无法解决,例如非英语错误消息或在输出中的任何地方返回单词bash的语句,但是足以掩盖对ERROR的基本调用的警告,而又​​不会炸毁整个脚本。希望其他人觉得这有用。

如果mysql只是添加了一个禁止显示此警告的选项,那就太好了。

答案 19 :(得分:0)

最好的解决方案是使用别名:

alias [yourapp]-mysql="mysql -u root -psomepassword -P3306 -h 127.0.0.1"

示例,将其放在脚本中:

alias drupal-mysql="mysql -u root -psomepassword -P3306 -h 127.0.0.1"

然后在脚本中稍后加载数据库:

drupal-mysql database_name < database_dump.sql

运行语句:

drupal-mysql -e "EXEC SOMESTATEMENT;"

答案 20 :(得分:0)

最简单的方法:

mysql -u root -p YOUR_DATABASE

输入此密码,您将需要输入密码。

注意:是的,没有分号。

答案 21 :(得分:-2)

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

 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

答案 22 :(得分:-2)

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

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

这只返回最后一行

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

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

答案 23 :(得分:-3)

您可以使用/ 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

享受!

答案 24 :(得分:-3)

它对我有用 - 刚刚在2> null之后添加了$(mysql_command),它只会抑制错误和警告消息。