樹莓派插入U盤自動拷貝系統日誌到U盤或通過U盤升級程序

注意,U盤用Fat32格式,NTFS格式的話,需要在Linux另外安裝相應驅動。

可通過udev實現如題的功能。


在/etc/udev/rules.d/目錄下新建規則文件98-logcopy.rules 

內容如下:

KERNEL!="sd[a-z][0-9]", GOTO="media_by_label_auto_mount_end"

# Import FS infos
IMPORT{program}="/sbin/blkid -o udev -p %N"

# Get a label if present, otherwise specify one
ENV{ID_FS_LABEL}!="", ENV{dir_name}="%E{ID_FS_LABEL}"
ENV{ID_FS_LABEL}=="", ENV{dir_name}="usbhd-%k"

# Global mount options
ACTION=="add", ENV{mount_options}="relatime"

# Filesystem-specific mount options
ACTION=="add", ENV{ID_FS_TYPE}=="vfat|ntfs", ENV{mount_options}="$env{mount_options},utf8,gid=100,umask=002"

# Mount the device
ACTION=="add", RUN+="/bin/mkdir -p /media/%E{dir_name}", RUN+="/bin/mount -o $env{mount_options} /dev/%k /media/%E{dir_name}" RUN+="/bin/cp -r /opt/trash/logs /media/%E{dir_name}"

# Clean up after removal
ACTION=="remove", ENV{dir_name}!="", RUN+="/bin/umount -l /media/%E{dir_name}", RUN+="/bin/rmdir /media/%E{dir_name}"

# Exit
LABEL="media_by_label_auto_mount_end"

 可根據實際情況,修改掛載後的處理腳本。

保存文件並重啓,插入U盤測試,發現並未成功的拷貝日誌。

 

通過如下命令查看日誌

systemctl status udev

看到有如下錯誤提示:

pi@raspberrypi:~ $ systemctl status udev
● systemd-udevd.service - udev Kernel Device Manager
   Loaded: loaded (/lib/systemd/system/systemd-udevd.service; static; vendor preset: enabled)
   Active: active (running) since Sat 2019-08-10 16:31:27 CST; 6h ago
     Docs: man:systemd-udevd.service(8)
           man:udev(7)
 Main PID: 128 (systemd-udevd)
   Status: "Processing with 16 children at max"
   CGroup: /system.slice/systemd-udevd.service
           └─128 /lib/systemd/systemd-udevd

Aug 10 21:27:15 raspberrypi mtp-probe[8780]: checking bus 1, device 8: "/sys/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.1/1-1.1.2"
Aug 10 21:27:17 raspberrypi systemd-udevd[8785]: Process '/root/mount_manager/mount_manager add' failed with exit code 1.
Aug 10 21:27:30 raspberrypi mtp-probe[8822]: checking bus 1, device 9: "/sys/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.3"
Aug 10 21:27:49 raspberrypi systemd-udevd[8871]: Process '/root/mount_manager/mount_manager remove' failed with exit code 1.
Aug 10 22:34:07 raspberrypi systemd-udevd[10802]: Process '/bin/umount -l /media/usbhd-sda1' failed with exit code 32.
Aug 10 22:34:07 raspberrypi systemd-udevd[10802]: Process '/bin/rmdir /media/usbhd-sda1' failed with exit code 1.
Aug 10 22:34:43 raspberrypi mtp-probe[10815]: checking bus 1, device 10: "/sys/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.1/1-1.1.2"
Aug 10 22:34:45 raspberrypi systemd-udevd[10819]: Process '/bin/mkdir -p /media/usbhd-sda1' failed with exit code 1.
Aug 10 22:34:45 raspberrypi systemd-udevd[10819]: Process '/bin/mount -o relatime,utf8,gid=100,umask=002 /dev/sda1 /media/usbhd-sda1' failed with exit code 32.
Aug 10 22:34:45 raspberrypi systemd-udevd[10819]: Process '/bin/cp /opt/trash/logs /media/usbhd-sda1' failed with exit code 1.

  經過Google查詢,原來樹莓派的系統有點Bug。關於此問題的詳細信息 看這裏

解決方法:

sudo nano /lib/systemd/system/systemd-udevd.service

打開上面的文件,將後7行註釋掉,就可以了。否則udev規則雖會觸發執行,但會執行失敗。

修改後的文件內容如下:

#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=udev Kernel Device Manager
Documentation=man:systemd-udevd.service(8) man:udev(7)
DefaultDependencies=no
Wants=systemd-udevd-control.socket systemd-udevd-kernel.socket
After=systemd-udevd-control.socket systemd-udevd-kernel.socket systemd-sysusers.service
Before=sysinit.target
ConditionPathIsReadWrite=/sys

[Service]
Type=notify
OOMScoreAdjust=-1000
Sockets=systemd-udevd-control.socket systemd-udevd-kernel.socket
Restart=always
RestartSec=0
ExecStart=/lib/systemd/systemd-udevd
#KillMode=mixed
#WatchdogSec=3min
#TasksMax=infinity
#MountFlags=slave
#MemoryDenyWriteExecute=yes
#RestrictRealtime=yes
#RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6

 再次保存,重啓。

將U盤插入樹莓派,已經成功複製了日誌文件。

 

現在也還有不完善的地方,比如,設備如果有多套,往U盤拷貝日誌的路徑是一樣的,那麼永遠只能拿到最後插的那臺設備的日誌。所以應該能在Copy日誌的時候用與設備相關的名稱做爲目錄對日誌文件進行管理。

按如上設想修改後,就可以用一個U盤從現場取N個設備的日誌了。

我又想到,也可以反方向的,像安卓手機卡刷一樣,用U盤升級系統。

 ===================================================================================================

2019-08-11更新 實現上面末尾提到的兩個功能

由板載程序在/opt/trash/boxid.txt位置創建一個保存設備編號的文件。板載程序通過登錄應答消息從服務端得到設備編號,並寫入到上述文件。

再把規則文件修改一下,掛載完U盤後執行一個Shell腳本,修改後內容如下:

KERNEL!="sd[a-z][0-9]", GOTO="media_by_label_auto_mount_end"

# Import FS infos
IMPORT{program}="/sbin/blkid -o udev -p %N"

# Get a label if present, otherwise specify one
ENV{ID_FS_LABEL}!="", ENV{dir_name}="%E{ID_FS_LABEL}"
ENV{ID_FS_LABEL}=="", ENV{dir_name}="usbhd-%k"

# Global mount options
ACTION=="add", ENV{mount_options}="relatime"

# Filesystem-specific mount options
ACTION=="add", ENV{ID_FS_TYPE}=="vfat|ntfs", ENV{mount_options}="$env{mount_options},utf8,gid=100,umask=002"

# Mount the device
ACTION=="add", RUN+="/bin/mkdir -p /media/%E{dir_name}", RUN+="/bin/mount -o $env{mount_options} /dev/%k /media/%E{dir_name}" RUN+="/opt/trash/usb %E{dir_name}"

# Clean up after removal
ACTION=="remove", ENV{dir_name}!="", RUN+="/bin/umount -l /media/%E{dir_name}", RUN+="/bin/rmdir /media/%E{dir_name}"

# Exit
LABEL="media_by_label_auto_mount_end"

  在/opt/trash目錄下創建一個shell腳本,名稱爲usb

shell腳本內容如下:

#!/bin/bash

boxid=$(cat /opt/trash/boxid.txt)
curdt=$(date +%Y%m%d%H%M%S)

sudo mkdir -p /media/$1/boxlogs/${boxid}/${curdt}
sudo cp -r /opt/trash/logs/* /media/$1/boxlogs/${boxid}/${curdt}

sudo cp /media/$1/boxupdate/* /opt/trash

以上腳本先從/opt/trash/boxid.txt文件取得保存的設備編號,然後又取了當前時間,按“設備號/時間”的形式創建了目錄,然後再把日誌拷貝到這個目錄裏。

最後一句是從U盤指定目錄拷貝內容到板載程序目錄,實現了用U盤更新板載程序的功能。

這樣,功能就完美了。

 

 

 

附幾個命令:

udevadm monitor

sudo udevadm control --reload-rules

  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章