Raspberry Pi树莓派数据存储管理优化方案.docx

上传人:b****7 文档编号:25650378 上传时间:2023-06-11 格式:DOCX 页数:36 大小:279.65KB
下载 相关 举报
Raspberry Pi树莓派数据存储管理优化方案.docx_第1页
第1页 / 共36页
Raspberry Pi树莓派数据存储管理优化方案.docx_第2页
第2页 / 共36页
Raspberry Pi树莓派数据存储管理优化方案.docx_第3页
第3页 / 共36页
Raspberry Pi树莓派数据存储管理优化方案.docx_第4页
第4页 / 共36页
Raspberry Pi树莓派数据存储管理优化方案.docx_第5页
第5页 / 共36页
点击查看更多>>
下载资源
资源描述

Raspberry Pi树莓派数据存储管理优化方案.docx

《Raspberry Pi树莓派数据存储管理优化方案.docx》由会员分享,可在线阅读,更多相关《Raspberry Pi树莓派数据存储管理优化方案.docx(36页珍藏版)》请在冰豆网上搜索。

Raspberry Pi树莓派数据存储管理优化方案.docx

RaspberryPi树莓派数据存储管理优化方案

1RaspberryPi树莓派数据存储管理优化方案

1.1整体优化方案

树莓派系统在使用过程中,难免需要存储各种数据信息,便是系统的存储空间是有限的,存储介质也包括有外接U盘或系统TF卡,因此需要有一套有效的数据存储管理方案以满足系统的长期稳定运行需求,避免因为存储空间不足或出现不可读写等现象而异致系统故障。

本方案设计了一套完整可靠的数据存储管理优化方案,可应用于有效管理树莓派系统或应用程序持续产出的数据文件,保障树莓派系统长期稳定运行,具体的优化方案描述如下。

1、首先,创建/home/storage目录,定义为数据存储空间,专门应用于管理系统及应用程序的产出数据。

2、当有外接U盘接入的情况下,启动自动挂载脚本优先将U盘自动挂载到/home/storage,此时主要以U盘作为数据存储介质。

自动挂载脚本的详细制作就参考下面章节。

3、当没有外接U盘时,自动挂载脚本将自动检测系统TF卡是否存在数据分区(自定义),如果存在则自动挂载到/home/storage,此时主要以数据分区作为数据存储介质。

关于数据分区的制作方法请参考下面章节。

4、当系统既没有外接U盘接入,也没有数据分区时,系统默认以/home/storage目录直接作为数据存储空间,数据直接保存在系统TF卡的系统主分区。

1.2U盘初始化方法

目前树莓派系统支持的U盘大小有16G、32G、64G等规格,系统对一般通用的U盘产品是自动识别的,不需要安装驱动,只要把U盘插入树莓派的USB接口,正常情况下,通过sudofdisk-l命令就可以查询到U盘的识别状态以及其属性信息,如下图所示。

如上图所示,系统识别出来了一个32GB大小的磁盘,格式为FAT32,这个就是U盘。

关于外接U盘的格式问题,建议在使用前统一格式化为Ext4的Linux格式,此格式对于Linux操作系统的兼容性是最好的。

当然保留FAT32格式也可以正常使用的,但经实践发现,如果使用FAT32格式,容易会出现U盘写保护的现象,这时U盘将无法正常进行写操作,即使重启设备也无法触决问题,需要人工修复。

本方案设计了一套U盘自动格式化脚本(formatUSB.py,脚本代码参考下面章节),可直接通过执行该脚本自动将U盘格式化为Ext4格式,如下图所示。

sudopythonformatUSB.pyauto

1.3U盘自动挂载方法

一般在实际的应用过程中,系统程序或应用程序保存数据时需要指定目录路径,比如本文案指定/home/storage为数据存储目录,因此我们需要先于相关程序启动前将数据存储目录与实际的存存介质关联起来(挂载),本章节设计的U盘自动挂载脚本就是实现此目的,根据实际的存储条件自动完成挂载功能。

自动挂载脚本为mountStorage.py,系统在启动时自动调用该脚本执行挂载。

由于系统及应用程序的产出数据目录需要指向/home/storage目录,因此自动挂载脚本应该在这些应用程序启动前执行挂载,由于存在这种先后的依赖关系,因此我们把自动挂载脚本做成了一个系统服务,并指定在这些应用程序前执行,如下图所示。

/etc/systemd/system/mountStorage.service

该服务的内容如下所示:

[Unit]

Description=RunMountservice

Before=apache2.service

#Before=rc.local.service

[Service]

Type=oneshot

RemainAfterExit=yes

ExecStart=/usr/bin/python/home/pi/app/script/mountStorage.py

[Install]

WantedBy=multi-user.target

补充说明:

Before=apache2.service配置指明mountStorage.service在apache2.service之前先启动,因为apache2的日志目录需要指向storage目录,因此需要在apache2启动前完成自动挂载。

如果是新创建的系统服务,请执行以下命令使其生效。

pi@raspberrypi:

/etc/systemd/system#chmod+xmountStorage.service

pi@raspberrypi:

/etc/systemd/system#systemctldaemon-reload

pi@raspberrypi:

/etc/systemd/system#systemctlenablemountStorage.service

1.4U盘自动管理方法

本方案设定/home/storage目录作为系统的主要数据存储空间,如果没有合理的管理方案,随着数据的不断写入,总有一天会写满磁盘空间,异致不必要的异常出现。

本方案设计了一套自动存储管理脚本clearStorage.py。

由于/home/storage目录存储的数据类型并不是固定的,所以用户应该根据/home/storage目录的具体存储数据特点对clearStorage.py进行修改。

其中一个基本的设计原则是可以增加专用的配置语文件,定义好主要的数据存储目录允许保存的最长时间,自动存储管理脚本定期检查并清除过期数据。

另外一个基本的设计原则是定期检测存储空间的使用率,当总使用率大于80%时,强制删除历史数据(删除的数据类型需要在脚本中自行定义)。

自动存储管理脚本可以设置成系统定时任务crontab,由系统定期(每天执行一次)执行即可。

1.5系统分区制作方法

1、执行命令:

sudocfdisk/dev/mmcblk0

2、移动光标到最下面的标志为FreeSpace的分区,按回车键选中,此时选中的分区高亮(白底黒字)。

3、移动光标,选定底下的New命令然后按回车键,开始创建新的分区

4、接下去会提示你输入要创建的新分区大小。

默认会将所有剩余空间用于创建新分区,这里将新分区设为1G

5、接下去将提示你选择创建主分区还是逻辑分区。

默认选择主分区,按回车键接受默认选择。

5、同样的方法将剩下的所有空闲磁盘空间划分为另一个分区,如下图所示

6、然后,移动光标到Write菜单按回车键选择从而写入分区表。

7、此时将提示你是否确定要改变分区,输入yes并按回车键。

8、移动光标到Quit菜单按回车键退出cfdisk程序。

9、执行命令:

sudofdisk-l查看分区情况:

10、执行命令:

sudoreboot重启系统

11、重启后执行命令:

sudomkfs.ext4/dev/mmcblk0p3格式化分区

sudomkfs.ext4/dev/mmcblk0p4格式化分区

1.6优化脚体制作

1.6.1U盘自动格式化脚本

#!

/usr/bin/envpython

#-*-coding:

utf-8-*-

"""

用于自动格式化挂载的U盘的脚本

"""

importos

importsys

importre

importdatetime

importre

importtime

importlogging

importlogging.handlers

MOUNT_POINT='/home/storage'#测试的挂载目录

fmtlogger=logging.getLogger('fmtlogger')

fmtlogger.setLevel(logging.INFO)

log_dir='/home/pi/log/'

log_file='formatusb.log'

ifos.path.exists(log_dir):

#print'OK'

full_log_path=log_dir+log_file

ifos.path.exists(full_log_path):

os.system('chmod-R777%s'%(full_log_path))

#setsplitteris1M,andonly1backup

fh=logging.handlers.RotatingFileHandler(full_log_path,

maxBytes=1*10**6,backupCount=1)

fh.setLevel(logging.INFO)

formatter=logging.Formatter('%(asctime)s-%(name)s-%(levelname)s-%(message)s')

fh.setFormatter(formatter)

console=logging.StreamHandler()

console.setLevel(logging.DEBUG)

fmtlogger.addHandler(fh)

#fmtlogger.addHandler(console)

classUSBInfo:

def__init__(self,dev_name):

self._dev_name=dev_name

self._format=''

self._mount_point=''

self._is_mount=False

self._has_files=False

defgetDevName(self):

returnself._dev_name

defsetDevName(self,name):

self._dev_name=name

defgetFormat(self):

returnself._format

defisLinuxFormat(self):

returnself._format=='Linux'

defsetFormat(self,fmt):

self._format=fmt

defisMount(self):

returnself._is_mount

defsetMountPoint(self,path=''):

self._is_mount=Falseifpath==''elseTrue

self._mount_point=path

defgetMountPoint(self):

returnself._mount_point

defhasFile(self):

returnself._has_files

defsetChkFileRes(self,state):

ifisinstance(state,bool):

self._has_files=state

classUSBFmt:

OP_SUCCESS=1#操作成功

MNT_SUCCESS=2#挂载U盘成功

UMNT_SUCCESS=3#卸载U盘成功

FMT_SUCCESS=4#格式化U盘成功

OP_FAIL=0#操作失败

USB_NOT_EXIST=-1#没有USB

MNT_NOPOINT=-2#该路径不能挂载

MNT_POINT_OCCUPIED=-3#该路径已被挂载,冲突

MNT_FAIL=-4#挂载U盘失败

UMNT_FAIL=-5#卸载U盘失败

FMT_FAIL=-6#格式化U盘失败

def__init__(self):

self._usbInfoMap={}#U盘信息表

self.getDeviceMap()

defumountAllUsb(self):

"""

取消挂载所有的USB分区

"""

usb_list=self._findAvailUSB()

fordevinusb_list:

part1='%s1'%dev

try:

os.system('umount%s>/dev/null2>&1'%part1)

except:

pass

defgetDeviceMap(self):

"""

读取U盘设备的分区表类型,能否挂载,是否已拷贝文件的信息

"""

self._usbInfoMap={}#clean

usb_list=self._findAvailUSB()

#printusb_list

fordeviceinusb_list:

self._getUsbInfo(device)

returnself._usbInfoMap

def_findAvailUSB(self):

"""

尝试在/dev/sda-/dev/sdz中查找可用的usb

@return返回可用usb的list

"""

usb_list=[]

start=97#'a'asciicode

foriinxrange(start,start+26):

dev='/dev/sd%s'%chr(i)

cmd='fdisk-l|grep"%s"'%dev

ret=os.popen(cmd).readlines()

iflen(ret)>0:

usb_list.append(dev)

returnusb_list

def_getUsbInfo(self,device_name):

"""

读取U盘设备的分区类型

"""

part1='%s1'%device_name

devInfo=USBInfo(device_name)#addinfo

#checkformat

fmt=self._checkFormat(part1)

devInfo.setFormat(fmt)

#checkwhetherismounted

path=self._checkMounted(part1)

devInfo.setMountPoint(path)

self._usbInfoMap[device_name]=devInfo

returnself._usbInfoMap

def_checkFormat(self,part1):

#checkformat

cmd='fdisk-l|grep"^%s"'%part1

#printcmd

ret=os.popen(cmd).readlines()

iflen(ret)>0:

#addindevicemap

if'Linux'inrepr(ret):

return'Linux'

elif'FAT32'inrepr(ret):

return'FAT32'

else:

return'Other'

else:

return''

def_checkMounted(self,part1):

cmd='df-h|grep"^%s"'%part1

res=os.popen(cmd).readlines()

#print'checkmount:

',res

iflen(res)>0:

forlineinres:

pattern=r'^%s.+\s+(/\S+)$'%part1

result=re.search(pattern,line)

ifresultisnotNone:

#print'match',part1

returnresult.group

(1)

else:

#printpart1,'notmatch'

return''

return''

deftryMount(self,device_name,mount_point='/home/pi/testMount'):

"""

检查是否能挂载该设备的分区,

如果设备是/dev/sda,则尝试挂载/dev/sda

@return:

成功则返回True,失败则返回False

"""

ret=USBFmt.OP_FAIL

ifnotos.path.exists(mount_point):

os.system('mkdir-m=777-p%s'%mount_point)

ifnotos.path.exists(mount_point):

returnUSBFmt.MNT_NOPOINT

ifdevice_namenotinself._usbInfoMap:

returnUSBFmt.USB_NOT_EXIST

ifself._usbInfoMap[device_name].isMount():

fmtlogger.info('%shasmounted.'%device_name)

ret=self._umount(device_name)

ifret!

=USBFmt.OP_SUCCESS:

returnret

ifos.path.ismount(mount_point):

returnUSBFmt.MNT_POINT_OCCUPIED

ret=self._mount(device_name,mount_point)

ifret!

=USBFmt.OP_SUCCESS:

returnret

time.sleep(3)#delayforsystemresponse

ret=self._umount(device_name)

ifret!

=USBFmt.OP_SUCCESS:

returnret

returnUSBFmt.OP_SUCCESS

def_mount(self,device_name,mount_point):

part1='%s1'%device_name

res=''

try:

res=os.popen('mount%s%s2>&1'%(part1,mount_point)).read()

except:

returnUSBFmt.MNT_FAIL

iflen(res)>0:

fmtlogger.error('mounterror:

%s'%res)

returnUSBFmt.MNT_FAIL

fmtlogger.info('mount%ssucecss!

'%part1)

returnUSBFmt.OP_SUCCESS

def_umount(self,device_name):

part1='%s1'%device_name

cmd='umount%s2>&1'%part1

try:

res=os.popen(cmd).read()

except:

returnUSBFmt.UMNT_FAIL

iflen(res)>0:

fmtlogger.error('mounterror:

%s'%res)

returnUSBFmt.UMNT_FAIL

fmtlogger.info('umount%ssucecss!

'%part1)

returnUSBFmt.OP_SUCCESS

defformatUsb(self,device_name):

"""

取消挂载设备,并格式化为ext4格式

@device_name设备名

"""

self.getDeviceMap()

ifdevice_namenotinself._usbInfoMap:

returnUSBFmt.USB_NOT_EXIST

part1='%s1'%device_name

ret=USBFmt.OP_FAIL

ifself._checkMounted(part1):

ret=self._umount(device_name)

ifret!

=USBFmt.OP_SUCCESS:

returnUSBFmt.FMT_FAIL

#doformat

ret=self._formatDevice(device_name)

ifret!

=USBFmt.OP_SUCCESS:

returnUSBFmt.FMT_FAIL

returnUSBFmt.OP_SUCCESS

def_formatDevice(self,device_name):

"""

用dos分区覆盖原先分区表,创建1个默认最大的ext4分区

"""

part_cmd='(echoo;'\

'echon;'\

'echop;'\

'echo1;'\

'echo;'\

'echo;'\

'echow'\

')|fdisk%s2>&1'%device_name

#printpart_cmd

result=''

try:

result=os.popen(part_cmd).read()

except:

errmsg='%sFormaterror!

'%device_name

fmtlogger.error(errmsg)

returnUSBFmt.FMT_FAIL

iflen(result)>0:

fmtlogger.warning('fdiskresult:

%s'%result)

time.sleep(3)

part1='%s1'%device_name

fmtlogger.info('%smkfsstep.'%part1)

fmt_cmd='mkfs.ext4%s2>&1'%part1

try:

result=os.popen(fmt_cmd).read()

except:

errmsg='%sFormaterror!

'%device_name

fmtlogger.error(errmsg)

returnUSBFmt.FMT_FAIL

iflen(result)>0:

fmtlogger.warning('fdiskresult:

%s'%result)

time.sleep(3)

returnUSBFmt.OP_SUCCESS

defformatAllUsb(self):

fmtlogger.info('formatAll')

self.getDeviceMap()

fordev,infoinsorte

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 其它模板

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1