[mysql] Convert to systemd startup support

Tom Lane tgl at fedoraproject.org
Wed Jul 27 19:14:17 UTC 2011


commit 69a13754993137c004c4c59c5e4bd85e4b5ab791
Author: Tom Lane <tgl at redhat.com>
Date:   Wed Jul 27 15:13:15 2011 -0400

    Convert to systemd startup support

 mysql.init            |  228 -------------------------------------------------
 mysql.spec            |   67 ++++++++++++---
 mysqld-nowatch.patch  |   51 +++++++++++
 mysqld-prepare-db-dir |   54 ++++++++++++
 mysqld-wait-ready     |   56 ++++++++++++
 mysqld.service        |   24 +++++
 6 files changed, 239 insertions(+), 241 deletions(-)
---
diff --git a/mysql.spec b/mysql.spec
index 0594a36..adfb127 100644
--- a/mysql.spec
+++ b/mysql.spec
@@ -1,6 +1,9 @@
 Name: mysql
 Version: 5.5.14
-Release: 2%{?dist}
+Release: 3%{?dist}
+# Update this whenever F15 gets rebased; it must be NVR-greater than F15 pkg:
+%global first_systemd_version 5.5.14-3
+
 Summary: MySQL client programs and shared libraries
 Group: Applications/Databases
 URL: http://www.mysql.com
@@ -20,7 +23,6 @@ Source0: mysql-%{version}-nodocs.tar.gz
 # the tarball into the current directory:
 # ./generate-tarball.sh $VERSION
 Source1: generate-tarball.sh
-Source2: mysql.init
 Source3: my.cnf
 Source4: scriptstub.c
 Source5: my_config.h
@@ -29,6 +31,9 @@ Source7: README.mysql-license
 Source8: libmysql.version
 Source9: mysql-embedded-check.c
 Source10: mysql.tmpfiles.d
+Source11: mysqld.service
+Source12: mysqld-prepare-db-dir
+Source13: mysqld-wait-ready
 # Working around perl dependency checking bug in rpm FTTB. Remove later.
 Source999: filter-requires-mysql.sh
 
@@ -45,6 +50,7 @@ Patch10: mysql-embedded-crash.patch
 Patch11: mysql-plugin-bool.patch
 Patch12: mysql-s390-tsc.patch
 Patch13: mysql-openssl-test.patch
+Patch14: mysqld-nowatch.patch
 
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
 BuildRequires: perl, readline-devel, openssl-devel
@@ -54,6 +60,7 @@ BuildRequires: systemtap-sdt-devel
 BuildRequires: time procps
 # Socket and Time::HiRes are needed to run regression tests
 BuildRequires: perl(Socket), perl(Time::HiRes)
+BuildRequires: systemd-units
 
 Requires: grep, fileutils
 Requires: %{name}-libs%{?_isa} = %{version}-%{release}
@@ -96,11 +103,16 @@ Requires: sh-utils
 Requires(pre): /usr/sbin/useradd
 Requires(post): chkconfig
 Requires(preun): chkconfig
-# This is for /sbin/service
-Requires(preun): initscripts
-Requires(postun): initscripts
-# This is for /etc/tmpfiles.d
+# We require this to be present for /etc/tmpfiles.d
 Requires: systemd-units
+# Make sure it's there when scriptlets run, too
+Requires(post): systemd-units
+Requires(preun): systemd-units
+Requires(postun): systemd-units
+# This is actually needed for the %%triggerun script but Requires(triggerun)
+# is not valid.  We can use %%post because this particular %%triggerun script
+# should fire just after this package is installed.
+Requires(post): systemd-sysv
 # mysqlhotcopy needs DBI/DBD support
 Requires: perl-DBI, perl-DBD-MySQL
 Conflicts: MySQL-server
@@ -189,6 +201,7 @@ the MySQL sources.
 %patch11 -p1
 %patch12 -p1
 %patch13 -p1
+%patch14 -p1
 
 # workaround for upstream bug #56342
 rm -f mysql-test/t/ssl_8k_key-master.opt
@@ -330,12 +343,18 @@ chmod 755 ${RPM_BUILD_ROOT}%{_bindir}/mysql_config
 mkdir -p $RPM_BUILD_ROOT/var/log
 touch $RPM_BUILD_ROOT/var/log/mysqld.log
 
-mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
 mkdir -p $RPM_BUILD_ROOT/var/run/mysqld
 install -m 0755 -d $RPM_BUILD_ROOT/var/lib/mysql
-install -m 0755 %{SOURCE2} $RPM_BUILD_ROOT/etc/rc.d/init.d/mysqld
+
+mkdir -p $RPM_BUILD_ROOT/etc
 install -m 0644 %{SOURCE3} $RPM_BUILD_ROOT/etc/my.cnf
 
+# install systemd unit files and scripts for handling server startup
+mkdir -p ${RPM_BUILD_ROOT}%{_unitdir}
+install -m 644 %{SOURCE11} ${RPM_BUILD_ROOT}%{_unitdir}/
+install -m 755 %{SOURCE12} ${RPM_BUILD_ROOT}%{_libexecdir}/
+install -m 755 %{SOURCE13} ${RPM_BUILD_ROOT}%{_libexecdir}/
+
 mkdir -p $RPM_BUILD_ROOT/etc/tmpfiles.d
 install -m 0644 %{SOURCE10} $RPM_BUILD_ROOT/etc/tmpfiles.d/mysql.conf
 
@@ -408,15 +427,28 @@ rm -rf $RPM_BUILD_ROOT
 
 %post server
 if [ $1 = 1 ]; then
-    /sbin/chkconfig --add mysqld
+    # Initial installation
+    /bin/systemctl daemon-reload >/dev/null 2>&1 || :
 fi
 /bin/chmod 0755 /var/lib/mysql
 /bin/touch /var/log/mysqld.log
 
+# Run this when upgrading from SysV initscript to native systemd unit
+%triggerun server -- mysql-server < %{first_systemd_version}
+# Save the current service runlevel info
+# User must manually run systemd-sysv-convert --apply mysqld
+# to migrate them to systemd targets
+/usr/bin/systemd-sysv-convert --save mysqld >/dev/null 2>&1 || :
+
+# Run these because the SysV package being removed won't do them
+/sbin/chkconfig --del mysqld >/dev/null 2>&1 || :
+/bin/systemctl try-restart mysqld.service >/dev/null 2>&1 || :
+
 %preun server
 if [ $1 = 0 ]; then
-    /sbin/service mysqld stop >/dev/null 2>&1
-    /sbin/chkconfig --del mysqld
+    # Package removal, not upgrade
+    /bin/systemctl --no-reload disable mysqld.service >/dev/null 2>&1 || :
+    /bin/systemctl stop mysqld.service >/dev/null 2>&1 || :
 fi
 
 %postun libs
@@ -425,8 +457,10 @@ if [ $1 = 0 ] ; then
 fi
 
 %postun server
+/bin/systemctl daemon-reload >/dev/null 2>&1 || :
 if [ $1 -ge 1 ]; then
-    /sbin/service mysqld condrestart >/dev/null 2>&1 || :
+    # Package upgrade, not uninstall
+    /bin/systemctl try-restart mysqld.service >/dev/null 2>&1 || :
 fi
 
 
@@ -572,7 +606,10 @@ fi
 %{_datadir}/mysql/my-*.cnf
 %{_datadir}/mysql/config.*.ini
 
-/etc/rc.d/init.d/mysqld
+%{_unitdir}/mysqld.service
+%{_libexecdir}/mysqld-prepare-db-dir
+%{_libexecdir}/mysqld-wait-ready
+
 /etc/tmpfiles.d/mysql.conf
 %attr(0755,mysql,mysql) %dir /var/run/mysqld
 %attr(0755,mysql,mysql) %dir /var/lib/mysql
@@ -611,6 +648,10 @@ fi
 %{_mandir}/man1/mysql_client_test.1*
 
 %changelog
+* Wed Jul 27 2011 Tom Lane <tgl at redhat.com> 5.5.14-3
+- Convert to systemd startup support (no socket activation, for now anyway)
+Related: #714426
+
 * Tue Jul 12 2011 Tom Lane <tgl at redhat.com> 5.5.14-2
 - Remove make_scrambled_password and make_scrambled_password_323 from mysql.h,
   since we're not allowing clients to call those functions anyway
diff --git a/mysqld-nowatch.patch b/mysqld-nowatch.patch
new file mode 100644
index 0000000..9ca2d12
--- /dev/null
+++ b/mysqld-nowatch.patch
@@ -0,0 +1,51 @@
+Add a --nowatch option to mysqld_safe that causes it to exit after
+spawning mysqld.  We don't need mysqld_safe to restart mysqld after
+a crash, because systemd can do that just fine.
+
+
+diff -Naur mysql-5.5.14.orig/scripts/mysqld_safe.sh mysql-5.5.14/scripts/mysqld_safe.sh
+--- mysql-5.5.14.orig/scripts/mysqld_safe.sh	2011-06-21 12:42:40.000000000 -0400
++++ mysql-5.5.14/scripts/mysqld_safe.sh	2011-07-25 13:52:40.363068060 -0400
+@@ -15,6 +15,7 @@
+ KILL_MYSQLD=1;
+ MYSQLD=
+ niceness=0
++nowatch=0
+ mysqld_ld_preload=
+ mysqld_ld_library_path=
+ 
+@@ -54,6 +55,7 @@
+   --mysqld=FILE              Use the specified file as mysqld
+   --mysqld-version=VERSION   Use "mysqld-VERSION" as mysqld
+   --nice=NICE                Set the scheduling priority of mysqld
++  --nowatch                  Exit after starting mysqld
+   --plugin-dir=DIR           Plugins are under DIR or DIR/VERSION, if
+                              VERSION is given
+   --skip-kill-mysqld         Don't try to kill stray mysqld processes
+@@ -140,8 +142,16 @@
+       ;;
+   esac
+ 
+-  #echo "Running mysqld: [$cmd]"
+-  eval "$cmd"
++  if test $nowatch -eq 1
++  then
++    # We'd prefer to exec $cmd here, but SELinux needs to be fixed first
++    #/usr/bin/logger "Running mysqld: $cmd"
++    eval "$cmd &"
++    exit 0
++  else
++    #echo "Running mysqld: [$cmd]"
++    eval "$cmd"
++  fi
+ }
+ 
+ shell_quote_string() {
+@@ -198,6 +208,7 @@
+         fi
+         ;;
+       --nice=*) niceness="$val" ;;
++      --nowatch) nowatch=1 ;;
+       --open-files-limit=*) open_files="$val" ;;
+       --open_files_limit=*) open_files="$val" ;;
+       --skip-kill-mysqld*) KILL_MYSQLD=0 ;;
diff --git a/mysqld-prepare-db-dir b/mysqld-prepare-db-dir
new file mode 100644
index 0000000..72badd7
--- /dev/null
+++ b/mysqld-prepare-db-dir
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+# This script creates the mysql data directory during first service start.
+# In subsequent starts, it does nothing much.
+
+# extract value of a MySQL option from config files
+# Usage: get_mysql_option SECTION VARNAME DEFAULT
+# result is returned in $result
+# We use my_print_defaults which prints all options from multiple files,
+# with the more specific ones later; hence take the last match.
+get_mysql_option(){
+        result=`/usr/bin/my_print_defaults "$1" | sed -n "s/^--$2=//p" | tail -n 1`
+        if [ -z "$result" ]; then
+            # not found, use default
+            result="$3"
+        fi
+}
+
+# Defaults here had better match what mysqld_safe will default to
+get_mysql_option mysqld datadir "/var/lib/mysql"
+datadir="$result"
+get_mysql_option mysqld_safe log-error "/var/log/mysqld.log"
+errlogfile="$result"
+
+
+# Set up the errlogfile with appropriate permissions
+touch "$errlogfile"
+chown mysql:mysql "$errlogfile"
+chmod 0640 "$errlogfile"
+[ -x /sbin/restorecon ] && /sbin/restorecon "$errlogfile"
+
+# Make the data directory
+if [ ! -d "$datadir/mysql" ] ; then
+    # First, make sure $datadir is there with correct permissions
+    # (note: if it's not, and we're not root, this'll fail ...)
+    if [ ! -e "$datadir" -a ! -h "$datadir" ]
+    then
+        mkdir -p "$datadir" || exit 1
+    fi
+    chown mysql:mysql "$datadir"
+    chmod 0755 "$datadir"
+    [ -x /sbin/restorecon ] && /sbin/restorecon "$datadir"
+
+    # Now create the database
+    echo "Initializing MySQL database"
+    /usr/bin/mysql_install_db --datadir="$datadir" --user=mysql
+    ret=$?
+    chown -R mysql:mysql "$datadir"
+    if [ $ret -ne 0 ] ; then
+        exit $ret
+    fi
+fi
+
+exit 0
diff --git a/mysqld-wait-ready b/mysqld-wait-ready
new file mode 100644
index 0000000..10e86fe
--- /dev/null
+++ b/mysqld-wait-ready
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+# This script waits for mysqld to be ready to accept connections
+# (which can be many seconds or even minutes after launch, if there's
+# a lot of crash-recovery work to do).
+# Running this as ExecStartPost is useful so that services declared as
+# "After mysqld" won't be started until the database is really ready.
+
+# Service file passes us the daemon's PID
+daemon_pid="$1"
+
+# extract value of a MySQL option from config files
+# Usage: get_mysql_option SECTION VARNAME DEFAULT
+# result is returned in $result
+# We use my_print_defaults which prints all options from multiple files,
+# with the more specific ones later; hence take the last match.
+get_mysql_option(){
+	result=`/usr/bin/my_print_defaults "$1" | sed -n "s/^--$2=//p" | tail -n 1`
+	if [ -z "$result" ]; then
+	    # not found, use default
+	    result="$3"
+	fi
+}
+
+# Defaults here had better match what mysqld_safe will default to
+get_mysql_option mysqld datadir "/var/lib/mysql"
+datadir="$result"
+get_mysql_option mysqld socket "$datadir/mysql.sock"
+socketfile="$result"
+
+# Wait for the server to come up or for the mysqld process to disappear
+ret=0
+while /bin/true; do
+	RESPONSE=`/usr/bin/mysqladmin --socket="$socketfile" --user=UNKNOWN_MYSQL_USER ping 2>&1`
+	mret=$?
+	if [ $mret -eq 0 ]; then
+	    break
+	fi
+	# exit codes 1, 11 (EXIT_CANNOT_CONNECT_TO_SERVICE) are expected,
+	# anything else suggests a configuration error
+	if [ $mret -ne 1 -a $mret -ne 11 ]; then
+	    ret=1
+	    break
+	fi
+	# "Access denied" also means the server is alive
+	echo "$RESPONSE" | grep -q "Access denied for user" && break
+
+	# Check process still exists
+	if ! /bin/kill -0 $daemon_pid 2>/dev/null; then
+	    ret=1
+	    break
+	fi
+	sleep 1
+done
+
+exit $ret
diff --git a/mysqld.service b/mysqld.service
new file mode 100644
index 0000000..b3bc486
--- /dev/null
+++ b/mysqld.service
@@ -0,0 +1,24 @@
+[Unit]
+Description=MySQL database server
+After=syslog.target
+After=network.target
+
+[Service]
+Type=forking
+User=mysql
+Group=mysql
+
+ExecStartPre=/usr/libexec/mysqld-prepare-db-dir
+# Note: we set --basedir to prevent probes that might trigger SELinux alarms,
+# per bug #547485
+ExecStart=/usr/bin/mysqld_safe --nowatch --basedir=/usr
+ExecStartPost=/usr/libexec/mysqld-wait-ready $MAINPID
+
+# Give a reasonable amount of time for the server to start up/shut down
+TimeoutSec=300
+
+# We rely on systemd, not mysqld_safe, to restart mysqld if it dies
+Restart=always
+
+[Install]
+WantedBy=multi-user.target


More information about the scm-commits mailing list