How to specify the log file for memcached on RHEL / CentOS

I'm running memcached 1.4.5 on RHEL5.5. I installed this using yum which has installed the standard memcached script in /etc/init.d and the configuration file in /etc/sysconfig/memcached:

PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="256"
OPTIONS=""

Everything is working fine with one exception - I can't figure out how to specify the log file location. I'd like to put the log file in /var/log but the help nor the manual specify how to do this.

Is it possible to achieve this using the base scripts?


Solution 1:

Modify the OPTIONS line in /etc/sysconfig/memcached adding ">> /var/log/memcached 2>&1" on the end. IE

OPTIONS="-vv >> /var/log/memcached 2>&1"

Solution 2:

Using 2>&1 >> logfile in the OPTIONS or init script is not wise, as the log file will not get reopened when log rotation occurs, assuming of course that you have put something in place for that to occur. The implication of this is that you'll end up with rotated log files (empty, depending on rotation settings) and your actual log data will be written to a file for which no directory entry actually exists, which means that it will get deleted when the file is closed. For the logfile to be closed when intended, and therefore safely rotated, you would have to restart memcached (goodbye cache!).

Instead, use something like the logger(1) command to log to syslog (with a particular facility such as local1, and have your syslog rules route it appropriately (hello timestamps!),

OPTIONS=" 2>&1 | logger -i -p local1.info -t memcached"

A rule to route the messages specially in syslog is optional, but if you're using rsyslog, then this would help:

local1.debug  /var/log/memcached/memcached.log

Don't forget a logrotate rule, and because you're using logger, you don't need to worry about closing any log files, because syslog will do that for you.

# cat /etc/logrotate.d/memcached
/var/log/memcached/memcached.log {
    daily
    rotate 3
    dateext
    missingok
    create 0640 root root
    compress
    delaycompress
    postrotate
        #/bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
        /bin/kill -HUP `cat /var/run/syslogd.pid`
    endscript
}

FWIW, the situtation is different for EL7 (systemd) systems

For systemd systems, it will take care of collecting the output of stderr and logging that, so if you just include -v (still very quiet) or -vv (too verbose), then you can query those logs with journalctl:

# journalctl --since '2012-01-01' _SYSTEMD_UNIT=memcached.service
-- Logs begin at Fri 2015-07-10 11:00:21 NZST, end at Mon 2015-08-03 23:36:49 NZST. --
Aug 03 23:36:49 HOSTNAME memcached[4318]: slab class  17: chunk size      3632 perslab     288
Aug 03 23:36:49 HOSTNAME memcached[4318]: slab class  18: chunk size      4544 perslab     230
...
Aug 03 23:36:49 HOSTNAME memcached[4318]: slab class  42: chunk size   1048576 perslab       1
Aug 03 23:36:49 HOSTNAME memcached[4318]: <26 server listening (auto-negotiate)
Aug 03 23:36:49 HOSTNAME memcached[4318]: <27 send buffer was 212992, now 268435456
Aug 03 23:36:49 HOSTNAME memcached[4318]: <27 server listening (udp)
Aug 03 23:36:49 HOSTNAME memcached[4318]: <27 server listening (udp)
Aug 03 23:36:49 HOSTNAME memcached[4318]: <27 server listening (udp)
Aug 03 23:36:49 HOSTNAME memcached[4318]: <27 server listening (udp)

Although you don't find these logs existing anywhere under /var/log/; the logs are held in a binary format so you can use journalctl --output json ... if you wanted. See /etc/systemd/journald.conf for more information.

From beginning to end (albeit for RHEL7 / systemd servers)

# cat /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-l 127.0.0.1 -vv"


# cat /usr/lib/systemd/system/memcached.service
[Unit]
Description=Memcached
Before=httpd.service
After=network.target

[Service]
Type=simple
EnvironmentFile=-/etc/sysconfig/memcached
ExecStart=/usr/bin/memcached -u $USER -p $PORT -m $CACHESIZE -c $MAXCONN $OPTIONS

[Install]
WantedBy=multi-user.target


# cat /etc/systemd/system/memcached.service.d/local.conf
[Service]
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=memcached
SyslogFacility=local1
SyslogLevel=debug
SyslogLevelPrefix=false


# systemctl daemon-reload
# systemctl restart memcached.service

# systemctl status memcached
memcached.service - Memcached
   Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled)
  Drop-In: /etc/systemd/system/memcached.service.d
           └─local.conf                                                      <---------- NOTE
   Active: active (running) since Tue 2015-08-04 01:07:50 NZST; 7s ago
 Main PID: 3842 (memcached)
   CGroup: /system.slice/memcached.service
           └─3842 /usr/bin/memcached -u memcached -p 11211 -m 64 -c 1024 -l 127.0.0.1 -vv
...

// Note: rsyslogd uses its imjournal module to read logs from journald;
// make sure you have this configured if you've brought your rsyslog
// config from a previous version of RHEL

# echo "local1.debug  /var/log/memcached/memcached.log" >> /etc/rsyslog.d/memcached.conf
# mkdir /var/log/memcached
# systemctl restart rsyslog.service
# systemctl status rsyslog.service

// Don't forget log rotation

# cat /etc/logrotate.d/memcached
/var/log/memcached/memcached.log {
    daily
    rotate 3
    dateext
    missingok
    create 0640 root root
    compress
    delaycompress
    postrotate
        /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
    endscript
}

Solution 3:

Memcached doesn't provide a commandline option for log file location. On Ubuntu, there's a wrapper script called start-memcached which parses an /etc/memcached.conf which contains a logfile parameter. Unfortunately, this doesn't seem to exist on CentOS/RHEL. I think you'd have to modify the init script to accomplish what you want. It does seem to be a bit of an oversight - a quick googling shows that other people have this problem too, so maybe its something they'll fix soon (or have fixed already and I'm not aware of). Or you could try the startup scripts from Ubuntu.