当我尝试在终端内运行MySQL上的以下命令时:
mysql -u $user -p$password -e "statement"
执行按预期工作,但它总是发出一个警告:
警告:在命令行界面上使用密码可能不安全。
但是,我必须使用存储密码的环境变量($password)来执行上面的语句,因为我想从Terminal中在bash脚本中迭代地运行命令,而且我绝对不喜欢等待提示显示并强迫我在一个脚本中输入密码50或100次的想法。我的问题是:
压制警告可行吗?如我所述,该命令可以正常工作,但是当我循环并运行该命令50或100次时,窗口变得非常混乱。
我应该遵守警告信息,不写我的密码在我的脚本?如果是这样的话,那么每次提示时我都必须输入密码吗?
Running man mysql没有帮助,说的只是
——显示警告
在每条语句后显示警告(如果有的话)。此选项适用于交互和批处理模式。
也没有提到如何关闭功能,如果我没有错过什么。
我使用的是OS X 10.9.1 Mavericks,使用的是自制的MySQL 5.6。
我使用的是:
mysql --defaults-extra-file=/path/to/config.cnf
or
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
一种方便(但同样不安全)的方法是使用:
MYSQL_PWD=xxxxxxxx mysql -u root -e "statement"
请注意,官方文件不建议这样做。
请参见6.1.2.1密码安全终端用户指南(Mysql手册for Version 5.6):
Storing your password in the MYSQL_PWD environment variable
This method of specifying your MySQL password must be considered extremely insecure and should not be used. Some versions of ps include an option to display the environment of running processes. On some systems, if you set MYSQL_PWD, your password is exposed to any other user who runs ps. Even on systems without such a version of ps, it is unwise to assume that there are no other methods by which users can examine process environments.
您可以使用/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
享受吧!
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
对于PowerShell (pwsh,而不是bash),这是一个相当土豪的解决方案……我的第一次尝试是在try/catch函数中包装对mysql的调用,但由于PowerShell错误处理中的一些奇怪行为,这是不可行的。
解决方案是重写$ErrorActionPreference,以足够长的时间组合和捕获STDERR和STDOUT,并解析单词ERROR并根据需要重新抛出。我们不能捕获和释放“^mysql.*警告。因为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是一个环境变量,可以设置为与默认文件不同的文件路径。
如果您运行在一个fork进程中,并且不能移动或复制文件到$HOME目录,这尤其有用。
请在这里查看文档。
来自@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中捕获退出码。