{"id":579,"date":"2017-09-10T18:00:37","date_gmt":"2017-09-10T16:00:37","guid":{"rendered":"https:\/\/www.anginf.de\/?p=579"},"modified":"2018-06-20T16:02:46","modified_gmt":"2018-06-20T14:02:46","slug":"raspberry-pi-sd-karte-schreibgeschuetzt-nutzen","status":"publish","type":"post","link":"https:\/\/www.anginf.de\/?p=579","title":{"rendered":"Raspberry Pi SD-Karte schreibgesch\u00fctzt nutzen"},"content":{"rendered":"<p>Raspberry Pis sind ber\u00fcchtigt daf\u00fcr, dass sie die Inhalte verwendeter SD-Karten gerne mal besch\u00e4digen. H\u00e4ufig ist der Grund dahinter, dass der Strom getrennt wurde, w\u00e4hrend der Pi versuchte, auf die SD-Karte schreibend zuzugreifen.<\/p>\n<p>Sofern man nur eine einfache Anwendung hat, welche keine lokalen Daten schreiben muss, kann man die SD-Karte auch direkt &#8222;readonly&#8220; mounten, und damit den schreibenden Zugriff komplett unterbinden.<\/p>\n<p>Es ist unerheblich, ob man auf dem Raspberry Pi ein klassisches Raspbian oder ein minimal-Image nutzt. Allerdings wird es sehr viel einfacher, wenn man auf eine grafische Benutzeroberfl\u00e4che verzichten kann.<\/p>\n<p>Ich habe bei zwei Anwendungsf\u00e4llen hierzu bereits Erfolg gehabt. Bei dem einen wurde der eingesetzte Raspberry Pi als Steuereinheit f\u00fcr ein Flipdot im <a href=\"https:\/\/www.chaostreff-dortmund.de\/\" rel=\"noopener\" target=\"_blank\">Chaostreff Dortmund<\/a> eingesetzt. Bei dem anderen sollte der Raspbery Pi ausschlie\u00dflich im Kiosk-Modus eine (lokal gehostete) Webseite anzeigen. F\u00fcr den letzeren Fall griff ich auf Chromium zur\u00fcck, welcher sich gut \u00fcber Kommandozeilenparameter anpassen lie\u00df.<\/p>\n<p><hl><\/p>\n<p>Zun\u00e4chst m\u00fcssen wir das System vorbereiten und ein wenig verkleinern. Sofern ein klassisches Raspbian verwendet wird, sollte man vorher mit <code>sudo su -<\/code> auf den root-Benutzer wechseln, um die nachfolgenden Befehle ausf\u00fchren zu k\u00f6nnen. Um m\u00f6glichst kompatibel in den Befehlen zu bleiben, f\u00fchre ich das <code>sudo<\/code> nicht immer mit aus, da bei minimal-Linuxen sudo gar nicht erst als Paket eingebunden ist und man sowieso nur als root arbeiten kann.<\/p>\n<p>Als erstes sollte sichergestellt sein, dass die gesamte SD-Karte auch verwendet wird. In <code>raspi-config<\/code> kann man dies einstellen.<\/p>\n<pre lang=\"bash\">\r\napt-get update\r\napt-get -y upgrade\r\nreboot\r\n<\/pre>\n<p>Der reboot ist notwendig, damit neuere Kernel bereits geladen sind.<\/p>\n<p>Nachfolgend werden alle grafischen Bentuzerelemente entfernt sowie der cron-Daemon, welcher sonst log-Eintr\u00e4ge verursachen w\u00fcrde.<\/p>\n<pre lang=\"bash\">\r\napt-get remove --purge wolfram-engine triggerhappy anacron logrotate dphys-swapfile xserver-common lightdm\r\ninsserv -r x11-common\r\napt-get autoremove --purge\r\n<\/pre>\n<p>Log-Messages werden noch im Speicher gehalten und k\u00f6nnen mit <code>logread<\/code> ausgelesen werden, nachdem man den &#8222;busybox&#8220;-syslogd verwendet:<\/p>\n<pre lang=\"bash\">\r\napt-get install busybox-syslogd; dpkg --purge rsyslog\r\n<\/pre>\n<p>Die Eintr\u00e4ge <code>fastboot noswap ro<\/code> f\u00fcgen wir nun der cmdline.txt an, hierdurch wird das Dateisystem als nicht-schreibbar (&#8222;ro&#8220; = &#8222;readonly&#8220;) gesetzt und der Swap (die Auslagerungsdatei) abgeschaltet. Ressourcenintensive Speicherfresser k\u00f6nnen somit nicht mehr eingesetzt werden!<\/p>\n<pre lang=\"bash\">\r\necho -n \"fastboot noswap ro\" >>\/boot\/cmdline.txt\r\n<\/pre>\n<p>Einige typische Dateien und Verzeichnisse m\u00fcssen nun direkt auf das tmpfs (das ist die Ramdisk im Speicher des Raspberry Pis) verlinkt werden.<\/p>\n<pre lang=\"bash\">\r\nrm -rf \/var\/lib\/dhcp\/ \/var\/run \/var\/spool \/var\/lock \/etc\/resolv.conf\r\nln -s \/tmp \/var\/lib\/dhcp\r\nln -s \/tmp \/var\/run\r\nln -s \/tmp \/var\/spool\r\nln -s \/tmp \/var\/lock\r\ntouch \/tmp\/dhcpcd.resolv.conf; ln -s \/tmp\/dhcpcd.resolv.conf \/etc\/resolv.conf\r\n<\/pre>\n<p>Die dhcpcd.pid muss ebenfalls auf das tmpfs zeigen, hierf\u00fcr muss (zumindest auf dem Raspberry Pi 3) eine Datei angepasst werden.<\/p>\n<pre lang=\"bash\">\r\nsed -i \/etc\/systemd\/system\/dhcpcd5 's#PIDFile=\/run\/dhcpcd.pid#PIDFile=\/var\/run\/dhcpcd.pid#'\r\n<\/pre>\n<p>Falls mit <code>random-seed<\/code> gearbeitet wird, muss dies ebenfalls ins tmpfs. Der Befehl ist ungef\u00e4hrlich, falls dies nicht der Fall ist und kann trotzdem ausgef\u00fchrt werden:<\/p>\n<pre lang=\"bash\">\r\nrm \/var\/lib\/systemd\/random-seed\r\nln -s \/tmp\/random-seed \/var\/lib\/systemd\/random-seed\r\n<\/pre>\n<p>Das random-seed wird allerdings bei jedem Neustart ben\u00f6tigt, daher m\u00fcssen wir die Datei mithilfe von systemd noch anlegen, wenn der Dienst gestartet wird.<\/p>\n<pre lang=\"bash\">\r\nsed -i \/lib\/systemd\/system\/systemd-random-seed.service 's#ExecStart=\/lib\/systemd\/systemd-random-seed load#ExecStartPre=\/bin\/echo \"\" >\/tmp\/random-seed\\nExecStart=\/lib\/systemd\/systemd-random-seed load#'\r\nsystemctl daemon-reload\r\n<\/pre>\n<p>Abschlie\u00dfend m\u00fcssen wir noch ein paar startup-Skripte loswerden:<\/p>\n<pre lang=\"bash\">\r\ninsserv -r bootlogs; insserv -r console-setup\r\n<\/pre>\n<p>Da die SD-Karte \u00fcblicherweise mit &#8222;\/dev\/mmcblk0p1&#8220; eingebunden wird, k\u00f6nnen wir mit einem kleinem Skript noch die \/etc\/fstab ver\u00e4ndern, so dass &#8222;\/boot&#8220; und &#8222;\/&#8220; beim n\u00e4chsten starten nur noch als Nur-Lesbar gemountet werden.<\/p>\n<pre lang=\"bash\">\r\nsed -i \/etc\/fstab 's#\\(.*mmcblk.*defaults\\)\\(.*\\)#\\1,ro\\2#'\r\ncat <<EOT >>\/etc\/fstab\r\n\r\ntmpfs           \/tmp            tmpfs   nosuid,nodev         0       0\r\ntmpfs           \/var\/log        tmpfs   nosuid,nodev         0       0\r\ntmpfs           \/var\/tmp        tmpfs   nosuid,nodev         0       0\r\nEOT\r\n<\/pre>\n<p>Um beim Einloggen auf den Raspberry Pi trotzdem \u00c4nderungen durchf\u00fchren zu k\u00f6nnen, reichen zwei Kommandos <code>ro<\/code> und <code>rw<\/code>, welche man mit in die bash.bashrc hinzuf\u00fcgt. Falls man auf einem nicht-Multiuser-System unterwegs ist, muss man die &#8222;sudo&#8220; nat\u00fcrlich noch vorher entfernen:<\/p>\n<pre lang=\"bash\">\r\ncat <<EOT >>\/etc\/bash.bashrc\r\n# set variable identifying the filesystem you work in (used in the prompt below)\r\nset_bash_prompt(){\r\n    fs_mode=$(mount | sed -n -e \"s\/^\\\/dev\\\/.* on \\\/ .*(\\(r[w|o]\\).*\/\\1\/p\")\r\n    PS1='\\[\\033[01;32m\\]\\u@\\h${fs_mode:+($fs_mode)}\\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]\\$ '\r\n}\r\n \r\nalias ro='sudo mount -o remount,ro \/ ; sudo mount -o remount,ro \/boot'\r\nalias rw='sudo mount -o remount,rw \/ ; sudo mount -o remount,rw \/boot'\r\n \r\n# setup fancy prompt\"\r\nPROMPT_COMMAND=set_bash_prompt\r\nEOT\r\n<\/pre>\n<p>Und beim Ausloggen noch automatisiert zur\u00fcck auf read-only wechseln. Dies speichert auch die history f\u00fcr den aktuellen Benutzer ab.<\/p>\n<pre lang=\"bash\">\r\ncat <<EOT >>\/etc\/bash.bash_logout\r\nmount -o remount,rw \/\r\nhistory -a\r\nmount -o remount,ro \/\r\nmount -o remount,ro \/boot\r\nEOT\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Raspberry Pis sind ber\u00fcchtigt daf\u00fcr, dass sie die Inhalte verwendeter SD-Karten gerne mal besch\u00e4digen. H\u00e4ufig ist der Grund dahinter, dass der Strom getrennt wurde, w\u00e4hrend der Pi versuchte, auf die SD-Karte schreibend zuzugreifen. Sofern man nur eine einfache Anwendung hat, welche keine lokalen Daten schreiben muss, kann man die SD-Karte auch direkt &#8222;readonly&#8220; mounten, und &hellip; <a href=\"https:\/\/www.anginf.de\/?p=579\" class=\"more-link\"><span class=\"screen-reader-text\">Raspberry Pi SD-Karte schreibgesch\u00fctzt nutzen<\/span> weiterlesen <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-579","post","type-post","status-publish","format-standard","hentry","category-allgemein"],"_links":{"self":[{"href":"https:\/\/www.anginf.de\/index.php?rest_route=\/wp\/v2\/posts\/579","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.anginf.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.anginf.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.anginf.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.anginf.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=579"}],"version-history":[{"count":6,"href":"https:\/\/www.anginf.de\/index.php?rest_route=\/wp\/v2\/posts\/579\/revisions"}],"predecessor-version":[{"id":626,"href":"https:\/\/www.anginf.de\/index.php?rest_route=\/wp\/v2\/posts\/579\/revisions\/626"}],"wp:attachment":[{"href":"https:\/\/www.anginf.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=579"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.anginf.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=579"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.anginf.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=579"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}