当我尝试从终端中在 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。
~/.my.cnf
中的 [client]
password=my_password
)。当然,它也有一些安全隐患,但至少 任何人 都无法运行 ps
,并且您可以通过文件权限控制它。
mysql -u root password root -e "statement" > /dev/null
?
pexcept
之类的东西。它可以进行终端插入,也可以处理命令给出的反馈。这样你就可以跳过那个详细的输出并去掉你想要的实际输出:)
如果您的 MySQL 客户端/服务器版本是 5.6.xa 避免 WARNING 消息的方法,则使用 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"
我使用类似的东西:
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
--defaults-extra-file
必须是第一个选项,否则 mysql 会报错 mysqldump: unknown variable 'defaults-extra-file
。
MYSQL_PWD
变量....
mysql --defaults-extra-file=<(printf "[client]\nuser = %s\npassword = %s" "$user" "$pwd") -e "statement"
。由于 printf
是由 Bash 直接执行的,因此它不会显示在 ps
中。
--defaults-file
而不是 --defaults-extra-file
,因为后者优先考虑 ~/.my.cnf 中的设置。
一种方便(但同样不安全)的方法是使用:
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 的系统上,假设没有其他方法可供用户检查进程环境也是不明智的。
Access denied for user 'root'@'localhost' (using password: NO)
export MYSQL_PWD=whatever
。
export
的脚本中,只需将其全部放在一行中:MYSQL_PWD=xxxxxxxx mysql -u root -e "statement"
如果您希望在命令行中使用密码,我发现这可以过滤掉特定的错误消息:
mysqlcommand 2>&1 | grep -v "Warning: Using a password"
它基本上是将标准错误重定向到标准输出——并使用 grep 删除与“警告:使用密码”匹配的所有行。
这样,您可以看到任何其他输出,包括错误。我将它用于各种 shell 脚本等。
1>&2
)
以下是我如何让我的 bash 脚本让我的日常 mysqldump 数据库备份更安全地工作。这是 Cristian Porta 伟大的 answer 的扩展。
首先使用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
没有更多暴露的密码。
最简单的方法是
mysql -u root -pMYPASSWORD -e "show databases" 2>/dev/null
2>/dev/null | grep -v "mysql: [Warning] Using a password on the command line interface can be insecure."
仅抑制有问题的警告
这很简单。这对我来说是工作。
export MYSQL_PWD=password; mysql --user=username -e "statement"
MYSQL_PWD
是 environment variables that are used directly or indirectly by MySQL 之一。
从文档:
MYSQL_PWD - 连接到 mysqld 时的默认密码。使用它是不安全的。请参见第 6.1.2.1 节“密码安全的最终用户指南”。
MYSQL_PWD
环境变量来指定 MySQL 密码。
好的,没有临时文件或任何东西的解决方案:
mysql --defaults-extra-file=<(echo $'[client]\npassword='"$password") -u $user -e "statement"
它与其他人提到的类似,但这里您不需要实际文件,这部分命令伪造文件:<(echo ...)
(注意<(
中间没有空格强>
~/.
中已经有一个带有密码条目的 .my.cnf
文件,这将不起作用
mysql[dump]
报告的安全问题来自密码将出现在正在运行的进程列表中的事实(请参阅 ps -ef | grep mysql
)。如果您将它放在该语句中所示的变量中,则可能没问题。但是,如果您有明文而不是 $password
的密码,那也不会好多少(回显会非常快,因此作为黑客,在这种情况下更难获取信息,但仍有可能)。
您还可以在脚本中运行 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}
"
这将启动一个期望会话,该会话可在脚本中用于与提示交互
一个简单的工作脚本。将此命名为“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
您也可以将标准错误 STDERR 输出重定向到 /dev/null
所以就这样做:
mysql -u $user -p$password -e "statement" 2> /dev/null
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
来自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
另一种选择是使用 sshpass 来调用 mysql,例如:
sshpass -p topsecret mysql -u root -p username -e 'statement'
这是脚本 /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。
希望它会帮助你喜欢它可以帮助我!
docker exec [MYSQL_CONTAINER_NAME] sh -c 'exec echo "[client] [RETURN HERE] password=pa55" > /root/defaults'
使用 --defaults-file
它也已经获得了 root 权限。
定义助手:
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
塔查安!您的代码干净且易于阅读
(用 bash 测试)
就个人而言,我使用脚本包装器来捕获该错误。这是代码示例:
#!/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
对于 PowerShell(pwsh
,而不是 bash
),这完全是一个 rube-goldberg 解决方案...我的第一次尝试是将对 mysql
的调用包装在 try/catch
函数中,但由于某些 strange behavior in PowerShell error handling ,这是不可行的。
解决方案是将 $ErrorActionPreference
覆盖足够长的时间以组合和捕获 STDERR
和 STDOUT
并解析单词 ERROR
并根据需要重新抛出。我们无法在 "^mysql.*Warning.*password"
上捕获和释放的原因是 PowerShell 将错误作为一个流处理并引发,因此您必须全部捕获才能过滤和重新抛出。 :/
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"
}
}
注意: PowerShell 可用于 Unix,因此该解决方案是跨平台的。它可以通过一些小的语法修改来适应 bash
。
警告: 有许多边缘情况不起作用,例如非英语错误消息或在输出中的任何位置返回单词 ERROR
的语句,但这足以吞下对 mysql
的基本调用发出警告,而不会炸毁整个脚本。希望其他人觉得这很有用。
如果 mysql
简单地添加一个选项来禁止此警告,那就太好了。
如果您碰巧使用 Rundeck 来安排您的任务,或者您要求提供 mylogin.cnf
文件的任何其他平台,我已成功使用以下 shell 代码为该文件提供一个新位置,然后再继续执行 sql 调用:
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
目录,这将特别有用。
我遇到的问题是在 bash 脚本中使用条件输出。
这并不优雅,但在 docker env 中,这真的无关紧要。基本上所有这些都是忽略不在最后一行的输出。您可以使用 awk 执行类似操作,并更改为返回除第一行以外的所有内容等。
这只返回最后一行
mysql -u db_user -pInsecurePassword my_database ... | sed -e '$!d'
它不会抑制错误,但会确保您可以在 bash 脚本中使用查询的输出。
最好的解决方案是使用别名:
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;"
@david-g 的答案非常好,但至少 BSD grep
会将 [Warning]
解释为单个字符的正则表达式表示(匹配单词 Warning
中的任何一个字符)。
对于我的脚本,我使用相同的方法,包装在一个函数中(为了简单起见,只匹配字符串的部分):
mysql() {
(
(
(
(
(
/usr/local/bin/mysql "$@"
) 1>&9
) 2>&1
) | grep -v 'Using a password on the command line interface can be insecure.'
) 1>&2
) 9>&1
}
out=$(mysql ...... 2>&1)
rc=$?
以上将使用一组选项调用 mysql,将过滤后的 stderr 重定向到 stdout,并捕获 $opt
中的组合输出和 $rc
中的退出代码。
另一种解决方案(例如,来自脚本):
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
它对我有用 - 只是在 $(mysql_command)
之后添加了 2> null
,它只会抑制错误和警告消息。
2>/dev/null
。使用 2> null
只会将输出放入当前目录中名为“null”的文件中。
您可以使用 /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
请享用!
最简单的方法:
mysql -u root -p YOUR_DATABASE
输入这个,你需要输入你的密码。
注意:是的,没有分号。
不定期副业成功案例分享
--login-path
必须位于所有其他参数之前。我正在尝试mysqldump --tables --login-path=local
并收到错误unknown variable 'login-path=local'
。