Chrooting Recent MySQL Versions on Debian and Ubuntu

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-chroot script 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_chroot right 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.pid disappears after each start. We have to create it each time, otherwise the stop command 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)
      …
  • In /etc/mysql/debian.cnf, change the two socket lines to:
    socket = /srv/mysql/var/run/mysqld/mysqld.sock
  • In /etc/mysql/my.cnf:
    • Change the socket line in the [client] section to:
      socket = /srv/mysql/var/run/mysqld/mysqld.sock

      Don’t change the socket lines in the other sections!

    • Add
      chroot = /srv/mysql

      to the [mysqld] section.

  • Prepend /srv/mysql to the log files listed in /etc/logrotate.d/mysql-server
  • Make /usr/bin/mysql_upgrade_shell use 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/syslog for errors ;-)

18 Responses to “Chrooting Recent MySQL Versions on Debian and Ubuntu”

  1. Bummer, i just see copying the ‘−−’ from the article doesn’t work. You have to delete the copied ‘−−’ and type them manually. I’ll correct that tomorrow.

  2. ollie röschke says:

    hi hi…

    thanks for that great doc, it really helped me out. there seems to be no other usable howto for chrooting mysql on debian on the net…

    sadly I have some problems when starting the mysql daemon via the init script. the daemon itself comes up, but the ‘debian-start’ util within the ‘upgrade_system_tables_if_necessary’ function:

    /etc/mysql/debian-start[17223]: Can’t find data directory. Please restart with –datadir=path-to-writable-data-dir

    I didn’t change the datadir option in ‘/etc/mysql/my.cnf’ and the directory and files in it are writeable to the ‘mysql’ user.

    any hints on that problem?
    my current version is ’5.0.32-7etch1′

    thanks ollie

  3. Hi ollie, try retyping all the ‘--’ you inserted. It should work then.

    There still were some problems with the script text on this page (see the first comment). I hope I’ve fixed all now.
    The text on this site contained some − (−) entities, they looked like a normal ‘-’ signs but it’s quite different for scripts.

  4. funbag says:

    Hi!

    I’m having the same problem as ollie.. I have double checked the ‘–’ characters and they are correct. I think something else is causing this.

    Would really appreciate some help here!

    Cheers,
    Tom

  5. ollie fixed his problem by adding ‘--datadir=<CHROOT_DIR>/var/lib/mysql’ to
    the MYUPGRADE variable in ‘/etc/mysql/debian-start’.

    I have to check with a fresh install if this is needed now.

  6. stjohn says:

    woo-hoo great howto! keep updating it!
    have you had a chance to see if its needed in fresh installs?

  7. Not yet. But stay tuned!

  8. Teppo Kauppinen says:

    Thanks! Seems to work just fine with Debian Etch 4.0r1! No need to use the fix Ollie had to use.

  9. Thanks Teppo!

    Also, I just did a fresh install on Ubuntu Gutsy. It worked fine like described above.

  10. B-man says:

    You da man, Juergen.
    Great script + great instruction = no problems.
    Working beautifully. Thanks 10^6.

  11. Dieter says:

    Hi

    I had to add an / to your chrootdir in my.cnf
    -> “chroot = /srv/mysql/”

    Thanks for your recipe !

    Greets,
    Dieter

  12. bieniu says:

    Hi!
    Great HowTo !!
    I had a problem with php and mysql.sock i sloved it by adding:

    ln -sf $CHROOT_DIR/var/run/mysqld/mysqld.sock /var/run/mysqld
    after:
    ln -sf $CHROOT_DIR/var/run/mysqld/mysqld.pid /var/run/mysqld

    Greets,
    Bieniu

  13. Thanks for the tip on adding “–datadir” to /etc/mysql/debian-start, that solved a non-chroot issue I’ve been having for an hour now.

    I would advice to put the “datadir” configuration parameter inside /etc/mysql/debian.cnf instead, thus removing the need of fiddling with init-scripts.

    Just my €.02… Thanks for a great blog for us Debian techies ;-)

  14. airween says:

    Great tutorial – I used it many times.

    Just a small reflection: above you have use the ‘ln’ command to create a symlink to pidfle, but many programs searches the socket under /var/run/mysqld. I think the bind mount better than use ‘ln’, just simply put this line to fstab:

    /srv/mysql/var/run/mysqld /var/run/mysqld none bind 0 2

    Thank you again.

    a.

  15. [...] Årsaken til dette er at scriptet ikke er optimalisert for et chrootet miljø. Jeg fant denne guiden, den virket ikke for meg men gjorde meg i stand til å bedre skjønne prosessen (noe utdatert). For [...]

  16. Still works great on Lenny with MySQL 5!!

    Thanks for this!!

  17. Mark says:

    I have a debian squeeze 64 bit system running, and I need to create a 32 bit chroot to run 32 bit mysql and other apps. I have the chroot working (lenny), but apt-get won’t install mysql in the chroot, and there are no error messages. This recipe copies an existing mysl to the chroot, but I need to create a new 32 bit mysql. Any suggestions or hints would be greatly appreciated!

    Thanks!

    Mark

Leave a Reply

Note: Comments are moderated, so your reply will not appear instantly.