Debian: logrotate fails when MySQL is not running
Tagged:  •    •    •  

I have a MySQL instance on my PC, but by default it's turned off. However, when I leave my PC running overnight, the next morning I find this friendly email from a person called Cron:

/etc/cron.daily/logrotate:
error: error running shared postrotate script for '/var/log/mysql.log /var/log/mysql/mysql.log /var/log/mysql/mysql-slow.log '
run-parts: /etc/cron.daily/logrotate exited with return code 1
Job run-parts --report /etc/cron.daily terminated (exit status: 1) (mailing output)

The logrotate script which comes with MySQL on Debian (Squeeze) contains some post-processing. After the log files have been rotated, MySQL should be notified of this by means of a flush. When you open /etc/logrotate.d/mysql-server, you will see this piece of code:

1 test -x /usr/bin/mysqladmin || exit 0
2
3 # If this fails, check debian.conf!
4 MYADMIN="/usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf"
5 if [ -z "`$MYADMIN ping 2>/dev/null`" ]; then
6   # Really no mysqld or rather a missing debian-sys-maint user?
7   # If this occurs and is not a error please report a bug.
8   if ps cax | grep -q mysqld; then
9     exit 1
10  fi
11 else
12   $MYADMIN flush-logs
13 fi

In line 5 it checks whether there's a MySQL instance listening. When there's no response, line 8 checks whether the MySQL daemon is running. When it does, that is an error and that should be reported.

But wait a minute, I have no instance running and I still receive these emails. Apparently my assumption was wrong, ps aux | grep mysqld shows me this output:

/usr/sbin/mysqld --defaults-file=/home/bram/.local/share/akonadi//mysql.conf --datadir=/home/bram/.local/share/akonadi/db_data/ --socket=/home/bram/.local/share/akonadi/db_misc/mysql.socket

So this MySQL instance is invoked by Akonadi (KDE's storage service), which validates the condition in line 8 and results in an error.

To fix this, I modified the logrotate script by replacing line 8 with this:

8 if [ -S '/var/run/mysqld/mysqld.sock' ]; then

So instead of determining the presence of the MySQL daemon by process name, I check whether the default socket exists. At least this check is more accurate, but I wonder whether it is generally applicable.