使用echo命令通过shell脚本自动化执行mysql_secure_installation

81

我正在尝试使用自动响应脚本自动化mysql_secure_installation。我的代码如下:

echo "& y y abc abc y y y y" | ./usr/bin/mysql_secure_installation

我要自动化的实际问题如下:

Enter current password for root (enter for none): <enter>
Set root password? [Y/n] y
New password: abc
Re-enter new password: abc
Remove anonymous users? [Y/n] y
Disallow root login remotely? [Y/n] y
Remove test database and access to it? [Y/n] y
Reload privilege tables now? [Y/n] y

但是它给了我一个错误提示:“抱歉,您不能在此处使用空密码”,但在我用来回答第一个问题的屏幕上,我按了返回键。


解决这个问题的方法是手动运行所有在mysql_secure_install期间触发的查询。目前它可以正常工作。谢谢。 - cucucool
16个回答

100

我偶然看到这个问题,但决定通过Bash脚本手动运行查询:

#!/bin/bash

# Make sure that NOBODY can access the server without a password
mysql -e "UPDATE mysql.user SET Password = PASSWORD('CHANGEME') WHERE User = 'root'"
# Kill the anonymous users
mysql -e "DROP USER ''@'localhost'"
# Because our hostname varies we'll use some Bash magic here.
mysql -e "DROP USER ''@'$(hostname)'"
# Kill off the demo database
mysql -e "DROP DATABASE test"
# Make our changes take effect
mysql -e "FLUSH PRIVILEGES"
# Any subsequent tries to run queries this way will get access denied because lack of usr/pwd param

12
禁止root用户远程登录DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1'); - Tirsvad
1
对于Mariadb,使用以下命令:mysql -e "ALTER USER 'root'@'localhost' IDENTIFIED BY 'password'; FLUSH PRIVILEGES;" - MaXi32
如果测试数据库不存在,这将以“0”返回状态退出,因此如果您使用set -e,它不会终止您的脚本:mysql -e“DROP DATABASE IF EXISTS test” - Freedom_Ben
4
MariaDB 10.6 显示此错误 **View 'mysql.user' references invalid table(s)**。 - vee
1
@vee 这是因为mysql.user不再是一个表,而是一个视图。你应该将语句更改为ALTER USER root@localhost IDENTIFIED BY 'strongpassword' - BUFU

63

由于 mysql_secure_installation 只是一个 Bash 脚本,所以只需检查此处显示的原始源代码。查找包含 do_query(注意我在do_query后面添加的额外空格;需要查找查询而不是函数)的行,然后您就可以找到这些命令。

UPDATE mysql.user SET Password=PASSWORD('root') WHERE User='root';
DELETE FROM mysql.user WHERE User='';
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
FLUSH PRIVILEGES;

请注意,对于这个例子,我把密码设置为root,但你可以随意更改以匹配你的设置需求。无论如何,把这些简单的 MySQL 命令保存在一个名为mysql_secure_installation.sql的文件中。

完成后,运行以下命令通过脚本保护 MySQL 安装:

mysql -sfu root < "mysql_secure_installation.sql"

s参数可以静默处理错误,f参数可以强制命令继续执行即使一个命令失败,u参数与其紧随的用户名相关,在这种情况下显然是root

将它在部署脚本中运行,其中MySQL最初安装时没有密码,并且您已设置好在没有任何键盘交互的情况下将其锁定。

附注:此脚本是为了在Ubuntu 14.04上安装MySQL时保护其而编写的。在安装过程中,使用了export DEBIAN_FRONTEND=noninteractive设置和实际安装命令设置为sudo -E aptitude install -y --assume-yes -q mysql-server mysql-client。这样做将在Ubuntu上干净地安装MySQL而无需密码;这对于部署脚本非常方便。然后,此mysql -sfu root < "mysql_secure_installation.sql"命令将在安装完成后几秒钟内将其全部锁定。


5
提供信息,MySQL 8中,团队用C++重写了mysql_secure_installation。如果您仍想使用从那里挑选命令的方法,请查看此处的源代码。更新密码的语法已更改:https://github.com/mysql/mysql-server/blob/7ed30a748964c009d4909cb8b4b22036ebdef239/client/mysql_secure_installation.cc - pietrorea

32

我刚在CentOS 6.7上完成了以下操作:

mysql_secure_installation <<EOF

y
secret
secret
y
y
y
y
EOF

1
非常好的答案。这个技巧很棒——它也适用于fdisk。干净易读。 - David Betz
9
方便是没问题,但可读性不高,无法让人知道正在发生什么。 - bschlueter
很好的Centos 6答案,但是不幸的是在7上对我没有用。 - John Elion
3
无法在Ubuntu 16.04上运行,mysql_secure_installation一直要求输入root密码。 - ssc
2
为什么要模拟标准输入,当你可以执行脚本执行的确切查询?这种解决方法是不好的实践。阅读您的脚本的读者不知道脚本在做什么。 - raw-bin hood
显示剩余3条评论

27

2
请更新“except”链接,该链接导致错误:指定了两个或更多的软件包(期望是wheezy)。 - Book Of Zeus

7

这里是一个自动化脚本,用于基于@Giacomo1968的答案的全新MySQL 5.7安装。在CentOS 7.5.1804上运行良好。

yum localinstall -y https://dev.mysql.com/get/mysql57-community-release-el7-9.noarch.rpm
yum install -y mysql-community-server

# start mysql service
service mysqld start

# get Temporary root Password
root_temp_pass=$(grep 'A temporary password' /var/log/mysqld.log |tail -1 |awk '{split($0,a,": "); print a[2]}')

echo "root_temp_pass:"$root_temp_pass

# mysql_secure_installation.sql
cat > mysql_secure_installation.sql << EOF
# Make sure that NOBODY can access the server without a password
UPDATE mysql.user SET Password=PASSWORD('yourrootpass') WHERE User='root';
# Kill the anonymous users
DELETE FROM mysql.user WHERE User='';
# disallow remote login for root
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
# Kill off the demo database
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
# Make our changes take effect
FLUSH PRIVILEGES;
EOF

mysql -uroot -p"$root_temp_pass" --connect-expired-password <mysql_secure_installation.sql

6

不需要使用 expect 命令或从源代码中获取 SQL 命令(但如果你想要的话,C++ 文件在这里:https://github.com/mysql/mysql-server/blob/7ed30a748964c009d4909cb8b4b22036ebdef239/client/mysql_secure_installation.cc)。

如果你对 mysql_secure_installation 中的默认设置感到满意(最安全的选项总是默认值),那么你可以使用 --use-default 选项跳过大部分交互。如果未设置 root 密码,则 mysql_secure_installation 仍会要求您进行交互式设置,因此您可以通过在调用 mysql_secure_option 之前设置密码来自动化此过程。

以下是一个示例:

mysql -u root <<EOF
SET PASSWORD FOR root@localhost = '${ROOT_PASSWORD}';
FLUSH PRIVILEGES;
EOF

mysql_secure_installation -u root --password="${ROOT_PASSWORD}" --use-default

在我看来,这是最好的答案,最简洁地回答了OP的需求,而且不会很笨拙(即标题中提到的“echo”部分)。 - jbobbins
我的mariadb安装版本(Ver 15.1 Distrib 10.5.15-MariaDB,for debian-linux-gnu (aarch64))中不存在此标志。 - BUFU

6
sudo mysql -e "SET PASSWORD FOR root@localhost = PASSWORD('123');FLUSH PRIVILEGES;" 

printf "123\n n\n n\n n\n y\n y\n y\n" | sudo mysql_secure_installation

输入root用户的当前密码(如果没有则不用输入)?(我的root密码是123)

切换到unix_socket身份验证?n

更改root密码?n

删除匿名用户?n

禁止远程登录root用户?y

删除测试数据库及其访问权限?y

立即重新加载权限表?y

版本: mysql Ver 15.1 Distrib 10.4.6-MariaDB,for osx10.14(x86_64),使用readline 5.1


3

我也遇到了同样的问题。 使用-e\n来替换echo命令似乎解决了这个问题。

echo -e "\ny\ny\nabc\nabc\ny\ny\ny\ny\n" | ./usr/bin/mysql_secure_installation

2

适用于AWS。Amazon Linux 2 AMI。 自定义设置以启动实例(AWS用户数据):

#!/bin/bash            
sudo yum -y update &> /dev/null
wget https://repo.mysql.com/mysql80-community-release-el7-1.noarch.rpm &> /dev/null
sudo yum -y localinstall mysql80-community-release-el7-1.noarch.rpm
sudo yum -y install mysql-community-server &> /dev/null
sudo service mysqld start
   
# get Temporary root Password
root_temp_pass=$(sudo grep 'A temporary password' /var/log/mysqld.log |tail -1 |awk '{split($0,a,": "); print a[2]}')
echo "root_temp_pass: " $root_temp_pass
# mysql_secure_installation.sql
sudo cat > mysql_secure_installation.sql << EOF
# Make sure that NOBODY can access the server without a password
ALTER USER 'root'@'localhost' IDENTIFIED BY 'yourrootpass';
# Kill the anonymous users
DELETE FROM mysql.user WHERE User='';
# disallow remote login for root
DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
# Kill off the demo database
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
# Make our changes take effect
FLUSH PRIVILEGES;
EOF
        
sudo mysql -uroot -p"$root_temp_pass" --connect-expired-password <mysql_secure_installation.sql
sudo systemctl enable mysql

2

我在Ubuntu Bionic 18.04LTS上进行了测试。

步骤 #1

export MYPWD="D33Ps3CR3T";
export NEWPWD="D33P3Rs3CR3T";

第二步。
# First time **ever**
sudo mysql_secure_installation 2>/dev/null <<MSI

n
y
${MYPWD}
${MYPWD}
y
y
y
y

MSI

# Did it work?
mysql -u root -p${MYPWD} -e "SELECT 1+1";
# -------

步骤 #3
# Every subsequent time
sudo mysql_secure_installation 2>/dev/null <<MSI2
${MYPWD}
n
y
${NEWPWD}
${NEWPWD}
y
y
y
y

MSI2

# Just in case (optional) ....
sudo service mysql restart

# Did it work?
mysql -u root -p${NEWPWD} -e "SELECT 1+1";

在编辑步骤#1中的旧密码和新密码后,您应该能够直接将步骤#2和#3复制并粘贴到终端中。

注释

  • 如果已设置根密码,则步骤#2将失败,请转到步骤#3
  • 这只是一个被传递到命令中的heredoc
  • sudo是必须的。
  • MSI没有特定的含义(这是避免冲突;我在脚本的其他地方使用EOF)
  • MYPWD == NEWPWD是允许的
  • 2>/dev/null隐藏警告信息"stty:'standard input': Inappropriate ioctl for device"
  • 您可以使用&>/dev/null进行完全静音模式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接