/null; then
? ? ? ? ? ? ? ? break
? ? ? ? ? ? fi
? ? ? ? ? ? echo 'MySQL init process in progress...'
? ? ? ? ? ? sleep 1
? ? ? ? done
? ? ? ? if [ "$i" = 0 ]; then
? ? ? ? ? ? echo >&2 'MySQL init process failed.'
? ? ? ? ? ? exit 1
? ? ? ? fi
这段代码主要是利用mysql客户端测试mysql服务是否启动。这里面利用括号()构造mysql变量的方式挺有意思的,以前没有见过。特意验证了一下:
[root@localhost ~]# mysql=( mysql --protocol=socket -uroot )
[root@localhost ~]# echo ${mysql}
mysql
[root@localhost ~]# echo ${mysql[@]}
mysql --protocol=socket -uroot
这段代码给了30s的时间来判断mysql服务是否已启动,如果启动了,则退出循环,如果没有启动,循环结束后,变量i的值为0,通过后续的if语句,屏幕输出“MySQL init process failed”。
这里判断mysql服务是否启动的方式蛮有意思的,
[root@localhost ~]# mysql=( mysql --protocol=socket -uroot )
[root@localhost ~]# echo 'SELECT 1' | "${mysql[@]}"
1
1
[root@localhost ~]# mysql
Welcome to the MySQL monitor.? Commands end with ; or \g.
Your MySQL connection id is 11
Server version: 5.6.26 MySQL Community Server (GPL)
mysql> select 1;
+---+
| 1 |
+---+
| 1 |
+---+
1 row in set (0.01 sec)
?
如果停掉了mysql服务,则输出如下:
[root@localhost ~]# systemctl stop mysqld
[root@localhost ~]# echo 'SELECT 1' | "${mysql[@]}"
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
在这里,还有一点很让人疑惑,
?if echo 'SELECT 1' | "${mysql[@]}" &> /dev/null; then
? ? break
?fi
if判断的条件难道不是echo 'SELECT 1' | "${mysql[@]}"命令的返回码么?如果是这样的话,成功执行,则$?为0,此时不应该执行break语句的,但事实与推测的相反。关于这点暂且留下。
9>
mysql_tzinfo_to_sql /usr/share/zoneinfo | sed 's/Local time zone must be set--see zic manual page/FCTY/' | "${mysql[@]}" mysql
修改mysql关于时区的一个bug,不去深究。
10>
?
? ? ? "${mysql[@]}" <<-EOSQL
? ? ? ? ? ? -- What's done in this file shouldn't be replicated
? ? ? ? ? ? --? or products like mysql-fabric won't work
? ? ? ? ? ? SET @@SESSION.SQL_LOG_BIN=0;
? ? ? ? ? ? DELETE FROM mysql.user ;
? ? ? ? ? ? CREATE USER 'root'@'%' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}' ;
? ? ? ? ? ? GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION ;
? ? ? ? ? ? DROP DATABASE IF EXISTS test ;
? ? ? ? ? ? FLUSH PRIVILEGES ;
? ? ? ? EOSQL
?
这段主要是用客户端登录数据库进行相关操作,包括修改root密码,为其授权,删除测试数据库等。SET @@SESSION.SQL_LOG_BIN=0的作用是停止使用日志文件,这点不是很明白。
11>
?
? ? ? ? if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then
? ? ? ? ? ? mysql+=( -p"${MYSQL_ROOT_PASSWORD}" )
? ? ? ? fi
? ? ? ? if [ "$MYSQL_DATABASE" ]; then
? ? ? ? ? ? echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" | "${mysql[@]}"
? ? ? ? ? ? mysql+=( "$MYSQL_DATABASE" )
? ? ? ? fi
? ? ? ? if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then
? ? ? ? ? ? echo "CREATE USER '"$MYSQL_USER"'@'%' IDENTIFIED BY '"$MYSQL_PASSWORD"' ;" | "${mysql[@]}"
? ? ? ? ? ? if [ "$MYSQL_DATABASE" ]; then
? ? ? ? ? ? ? ? echo "GRANT ALL ON \`"$MYSQL_DATABASE"\`.* TO '"$MYSQL_USER"'@'%' ;" | "${mysql[@]}"
? ? ? ? ? ? fi
? ? ? ? ? ? echo 'FLUSH PRIVILEGES ;' | "${mysql[@]}"
? ? ? ? fi
?
这段代码主要是创建数据库,新建mysql用户,并授权。这其实意味着用户在启动容器时可以通过指定MYSQL_DATABASE参数来创建数据库,通过MYSQL_USER和MYSQL_PASSWORD来创建新的数据库用户。
其中,mysql+=( -p"${MYSQL_ROOT_PASSWORD}" )用于拼接变量。譬如:
[root@localhost ~]# mysql=( mysql --protocol=socket -uroot )
[root@localhost ~]# MYSQL_DATABASE=docker
[root@localhost ~]# mysql+=( "$MYSQL_DATABASE" )
[root@localhost ~]# echo ${mysql[@]}
mysql --protocol=socket -uroot docker
12>
?
? ? ? for f in /docker-entrypoint-initdb.d/*; do
? ? ? ? ? ? case "$f" in
? ? ? ? ? ? ? ? *.sh)? echo "$0: running $f"; . "$f" ;;
? ? ? ? ? ? ? ? *.sql) echo "$0: running $f"; "${mysql[@]}" < "$f" && echo ;;
? ? ? ? ? ? ? ? *)? ? echo "$0: ignoring $f" ;;
? ? ? ? ? ? esac
? ? ? ? ? ? echo
? ? ? ? done? ? ?
?
其它需要执行的shell脚本或者sql脚本,可放到/docker-entrypoint-initdb.d/目录下。只需启动容器时,通过-v参数将容器该目录挂载到宿主机目录上。
13>
? ? ? ? if ! kill -s TERM "$pid" || ! wait "$pid"; then
? ? ? ? ? ? echo >&2 'MySQL in