注意,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

  

树莓派插入U盘自动拷贝系统日志到U盘或通过U盘升级程序的更多相关文章

  1. U盘自动拷贝

    描述:启动该程序后,自动检测U盘是否存在,若存在,将U盘中所有的文件拷贝到电脑的指定目录下. 注:本篇博文仅支持技术讨论,不用于数据的盗取之类的黑科技. 本程序基于Win32开发,主要是利用Win32 ...

  2. 二十三、uevnet机制和U盘自动挂载

    一.uevent机制 在分析之前,我们首先要知道uevent作用是什么.在此我们先来看一个uevent机制的框架图: 该图片来自:Linux设备模型(3)_Uevent 通过图片我们可以确定ueven ...

  3. 树莓派USB存储设备自动挂载并通过脚本实现自动拷贝,自动播放视频,脚本自动升级等功能

    需求:首先需要树莓派自动挂载USB设备,然后扫描USB指定目录下文件,将相关文件拷贝至树莓派指定目录,然后通过omxplayer循环播放新拷贝文件视频 1. 树莓派实现USB存储设备自动挂载 树莓派U ...

  4. 【360图书馆】插入U盘自动攻击:BadUSB原理与实现

    插入U盘自动攻击:BadUSB原理与实现       漏洞背景 “BadUSB”是今年计算机安全领域的热门话题之一,该漏洞由Karsten Nohl和Jakob Lell共同发现,并在今年的Black ...

  5. U盘无法拷贝超过4G的大文件

    现在U盘的容量越来越大了,8G闪存满天飞,几乎已成“标配”,市面上再见难觅64M.128M等U盘的踪迹,可是细心的你也许已经发现,即使是8G或更大体积的U盘,仍然不能拷贝存储体积超过4G的大文件,这是 ...

  6. 如何插上U盘 自动复制内容

    U盘插入自动复制,有效对付那些不肯给PPT的老师,还有一定几率拿到期末考试卷子···有图有真相!业界良心的好东西!!现在看还来得及!!! 代码优化了一下,把不是很重要的都删掉了,这次使用时看不出任何现 ...

  7. 33.Linux-实现U盘自动挂载(详解)

    1.当我们每次插入u盘后,都会自动创键U盘的设备节点/dev/sda%d 这是因为里面调用了device_create()实现的, busybox的mdev机制就会根据主次设备号等信息,在/dev下创 ...

  8. hotplug_uevent机制_修改mdev配置支持U盘自动挂载学习笔记

    1.接入U盘,看输出打印信息并分析 (1)输出信息 自动创建设备节点 (2)用ls命令查看 这里/dev/sda表示整个U盘,/dev/sda1表示这个U盘的第一个分区. (3)手动挂载,查看文件,手 ...

  9. Android PRODUCT_COPY_FILES 自动拷贝文件

    /********************************************************************** * Android PRODUCT_COPY_FILES ...

随机推荐

  1. C# 上传大文件

    上传大文件首先要修改web.config文件,否则上传报错.在web.config添加如下配置maxRequestLength表示能上传的最大文件值,单位是KB,requestLengthDiskTh ...

  2. java-we不在esclipse创建servlet之后改名不起作用的问题归纳

    有时候我们不满意类名而去改名,但是改过了之后却发现不能实现它本来该实现的功能了,这是为什么呢,原因就是在2.5里面创建了servlet之后就会在web.xml里生成关于这个servlet的配置,你只是 ...

  3. linux中>/dev/null 2>&1和2>&1 > /dev/null

    转载:https://www.cnblogs.com/520playboy/p/6275022.html 背景 我们经常能在shell脚本中发现>/dev/null 2>&1这样的 ...

  4. ReactiveX 学习笔记(30)操作符辨析

    RxJava: merge/concat/switch RxJS: merge/concat/switch/exhaust RxSwift: merge/concat/switchLatest mer ...

  5. linux 读取文件

    linux读取文件是经常要用到的操作,以下示例(说明看注释): #读取文件snlist.txt中的每一行内容赋给sn变量 while read sn do echo ">>> ...

  6. Problem F. Wiki with String

    Problem F. Wiki with StringInput file: standard input Time limit: 1 secondOutput file: standard outp ...

  7. 洛谷 SP338 ROADS - Roads 题解

    思路 dfs(只不过要用邻接表存)邻接表是由表头结点和表结点两部分组成,其中表头结点存储图的各顶点,表结点用单向链表存储表头结点所对应顶点的相邻顶点(也就是表示了图的边).在有向图里表示表头结点指向其 ...

  8. (10)Go结构体struct

    结构体 Go语言中的基础数据类型可以表示一些事物的基本属性,但是当我们想表达一个事物的全部或部分属性时,这时候再用单一的基本数据类型明显就无法满足需求了,Go语言提供了一种自定义数据类型,可以封装多个 ...

  9. 【洛谷】P1449 后缀表达式

    P1449 后缀表达式 分析: 简单的模拟题. 熟练容器stack的话很容易解决. stack,栈,有先进后出的特性. 比如你有一个箱子,你每放进第一个数时,就往箱底放,放第二个数时就在第一个数的上面 ...

  10. Android中LayoutInflater()方法

    在实际开发中LayoutInflater这个类还是非常有用的,它的作用类似于findViewById().不同点是LayoutInflater是用来找res/layout/下的xml布局文件,并且实例 ...