I’ve posted a recipe for chrooting MySQL on Debian sarge a while ago. These instructions no longer work out of the box for newer MySQL packages from Debian and Ubuntu. The main problem is that the startup script added a few extra checks and script invocations that don’t understand the chroot environment. So here’s an updated plan:
- Prepare the chroot directory. It’s recommended to use an extra partition/filesystem for it. I will use
/srv/mysql(which is an LVM2 partition with an ext3 filesystem on my system) for the rest of the text. - Stop MySQL:
/etc/init.d/mysql stop
- Copy the databases to new location:
mkdir -p /srv/mysql/var/lib cp -a /var/lib/mysql /srv/mysql/var/lib
- Copy this script to
/etc/default/mysql-chroot - Edit
/etc/init.d/mysql:- Source the
mysql-chrootscript somewhere at the top:… test -x /usr/sbin/mysqld || exit 0 . /etc/default/mysql-chroot SELF=$(cd $(dirname $0); pwd -P)/$(basename $0) …
- Fix the disk space check:
… # check for diskspace shortage datadir=`mysqld_get_param datadir` if LC_ALL=C BLOCKSIZE= df --portability $CHROOT_DIR$datadir/. | tail -n 1 | awk '{ exit ($4>4096) }'; then log_failure_msg "$0: ERROR: The partition with $datadir is too full!" … - Run
setup_chrootright in the start section:… if mysqld_status check_alive nowarn; then echo "...already running." else setup_chroot /usr/bin/mysqld_safe > /dev/null 2>&1 & …
- Somehow
/var/run/mysqld/mysqld.piddisappears after each start. We have to create it each time, otherwise thestopcommand won’t work properly:… if mysqld_status check_alive warn; then log_end_msg 0 ln -sf $CHROOT_DIR/var/run/mysqld/mysqld.pid \ /var/run/mysqld # Now start mysqlcheck or whatever the admin wants. output=$(/etc/mysql/debian-start) …
- Source the
- In
/etc/mysql/debian.cnf, change the twosocketlines to:socket = /srv/mysql/var/run/mysqld/mysqld.sock
- In
/etc/mysql/my.cnf:- Change the
socketline in the[client]section to:socket = /srv/mysql/var/run/mysqld/mysqld.sock
Don’t change the
socketlines in the other sections! - Add
chroot = /srv/mysql
to the
[mysqld]section.
- Change the
- Prepend
/srv/mysqlto the log files listed in/etc/logrotate.d/mysql-server - Make
/usr/bin/mysql_upgrade_shelluse the chrooted socket. Note: Currently these changes must be made each time mysql gets upgraded because upgrades override this file!… --password=*) password=`echo "$arg" | sed -e 's/^[^=]*=//'` ;; --socket=*) socket=`echo "$arg" | sed -e 's/^[^=]*=//'` ;; --ldata=*|--data=*|--datadir=*) DATADIR=`echo "$arg" | sed -e 's/^[^=]*=//'` ;; … fi $bindir/mysql_fix_privilege_tables --silent --user=$user --password=$password --socket=$socket $args exit 0 … check_args="--check-upgrade --all-databases --auto-repair --user=$user --password=$password --socket=$socket" … $bindir/mysql_fix_privilege_tables --silent --user=$user --password=$password --socket=$socket $args …
- Start MySQL:
/etc/init.d/mysql start
- Check
/var/log/syslogfor errors ;-)
