1. 程式人生 > >使用overlayfs打造一個只讀的不怕意外關機的樹莓派Raspberry Pi

使用overlayfs打造一個只讀的不怕意外關機的樹莓派Raspberry Pi

樹莓派的本領就不多說了。但是在樹莓派的應用場合,關機的時候還是顯得尷尬,先不說執行 sudo halt 要麼需要ssh上去,要麼需要有鍵盤和顯示器,更不要說,有的場景可能連網路和顯示器都沒有,真正的 headless。 但是如果不執行sudo halt直接關電源,那麼有很大的概率會損壞SD卡上的檔案系統,甚至損壞SD卡。

overlayfs是linux系統下的一種影子檔案系統,它可以把真正的儲存檔案系統作為只讀掛載,而把所有檔案改動都存放在RAM中,關機或者重啟就失效,真正的保護了儲存檔案系統。  下面就說一下我在樹莓派中實施overlayfs的方法,其實很簡單。

我參考了這個帖子中介紹的方法:

https://www.raspberrypi.org/forums/viewtopic.php?t=173063#p1151405

1. 首先,禁用交換空間,畢竟樹莓派裡的交換空間也是佔用RAM(tempfs)的,所以如果使用了overlayfs後,交換空間就顯得沒有意義了。

執行如下3條命令:

  sudo dphys-swapfile swapoff
  sudo dphys-swapfile uninstall
  sudo update-rc.d dphys-swapfile remove


2. 更新系統,保證系統為最新狀態

sudo apt-get update
sudo apt-get upgrade

3. 儲存如下指令碼為 overlayRoot.sh

#!/bin/sh
#  Read-only Root-FS for Raspian using overlayfs
#  Version 1.0
#
#  Created 2017 by Pascal Suter @ DALCO AG, Switzerland
#  to work on Raspian as custom init script
#  (raspbian does not use an initramfs on boot)
#
#  Modified 2017-Apr-21 by Tony McBeardsley 
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see
#    <http://www.gnu.org/licenses/>.
#
#
#  Tested with Raspbian mini, 2017-01-11
#
#  This script will mount the root filesystem read-only and overlay it with a temporary tempfs 
#  which is read-write mounted. This is done using the overlayFS which is part of the linux kernel 
#  since version 3.18. 
#  when this script is in use, all changes made to anywhere in the root filesystem mount will be lost 
#  upon reboot of the system. The SD card will only be accessed as read-only drive, which significantly
#  helps to prolong its life and prevent filesystem coruption in environments where the system is usually
#  not shut down properly 
#
#  Install: 
#  copy this script to /sbin/overlayRoot.sh and add "init=/sbin/overlayRoot.sh" to the cmdline.txt 
#  file in the raspbian image's boot partition. 
#  I strongly recommend to disable swapping before using this. it will work with swap but that just does 
#  not make sens as the swap file will be stored in the tempfs which again resides in the ram.
#  run these commands on the booted raspberry pi BEFORE you set the init=/sbin/overlayRoot.sh boot option:
#  sudo dphys-swapfile swapoff
#  sudo dphys-swapfile uninstall
#  sudo update-rc.d dphys-swapfile remove
#
#  To install software, run upgrades and do other changes to the raspberry setup, simply remove the init= 
#  entry from the cmdline.txt file and reboot, make the changes, add the init= entry and reboot once more. 

fail(){
	echo -e "$1"
	/bin/bash
}


# Load overlay module
modprobe overlay
if [ $? -ne 0 ]; then
    fail "ERROR: missing overlay kernel module"
fi


# Mount /proc
mount -t proc proc /proc
if [ $? -ne 0 ]; then
    fail "ERROR: could not mount proc"
fi


# Create a writable fs on /mnt to then create our mountpoints 
mount -t tmpfs inittemp /mnt
if [ $? -ne 0 ]; then
    fail "ERROR: could not create a temporary filesystem to mount the base filesystems for overlayfs"
fi


# Mount a tmpfs under /mnt/rw
mkdir /mnt/rw
mount -t tmpfs root-rw /mnt/rw
if [ $? -ne 0 ]; then
    fail "ERROR: could not create tempfs for upper filesystem"
fi



# Identify root fs device, PARTUUID, mount options and fs type

#rootDev=`blkid -o list | awk '$3 == "/" {print $1}'`
# Changed here(point to / ) in case the cmd above doesn't work # By ChenYang 20171122
rootDev=/dev/mmcblk0p2
rootPARTUUID=`awk '$2 == "/" {print $1}' /etc/fstab`
rootMountOpt=`awk '$2 == "/" {print $4}' /etc/fstab`
rootFsType=`awk '$2 == "/" {print $3}' /etc/fstab`


# Mount original root filesystem readonly under /mnt/lower
mkdir /mnt/lower
mount -t ${rootFsType} -o ${rootMountOpt},ro ${rootDev} /mnt/lower
if [ $? -ne 0 ]; then
    fail "ERROR: could not ro-mount original root partition"
fi


# Mount the overlay filesystem
mkdir /mnt/rw/upper
mkdir /mnt/rw/work
mkdir /mnt/newroot
mount -t overlay -o lowerdir=/mnt/lower,upperdir=/mnt/rw/upper,workdir=/mnt/rw/work overlayfs-root /mnt/newroot
if [ $? -ne 0 ]; then
    fail "ERROR: could not mount overlayFS"
fi


# Create mountpoints inside the new root filesystem-overlay
mkdir /mnt/newroot/ro
mkdir /mnt/newroot/rw

# Remove root mount from fstab (this is already a non-permanent modification)
grep -v "$rootPARTUUID" /mnt/lower/etc/fstab > /mnt/newroot/etc/fstab
echo "#the original root mount has been removed by overlayRoot.sh" >> /mnt/newroot/etc/fstab
echo "#this is only a temporary modification, the original fstab" >> /mnt/newroot/etc/fstab
echo "#stored on the disk can be found in /ro/etc/fstab" >> /mnt/newroot/etc/fstab


# Change to the new overlay root
cd /mnt/newroot
pivot_root . mnt
exec chroot . sh -c "$(cat <<END

	# Move ro and rw mounts to the new root
	mount --move /mnt/mnt/lower/ /ro
	if [ $? -ne 0 ]; then
	    echo "ERROR: could not move ro-root into newroot"
	    /bin/bash
	fi
	mount --move /mnt/mnt/rw /rw
	if [ $? -ne 0 ]; then
	    echo "ERROR: could not move tempfs rw mount into newroot"
	    /bin/bash
	fi

	# Unmount unneeded mounts so we can unmout the old readonly root
	umount /mnt/mnt
	umount /mnt/proc
	umount /mnt/dev
	umount /mnt

	# Continue with regular init
	exec /sbin/init
END
)"

注意,我的指令碼和帖子裡面的有些不同,我把

rootDev=`blkid -o list | awk '$3 == "/" {print $1}'`


改成了

rootDev=/dev/mmcblk0p2


不改的話,我這裡overlayRoot.sh會執行失敗

20180503更新)另外需要注意,如果在Windows下編輯overlayRoot.sh檔案,需要儲存為Unix文字文件格式,即行結束符為單個LF字元,而不是Windows風格的CR+LR兩個字元。否則你可能會看到如下錯誤:

---[ end Kernel panic - not syncing: Requested init /sbin/overlayRoot.sh failed (error -2).


4. 將指令碼拷貝到 /sbin/overlayRoot.sh

sudo cp overlayRoot.sh /sbin/overlayRoot.sh
sudo chmod a+x /sbin/overlayRoot.sh


5. 修改 cmdline.txt 檔案,在行尾加上 "init=/sbin/overlayRoot.sh",如下是我的 /boot/cmdline.txt 檔案的內容

[email protected]:~ $ cat /boot/cmdline.txt 
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=PARTUUID=0e82c2e4-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait init=/sbin/overlayRoot.sh


6. 為了保證整個SD卡都是隻讀,將 /boot 分割槽也修改為只讀, 修改 fstab 檔案,把/boot 對應的行改為ro,我的/etc/fstab檔案內容如下

[email protected]:~ $ cat /etc/fstab 
proc            /proc           proc    defaults          0       0
PARTUUID=0e82c2e4-01  /boot           vfat    defaults,ro          0       2
PARTUUID=0e82c2e4-02  /               ext4    defaults,noatime  0       1


7. 到這裡 sudo reboot 重啟,重啟後,檔案系統就處於影子系統的保護之下了,所有對於檔案系統的改動,在重啟後都將恢復原狀。 用mount命令可以確認overlayfs的正常工作。

root-rw on /rw type tmpfs (rw,relatime)
/dev/mmcblk0p2 on /ro type ext4 (ro,noatime,data=ordered)
overlayfs-root on / type overlay (rw,relatime,lowerdir=/mnt/lower,upperdir=/mnt/rw/upper,workdir=/mnt/rw/work)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
proc on /proc type proc (rw,relatime)
devtmpfs on /dev type devtmpfs (rw,nosuid,size=470160k,nr_inodes=117540,mode=755)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755)
tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/net_cls type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls)
systemd-1 on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=25,pgrp=1,timeout=0,minproto=5,maxproto=5,direct)
debugfs on /sys/kernel/debug type debugfs (rw,relatime)
sunrpc on /run/rpc_pipefs type rpc_pipefs (rw,relatime)
mqueue on /dev/mqueue type mqueue (rw,relatime)
configfs on /sys/kernel/config type configfs (rw,relatime)
/dev/mmcblk0p1 on /boot type vfat (ro,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro)
tmpfs on /run/user/1000 type tmpfs (rw,nosuid,nodev,relatime,size=94952k,mode=700,uid=1000,gid=1000)

原來的根檔案系統 /dev/mmcblk0p2 改為掛載在 /ro ,並且是隻讀;/boot 也掛載為只讀;而 / 的 type 變成了overlay。

好了,直接拔電試試看吧。事實上你可以反覆嘗試不正常關機,都不會有問題。

8. 以後如果想禁用overlayfs,可以修改 cmdline.txt 把 "init=/sbin/overlayRoot.sh" 刪掉,重啟即可。 當然修改前要先把 /boot remount 成可寫狀態。

更新系統等操作都需要先禁用overlayfs後再執行。

9. 如果臨時想修改原 /boot 以及根檔案系統的內容可以如下命令remount

要remount /boot為可寫

[email protected]:~ $ sudo mount -o remount,rw /boot


原來的根檔案系統在overlayfs下是掛載在 /ro 的,要remount的話

[email protected]:~ $ sudo mount -o remount,rw /ro

注意,remount檔案系統為可寫後,要重啟和關機需要使用sudo reboot或者sudo halt,不可以強行非正常關機,以免損壞檔案系統。

PS. 網上有人報告,如果在不接顯示器的情況下(即 headless),如上指令碼會執行失敗,但是我不接顯示器時並沒有遇到此問題 。

PS2. 網上有另外一個指令碼,連結如下

https://gist.githubusercontent.com/niun/34c945d70753fc9e2cc7/raw/3d60338cd8d8daf740692f426a5a1ec17839d613/root-ro

使用了  update-initramfs 的方式,我在官方系統中可以使用,但是在修改了核心的系統中,執行失敗。

20180717後記

--- 如果開啟了overlay以後,root分割槽的所有變動重啟後都會丟失,如果要儲存資料,可以縮小root分割槽後另外建立一個分割槽,使用FAT32,並mount為rw, sync, flush,用來儲存資料,另外最好使用f2fs分割槽格式,據說f2fs就是針對SD卡之類的儲存優化設計的。當然儲存資料的頻率不要太高,否則異常關機仍有可能會損壞SD卡,就失去使用overlay的意義了。 如果儲存資料的頻率很高,比如log,可以考慮儲存到外接U盤。

--- 也有人把 /boot 掛載為rw並臨時存放資料,我認為那是不可取的,因為 /boot 裡面存放的是啟動設定資訊以及核心等。

--- 網上也有人修改指令碼,(https://github.com/jacobalberty/root-ro),使得可以短路某GPIO後啟動系統就可寫,斷開後啟動就只讀。這是個好主意,有空研究一下。  

【20180720更新】 為了方便識別當前系統是不是在overlayfs模式下,我在 .bashrc 的結尾加上如下幾行(當然必須在非overlayfs下修改,否則修改內容不會儲存),這樣如果是在overlayfs模式下,命令提示行的前面會加上“[OVL]”

find_overlay=`mount | grep overlay`

if [ ${#find_overlay} -gt 0 ]; then
  PS1="[OVL] $PS1"
fi

歡迎交流

相關推薦

使用overlayfs打造一個只讀不怕意外關機樹莓Raspberry Pi

樹莓派的本領就不多說了。但是在樹莓派的應用場合,關機的時候還是顯得尷尬,先不說執行 sudo halt 要麼需要ssh上去,要麼需要有鍵盤和顯示器,更不要說,有的場景可能連網路和顯示器都沒有,真正的 headless。 但是如果不執行sudo halt直接關電源,那麼有很大的

樹莓Raspberry Pi和Micro:bit做一個自拍器

clear microsoft 編程 告訴 pac 文本編程 裝配 -a 按鈕 在這個項目中,我們將使用Python來構建一個由Micro:bit觸發樹莓派Raspberry Pi和相機模塊的自拍器。這是開始使用硬件和簡單文本編程的好方法。 我們將學習: 如何設置Raspb

樹莓raspberry pi配置

hang 開啟 鍵盤布局設置 jin -i icon ccf ron load (1)國際化語言 樹莓派初裝系統之後,首次啟動會出現“raspi-config”工具,如下圖:(若不是初次啟動,在命令模式下,請輸入 sudo raspi-

樹莓 Raspberry Pi 啟用 root 登陸賬戶

樹莓派使用指南樹莓派 Raspberry Pi 啟用 root 登陸賬戶樹莓派系統使用的linux是debian系統,所以樹莓派啟用root和debian是相同的。debian裏root賬戶默認沒有密碼,但賬戶鎖定。當需要root權限時,由默認賬戶經由sudo執行,Raspberry pi 系統中的Raspb

樹莓 Raspberry PI基礎

數字 -c san 波特率 fin block dddddd exp org 樹莓派 Raspberry PI基礎 官網網址:https://www.raspberrypi.org 下載地址:https://www.raspberrypi.org/downloads/ 官方

樹莓 Raspberry PI之GPIO

document ble lock back ocs 輸入輸出 indent 1.5 res 樹莓派 Raspberry PI之GPIO 樹莓派各版本硬件原理圖:https://www.raspberrypi.org/documentation/hardware/raspb

樹莓Raspberry Pi實戰之命令列下實現USB儲存裝置自動掛載

簡單介紹實現命令列下USB儲存裝置自動掛載的方法,Linux gnome/kde視窗環境下有移動儲存的管理程式,可以實現自動掛載移動儲存裝置,但是在命令列下 通常需要用mount命令手動掛載USB儲存裝置。   通過給linux下的裝置管理服務udev新增規則配置檔案,可以實現命令列下U

樹莓(Raspberry Pi 3) - 系統燒錄及系統使用

         樹莓派(Raspberry pi)是一塊整合度極高的ARM開發板,不僅包含了HDMI,RCA,CSI,HDMI,GPIO等埠,還支援藍芽以及無線通訊。由於Raspberry Pi幾乎是為Linux而生的一款卡片式微型電腦,所以R

樹莓(Raspberry Pi 3)的系統燒錄及使用

今天我們將詳細一步一步地講解樹莓派3的燒錄和使用。樹莓派3是整合度很高的較為先進的ARM開發板,功能豐富,我們先來看一下它的結構以及40個GPIO口分別的用處,以免接線的時候搞錯。 APP開發、一元建站、貨運APP、冷練車APP、直播系統、小程式開發,找上海捌

樹莓 raspberry pi 能象Arduino一樣外接感測器,控制器嗎

                答案是YES樹莓派板子上有26只管腳,這些GPIO (general purpose I/O) 包括 SPI, I2C, 串列埠 UART, 3V3 and 5V 電源。國內論壇就有文章“Raspbmc 設定紅外線接收器”介紹如何為樹莓派安裝Raspbmc 作業系統,安裝配置紅

樹莓Raspberry Pi的嵌入式QT平臺

在樹莓派上設計桌面應用一般情況會依賴於X11環境,如果是Windows平臺,就目前而言,我們也可以選擇Windows 10 IoT環境進行開發。UWP目前也支援在樹莓派2上進行部署。至於常見的Linux X11或者Wayland環境,相比之下比較冗餘,但是QT Emebe

Arduino 與樹莓 Raspberry Pi 相比各自有什麼優缺點

Arduino 與樹莓派 Raspberry Pi 的差異談不上優缺點,而是他們是兩個完全不同的產品: 1. 產品定位上:Arduino的定位是微控制器,側重IO效能;Raspberry Pi的定位是電腦側重計算效能 2. 運算效能:Arduino以UNO為例是AV

適用於樹莓Raspberry Pi的嵌入式QT平臺(一) -- 交叉編譯安裝Qt Embedded 5.5

在樹莓派上設計桌面應用一般情況會依賴於X11環境,如果是Windows平臺,就目前而言,我們也可以選擇Windows 10 IoT環境進行開發。UWP目前也支援在樹莓派2上進行部署。至於常見的Linux X11或者Wayland環境,相比之下比較冗餘,但是QT Emebedded直接利用Framebuffer

適用於樹莓Raspberry Pi的嵌入式QT平臺(二) -- 在Windows下用Qt Creator開發編譯Raspberry Qt 5應用程式

接著上篇 "",我們已經成功在Windows上交叉編譯了Raspberry Pi的嵌入式Qt 5.5。那麼我們就可以開始開發基於Qt 5的應用程式。接下來,我們需要在Windows上搭建必要的Qt開發工具,首當其衝就是官方的Qt Creator,不僅提供了原生的C++編輯器,Qt介面設計器,而且還可以整合現有

適用於樹莓Raspberry Pi的嵌入式QT平臺(三) -- 交叉編譯 Raspberry Pi 版GDB with Python

上篇講到“在Windows下用Qt Creator開發編譯Raspberry Qt 5應用程式”,由於目前Qt Creator所支援的GDB需要有Python支援,但是目前MinGW中的GDB都是無Python支援的,所以我們需要自己下載GDB程式碼並且編譯成針對Raspberry Pi支援Python的版本

樹莓(Raspberry Pi)上Qt5的本地構建

        網上有很多關於在Raspberry Pi上構建Qt5的教程,但所有或大部分教程都是使用桌面機器交叉編譯Raspberry Pi的二進位制檔案。如果您交叉編譯,您將無法執行qmake並在Raspberry Pi本身上建立。本教程旨在向您展示如何在Raspberr

樹莓(raspberry pi) 系統在SD卡上安裝Linux

剛剛拿到一隻Simon同學出借的樹莓派(raspberry pi) ,準備一張4GB的SD卡,準備跑一下Linux。在Windows 7上用 工具寫入img到SD卡上,報錯,失敗。好在俺有Linux vmware虛擬機器,在虛擬機器上搞,執行命令 sudo dd bs=1M

樹莓(raspberry pi)學習6: 中文支援(中文顯示和中文輸入法)

樹莓派(raspberry pi)的原版是沒有中文支援的,需安裝 startx 後,用 Midori 瀏覽器 可以瀏覽網頁 瀏覽www.baidu.com,一堆亂碼 安裝中文顯示支援 第一步,先為終端進行相關更新:sudo apt-get update 第二步:為

樹莓(Raspberry Pi 3)

      VNC 是一款優秀的遠端控制軟體,在樹莓派、手機、電腦或者平板上安裝VNC,就可以通過這些裝置來遠端控制樹莓派了。 安裝VNC服務 安裝VNC需要使用命令列來完成,如果需要遠端操作安裝VNC,就必須通過SSH登入到命令列介面。在安裝軟體包之前,可以通過執行

在Ubuntu 16.04上為樹莓(RaspBerry Pi 3)編譯Android 7(Nougat)

1. 環境準備和介紹         本文章的測試環境如下: 軟體環境:VMware Workstation Pro + Ubuntu 16.04  64 bit,虛擬機器的記憶體配置6GB,4個CPU 硬體環境:RaspBerry Pi3 + 16GB SD卡 測試