From a2bd433ed9483b5faaa631098eb372eecc0e4f12 Mon Sep 17 00:00:00 2001 From: Liraz Siri Date: Thu, 29 Jul 2010 23:40:37 +0300 Subject: [PATCH] mysql upstart workaround The problem? https://wiki.ubuntu.com/LucidLynx/ReleaseNotes """Upstart jobs cannot be run in a chroot: Upstart jobs cannot be started in a chroot because upstart acts as a service supervisor, and processes within the chroot are unable to communicate with the upstart running outside of the chroot (430224). This will cause some packages that have been converted to use upstart jobs instead of init scripts to fail to upgrade within a chroot. Users are advised to configure their chroots with /sbin/initctl pointing to /bin/true, with the following commands run within the chroot: dpkg-divert --local --rename --add /sbin/initctl ln -s /bin/true /sbin/initctl""" https://bugs.launchpad.net/ubuntu/+source/upstart/+bug/430224 In other words, starting an upstart job inside a chroot actually starts it outside the chroot. Upstart uses dbus to communicate with processes, and dbus uses unix sockets in the abstract namespace, which transcends the filesystem, and thus, chroot. --- bin/tklpatch-chroot | 139 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 138 insertions(+), 1 deletion(-) diff --git a/bin/tklpatch-chroot b/bin/tklpatch-chroot index ca9c738..2b5b236 100755 --- a/bin/tklpatch-chroot +++ b/bin/tklpatch-chroot @@ -1,6 +1,136 @@ #!/bin/bash -e # Copyright (c) 2009 Alon Swartz - all rights reserved +write_dummy_initctl() { + root=$1 + + cat>$root/sbin/initctl<<'EOF' +#!/bin/bash + +set -e +set -u +${DEBIAN_SCRIPT_DEBUG:+ set -v -x} + +. /lib/lsb/init-functions +ERR_LOGGER="logger -p daemon.err -t /etc/init.d/mysql -i" +MYADMIN="/usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf" + +mysqld_get_param() { + /usr/sbin/mysqld --print-defaults \ + | tr " " "\n" \ + | grep -- "--$1" \ + | tail -n 1 \ + | cut -d= -f2 +} + +mysqld_status () { + ping_output=`$MYADMIN ping 2>&1`; ping_alive=$(( ! $? )) + + ps_alive=0 + pidfile=`mysqld_get_param pid-file` + if [ -f "$pidfile" ] && ps `cat $pidfile` >/dev/null 2>&1; then ps_alive=1; fi + + if [ "$1" = "check_alive" -a $ping_alive = 1 ] || + [ "$1" = "check_dead" -a $ping_alive = 0 -a $ps_alive = 0 ]; then + return 0 # EXIT_SUCCESS + else + if [ "$2" = "warn" ]; then + echo -e "$ps_alive processes alive and '$MYADMIN ping' resulted in\n$ping_output\n" | $ERR_LOGGER -p daemon.debug + fi + return 1 # EXIT_FAILURE + fi +} + +start_mysql() +{ + test -x /usr/sbin/mysqld || exit 0 + + log_daemon_msg "Starting MySQL database server" "mysqld" + if mysqld_status check_alive nowarn; then + log_progress_msg "already running" + log_end_msg 0 + else + /usr/bin/mysqld_safe > /dev/null 2>&1 & + # 6s was reported in #352070 to be too few when using ndbcluster + for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14; do + sleep 1 + if mysqld_status check_alive nowarn ; then break; fi + log_progress_msg "." + done + if mysqld_status check_alive warn; then + log_end_msg 0 + # Now start mysqlcheck or whatever the admin wants. + output=$(/etc/mysql/debian-start) + [ -n "$output" ] && log_action_msg "$output" + else + log_end_msg 1 + log_failure_msg "Please take a look at the syslog" + fi + fi +} + +stop_mysql() +{ + # * As a passwordless mysqladmin (e.g. via ~/.my.cnf) must be possible + # at least for cron, we can rely on it here, too. (although we have + # to specify it explicit as e.g. sudo environments points to the normal + # users home and not /root) + log_daemon_msg "Stopping MySQL database server" "mysqld" + if ! mysqld_status check_dead nowarn; then + set +e + shutdown_out=`$MYADMIN shutdown 2>&1`; r=$? + set -e + if [ "$r" -ne 0 ]; then + log_end_msg 1 + [ "$VERBOSE" != "no" ] && log_failure_msg "Error: $shutdown_out" + log_daemon_msg "Killing MySQL database server by signal" "mysqld" + killall -15 mysqld + server_down= + for i in 1 2 3 4 5 6 7 8 9 10; do + sleep 1 + if mysqld_status check_dead nowarn; then server_down=1; break; fi + done + if test -z "$server_down"; then killall -9 mysqld; fi + fi + fi +} + +start() +{ + if [ "$1" == "mysql" ]; then + start_mysql + fi + +} + +stop() +{ + if [ "$1" == "mysql" ]; then + stop_mysql + fi +} + +op=$(basename $0) +service=$1 + +case "$op" in + start) + start $1 + ;; + + stop) + stop $1 + ;; + + *) + ;; +esac + +exit +EOF + chmod +x $root/sbin/initctl +} + fatal() { echo "fatal: $@" 1>&2 exit 1 @@ -39,11 +169,18 @@ command=$@ if [ ! "$root" == "/" ]; then + if ! [ -f $root/sbin/initctl.distrib ]; then + chroot $root dpkg-divert --local --rename --add /sbin/initctl + write_dummy_initctl $root + traphook="rm $root/sbin/initctl; chroot $root dpkg-divert --local --rename --remove /sbin/initctl;" + fi + resolvconf=$root/etc/resolv.conf if ! [ -f $root/etc/debian_chroot ]; then echo tklpatch > $root/etc/debian_chroot - traphook="rm -f /etc/debian_chroot;" + traphook="${traphook}rm -f /etc/debian_chroot;" fi + if ! [ -f $resolvconf.bak ]; then mv $resolvconf $resolvconf.bak cp /etc/resolv.conf $resolvconf