Contents
Introduction
As you already know, the SD card is a key part of the Raspberry Pi. Your Raspberry PI SD Card will provide the initial storage for the Operating System and files. Without an operative SD card, your Raspberry Pi will not start. As these cards have a limited erase/write cycles, it is very important to choose and use them carefully, in order to expand their lifespan. Otherwise, after a reboot you can come up with a corrupt SD card unable to boot the system again. In this post we will see some methods to increase the lifespan of the SD card by minimizing the number of read/write cycles.
Choosing a good Raspberry PI SD Card
As it was already stated in this post, the selection of a good SD card is very important. First of all you should consider the card class. This parameter determines the sustained write speed for the card; a class 4 card will be able to write at 4MB/s, whereas a class 10 should be able to reach 10 MB/s.
But apart from the class, the size of your Raspberry Pi SD Card is also an aspect to consider. Although it is not included in the SD specification, a good quality SD Card will use wear levelling algorithms. These algorithms will minimize the number of times each block is written, by arranging data so that erasures and re-writes are distributed evenly across the card. By this way, if the SD card is larger than the space needed, the wear can be spread over a much larger area of free space.
Analyzing Disk I/O
It is good practice to move the highly used files, which concentrate the majority of writes and deletes, away from your Raspberry Pi SD Card. By doing that, you will avoid using it for repetitive operations, which would reduce its operative life. These files can be moved to RAM memory or to an external HDD Drive. On the one hand, RAM reads and writes will be faster. For instance Raspberry Pi’s RAM, LPDDR2, offers in theory a bandwidth of up to 8.5 gigabytes per second. However, as a counterpart, the directories mounted in RAM space will not persist after a power interruption. After analysing Raspberry’s I/O, it is up to you to decide which directories should be moved to RAM space, which can be transferred to an external disk and which should be kept in your Raspberry Pi SD Card.
Using iotop and dmesg to find who produces work on disks
To find out which files are performing more frequently read/writes in disk you can use iotop
. Probably you will have to install it first:
1 |
sudo apt-get install iotop |
After that, leave running the command during a while with the options:
o
to show only the processes that have active disk usage.a
in order to see the cumulative bandwidth used and not the immediate consumption.k
to receive the results in kilobytes.
1 |
sudo iotop -aok |
You should analyze your results to find out which programs concentrate the majority of read/writes and, when possible, move the files used to RAM space.
To see where and what are writing these processes do:
1 |
sudo sysctl vm.block_dump=1 |
and run the following command several times to see the message buffer of the kernel.
1 |
dmesg |
This will show you more information about the processes that are writing blocks. Note that you should only focus on your Raspberry Pi SD Card memory, and not on the operations affecting the RAM memory (tmpfs
). Once finished analysing, remember to deactivate the block dumping by running:
1 |
sudo sysctl vm.block_dump=0 |
Results of the analysis
As an example, those were the directories that concentrated the majority of writes in my Raspberry Pi. For each one, I decided to mount them in tmpfs
or in an external HD. Note that depending on the version of Raspbian installed, some of them are by default mounted on tmpfs
. As you will see, tmpfs
is a common name for a temporary file storage facility on many Unix-like operating systems. It is intended to appear as a mounted file system, but stored in volatile memory instead of a persistent storage device. Its maximum capacity is, by default, half of the physical RAM memory. If you have not configured any video memory your tmpfs
size should be 512 MB.
/run and /run/lock
/run
stores volatile runtime data and is always mounted as a tmpfs
on systems which support tmpfs
, so you will not probably need to change anything in your configuration. Note that in modern linux distributions /run
replaces /var/run
because in some cases this directory was not always available at early boot. For compatibility reasons, you will find that your Raspberry creates a softlink between /var/run
and /run
.
/run/lock
contains files indicating that a shared device or other system resource is in use. These files contain the identity of the process (PID) using it. This allows other processes to properly coordinate access to the shared device. As it happens with /run
, a /var/run/lock
soft linked also exists and, by default, it will be mounted on RAM space. This configuration can be changed in file /etc/default/tmpfs
by setting the RAMLOCK
parameter to no
.
/dev/shm
This is a shared memory where some processes create memory portions which can be accessed by third processes in an efficient way. As in previous cases, is mounted by default on RAM space and the configuration can be changed in /etc/default/tmpfs
setting the RAMSHM
parameter to no
.
/tmp and /var/tmp
Those file systems have the same purpose and functionality: storage with a short lifetime. Both can be mounted on RAM space, being the first one configured also by parameter RAMTMP
in file /etc/default/tmpfs
.
/var/log
In this directory the system log are stored. As already stated, placing these files in RAM memory will erase them after a reboot. You should do this only in case your system is stable and you do not need to recover these files in the future. If you are interested in keeping the logs, you can also mount this file system on an external unit, such as an USB Hard Drive. Additionally, there are also programs that will make copies to hard drive/SD card only after a certain amount of time, or before restarting the system, ensuring that the log is saved safely. To do this, have a look into ram2log
on this link. However, the easiest way to keep your log files saved is just not placing them in RAM.
/var/www/html
This file system will store the web page served by apache
. As we will see, my domotic web is generated dynamically every 5 minutes with the last information served by the home sensors. In my case, it is not a problem to lose all the html code every time the Raspberry is restarted. That is the reason why I placed this directory in RAM space.
/var/lib/weewx
The databases of my domotic system are stored under this location, which are updated every 5 minutes. The information recorded is mainly related with the weather, heating system and Raspberry Pi conditions. Of course, the information recorded on this databases should be permanent and not be lost after each restart. For this reason I decided to move the databases from this point to a location in a external HDD.
/var/lib/upsd
I use USPD
(Uninterruptible Power Supply Daemon) to shut down in a controlled way my Raspberry Pi in case there is a power shortage. To know more about this topic see this post. This daemon will update frequently in this location some status information. As there is no need to keep this information after a restart I decided to move it to RAM.
Mounting Filesystems in RAM Disk
In order to mount a filesystem in tmpfs
space you should edit /etc/fstab
file. The fstab file typically lists all available disk partitions and other types of file systems and data sources that are not necessarily disk-based, and indicates how they are to be initialized or otherwise integrated into the larger file system structure. Each filesystem should be described in a separate line. These definitions will be converted dynamically into system mounted units at boot and when the configuration of the system manager is reloaded.
For instance, in order to mount /tmp
directory on tmpfs
just add to your fstab
file the following line:
1 2 |
vi /etc/fstab tmpfs /tmp tmpfs defaults,size=10M 0 0 |
The kernel will mount /tmp
on RAM, however it will not use any RAM until files are written to /tmp. When files are written, the kernel will save them to RAM using, as a maximum, 10 Megabytes. This avoids a filesystem from using up all the RAM, which can cause the system to slow down or even crash. When files are removed from this location, the associated RAM to store them will be freed up.
Editing fstab file
There are a few interesting options when configuring filesystems in fstab
file in order to reduce the writes performed in your Raspberry Pi SD Card:
- noatime option. Linux records information about the time when files were created and last modified as well as when they were last accessed. With the
noatime
mount option, reading accesses to the file system will no longer result in an update to theatime
information associated with the file. The importance of thenoatime
setting is, that it eliminates the need of the system to make writes to the file system for files which are simply being read. This can result in measurable performance gains. - commit option. Filesystems with journaling, such as ext4 or ext3, use the commit option as the frequency with which the filesystem driver itself forces a full sync of all dirty data/journal/metadata to the physical media. Increasing the commit time to 30 minutes, for instance, will certainly reduce the number of writes (multiple writes are combined into one single larger write, updates to previous writes within the commit time frame are cancelled out), increasing on the other hand the risk of losing up to 30 minutes of data upon power failure. As commented, I use an Uninterruptible Power Supply (UPS) to avoid power interruptions. In my particular case, the benefits of incrementing the commit time are greater than its drawbacks.
- nosuid, noexec and nodev option. Those are not efficiency options, but security precautions. The
nodev
mount option specifies that the filesystem cannot contain special devices. Thenoexec
option avoids the execution of any binaries on the partition. Thenosuid
mount option specifies that the filesystem cannot contain set userid files, eliminating the risk of root escalation.
Mounting Filesystems in External devices
Another option is to mount certain Filesystems outside the SD Card. In my case, I decided to move the weeWX database in an external USB Disk. To automatically mount the unit every time the system is restarted, you have just to add a line in the /etc/fstab
file. In order to identify the drive, use the UUID or the unit label extracted fromlsblk
command instead of the unit name, which can change over time. External devices that are to be mounted when present but ignored if absent may require the nofail
option. It can be combined with the x-systemd.device-timeout
option, in seconds. Be aware that 0 means infinite timeout.
Example of fstab file
1 2 3 4 5 6 7 8 9 10 11 12 |
proc /proc proc defaults 0 0 PARTUUID=bbf24818-01 /boot vfat defaults,noatime 0 2 PARTUUID=bbf24818-02 / ext4 defaults,noatime,commit=1800 0 1 UUID=8EEAC53DEAC521F7 /media/Multimedia ntfs-3g uid=1001,gid=dani,umask=0022 0 0UUID=8EEAC53DEAC521F7 /media/Multimedia ntfs-3g uid=1001,gid=dani,umask=0022 0 0UUID=fb6bce81-1cc0-41dc-aec4-1efc89af45af /media/weewxDB ext4 defaults,nofail,x-systemd.device-timeout=5,noatime 0 0 #/run, /var/run, /run/lock, /var/run/lock will be automatically created by default - tmpfs tmpfs /tmp tmpfs defaults,noatime,nosuid,nodev,noexec,mode=0755,size=10M 0 0 tmpfs /var/tmp tmpfs defaults,noatime,nosuid,nodev,noexec,mode=0755,size=1M 0 0 tmpfs /var/log tmpfs defaults,noatime,nosuid,nodev,noexec,mode=0755 0 0 tmpfs /var/www/html tmpfs defaults,noatime,nosuid,nodev,noexec,mode=0755,size=50M 0 0 tmpfs /var/lib/upsd tmpfs defaults,noatime,nosuid,nodev,noexec,mode=0755,size=4K 0 0 |
Disabling SWAP in your Raspberry Pi
To increase the quantity of RAM available, Linux system’s use swap space. If a system needs more RAM resources, it will move inactive pages in memory to the swap space. This can help the limited memory of your Raspberry Pi to have more available RAM. However, the swap space will be located in the SD card. It will not only offer slower access time, but also increase the number of writes. It will, without any doubt, reduce the lifespan of your card.
To disable swap just run the following command:
1 |
sudo swapoff --all |
Confirm that no swap exists by checking that the Swap line of the following command is 0:
1 |
sudo free -h |
If your system uses a swap partition instead of a swap file, remove the corresponding line in /etc/fstab
file as explained in the previous sections.
Checking the results
Once you are done editing the fstab
file, reboot and check if the system loads correctly. You can check the directories that have been mounted in tmps
of the mounting by typing:
1 |
sudo mount -l | grep tmpfs |
To see the free space in RAM, do:
1 |
sudo free -h |
And finally, to analyse how occupied is each file system mounted, use:
1 |
sudo df -h |
Remember that, when a file system is mounted in tmps
without any size limit, the available space will be shared between all of them.
Maybe try
https://github.com/StuartIanNaylor/zram-config
Complete zram config utility for swap, directory & log. Usefull for IoT / maker projects for reducing SD, Nand and Emmc block wear via log operations. Uses Zram to minimise precious memory footprint and extremely infrequent write outs and near ram speed working dirs.
Thank you for the tip!
“4.3 /var and /var/tmp
Those file systems have the same purpose and functionality: storage with a short lifetime. Both can be mounted on RAM space,”
I think that should read “/tmp and /var/tmp” 🙂
Woops, that was a mistake. Thanks for pointing this out!
These instructions broke my boot process:
“You are in emergency mode. After logging in, “journalctl -xb” to view”
Sorry to hear that. What step specifically broke your boot process?
Thanks a lot for this informativ article. I tried it on my raspberry with weewx and could observe a huge difference. Actually, I’m using a memory stick with writing LED. Before these changes it was blinking like crazy, now it blinks only once in a while!
One thing is not yet working though. I’m using nginx. And it complains during startup after pi-reboot that it cannot read /var/log/nginx/error.log (Alert) and /var/log/nginx/access.log (emerg). This logic, as the two files are in the RAM space a not available anymore after reboot. Unfortunately it says that configuration file /etc/nginx/nginx.conf test failed and won’t start.
I’m a beginner in unix systems. Does anyone has an idea how to get around that, so that nginx is available to start?
Actually, it is enough to create the folder nginx inside /var/log and Nginx will start. So my idea would be to let the system create this folder during boot-time before Nginx is started. Is this possible and how?
I use a microk8s in rasbian, and I see that k8s-dqlite process writes a lot, how can I reduce it?