Ramdisks for the Raspberry

If you use your Raspberry Pi as a standalone (headless) device, e.g. to measure and log the room temperature, there is no need to write all log files etc. to the SD card. Instead you can mount ramdisks into the relevant directories. This reduces the number of write accesses to the memory card and does not wear out its flash memory.

Stand-alone Raspberry with DS1820
temperature sensor.
Stand-alone Raspberry with DS1820 temperature sensor.

A standalone raspberry can be powered off without shutting down Linux by calling halt or shutdown -h now. If there is a write access to the sd card during power off, it might damage the internal filesystem structure and if you are really unlucky (as has happened to me...), the filesystem is damaged in a way that the Raspberry cannot boot anymore. Keep in mind to regulary create backups of your sd card!

At least the following directories are written to by the linux system, so they should be mounted to ramdisks:

  • /var/log: System logfiles
  • /var/lock: Lock files for active processes
  • /tmp: Temporary files

You can do this by adding lines to the file /etc/fstab:

proc            /proc             proc    defaults                   0       0
/dev/mmcblk0p1  /boot             vfat    defaults                   0       2
/dev/mmcblk0p2  /                 ext4    defaults,noatime           0       1
tmpfs           /tmp              tmpfs   defaults,noatime,mode=1777 0       0
tmpfs           /var/log          tmpfs   defaults,noatime,mode=0755 0       0
tmpfs           /var/lock         tmpfs   defaults,noatime,mode=0755 0       0

The lines starting with tmpfs are the important ones that mount ramdisks to the specified directories. The tmpfs filesystem implements a ramdisk that adapts its memory usage to the space needed in the ramdisk. So you do not need to specify its size in the options of /etc/fstab and consume only as much ram as is needed by the files in the ramdisk.

If you use a webserver like apache or nginx on the Raspberry, you need to take care of the directory where the server stores its logfiles. This is /var/log/apache or /var/log/nginx. Both webservers do not create this directory if it is missing and do not start. So you need a solution to create this log directory, before the webserver process is started.

Therefore I have written an init script named prepare-dirs that creates this directory, in my case for the nginx webserver.

#!/bin/bash
#
### BEGIN INIT INFO
# Provides:          prepare-dirs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Required-Start:  
# Required-Stop:   
# Short-Description: Create /var/log/nginx directory on tmpfs at startup
# Description:       Create /var/log/nginx directory on tmpfs at startup
### END INIT INFO

DIR=/var/log/nginx

#
# main()
#
case "${1:-''}" in
  start)
    # create the /var/log/nginx needed by webserver
    if [ ! -d ${DIR} ]; then
      mkdir ${DIR}
      chmod 755 ${DIR}
    fi
    ;;
  stop)
    ;;
  restart)
   ;;
  reload|force-reload)
   ;;
  status)
   ;;
  *)
   echo "Usage: $SELF start"
   exit 1
   ;;
esac

The script should be put into /etc/init.d and enabled in the boot process by calling

update-rc.d prepare-dirs defaults 01 99

This creates links in the /etc/rcX.d directories and makes sure that the script is called with the start or stop parameter when entering or leaving the corresponding runlevels. If you want to know more about the boot procedure on Raspbian, see the Upstart Website or the Upstart Wikipedia entry.

The numbers 01 and 99 tell update-rc.d to place the execution of the script at the beginning of the boot process and and the end of the shutdown process. The nginx webserver e.g. has the boot priority 02 by default, so it is started after the prepare-dirs script has been executed.

After editing /etc/fstab and setting up the init script, you should reboot the raspberry, so the ramdisks get mounted. You can check if everything works correctly by calling mount. It should print out a list with all mounted filesystems as specified in /etc/fstab.

With this setup you can prevent most of the write accesses to the sd card. To guarantee that the root filesystem (the one containing the data on the sd card) is never modified, it should be to mounted read-only, so that it cannot be damaged in any way. I hope to have enough time in the next days to try that out.

Update (2015-03-17)

Here the improved script from Tom, so there are no problems with copy and pasting and the quotation marks modified by wordpress:

#!/bin/bash
#
### BEGIN INIT INFO
# Provides: prepare-dirs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Required-Start:
# Required-Stop:
# Short-Description: Create needed directories on /var/log/ for tmpfs at startup
# Description: Create needed directories on /var/log/ for tmpfs at startup
### END INIT INFO

# needed Dirs
DIR[0]=/var/log/apt
DIR[1]=/var/log/fsck
DIR[2]=/var/log/lighttpd
PRM[2]="www-data.www-data"
DIR[3]=/var/log/stunnel4
PRM[3]="stunnel4.stunnel4"

case "${1:-}" in
  start)
    typeset -i i=0 max=$(echo "${!DIR[*]}" | tr " " "\n" | sort -nr | head -n1)
    while (( i <= max ));do
      if [ -n "${DIR[$i]}" ];then
        mkdir -p ${DIR[$i]}
        chmod 755 ${DIR[$i]}
      fi
      i=i+1
    done
    # set rights
    typeset -i i=0 max=$(echo "${!PRM[*]}" | tr " " "\n" | sort -nr | head -n1)
    while (( i <= max ));do
      if [ -n "${PRM[$i]}" ];then
        chown -R ${PRM[$i]} ${DIR[$i]}
      fi
      i=i+1
    done
    ;;
  stop)
    ;;
  restart)
    ;;
  reload|force-reload)
    ;;
  status)
    ;;
  *)
    echo "Usage: $SELF start"
    exit 1
    ;;
esac
LinkedIn logo mail logo