在Linux中更好地脚本化USB设备

我正在为与用户提供的USB记忆棒交互的设备编写一个python模块。 用户可以将USB记忆棒插入设备的USB插槽中,设备将数据转储到记忆棒上,无需用户干预。 如果设备在用户插入U盘时运行,我已经挂接到D-Bus上并且有一个自动安装例程。 新的问题是,如果在设备断电的情况下插入棒,该怎么办? 在设备开机后,我没有得到任何D-Bus插入事件,或任何关于记忆棒的信息的相关信息。

我已经find了通过调用/ proc来获取设备节点(/ dev / sd?)来扫描USB设备的方法:

ls /proc/scsi/usb-storage

如果您捕获该文件夹中的每个文件,则会给出scsi设备信息。

然后,我从usb-storagelogging中获取供应商,产品和序列号字段,生成一个标识符string,然后用于

ll /dev/disc/by-id/usb_[vendor] _[product] _[serial_number]-0:0

所以我可以通过结果parsing得到相对path

../../sdc

然后,我可以安装USB棒。

这是一个繁琐的过程,几乎所有的文本为基础,并准备好当有人引入一个奇怪的字符或非标准的序列号string的错误。 它适用于我拥有的全部2个USB记忆棒。 我试图从/ var / log / messages映射输出,但是最后也是文本比较。 lsusb,fdisk,udevinfo,lsmod等的输出只显示一半所需的数据。

我的问题:在没有D-Bus消息的情况下,如何确定在没有用户干预的情况下分配给USB记忆棒的/ dev设备,还是事先知道所插入设备的细节?

谢谢,对小说感到抱歉。

Solutions Collecting From Web of "在Linux中更好地脚本化USB设备"

这似乎是结合/proc/partitions/sys/class/block方法ephimient采取的。

 #!/usr/bin/python import os partitionsFile = open("/proc/partitions") lines = partitionsFile.readlines()[2:]#Skips the header lines for line in lines: words = [x.strip() for x in line.split()] minorNumber = int(words[1]) deviceName = words[3] if minorNumber % 16 == 0: path = "/sys/class/block/" + deviceName if os.path.islink(path): if os.path.realpath(path).find("/usb") > 0: print "/dev/%s" % deviceName 

我不确定这是多么便携或可靠,但它适用于我的USB棒。 当然find("/usb")可以做成更严格的正则表达式。 做mod 16也可能不是找到磁盘本身的最好方法,并且过滤出分区,但是到目前为止,它对我来说是有效的。

我不完全确定这是多么便携。 此外,这些信息大概也可以从U盘或HAL通过D-Bus获得,但这些信息都不在我的系统中,所以我不能尝试。 无论如何,这似乎是相当准确的:

 $ for / in / sys / class / block / *; 做
 > / sbin / udevadm info -a -p $ i |  grep -qx'SUBSYSTEMS ==“usb”'&&
 > echo $ {i ## * /}
 >完成
 SDE
 SDF
 SDG
 SDH
 SDI
 SDJ
 sdj1
 $ cd / sys / class / block /
 $ for i in *;  do [[$(cd $ i; pwd -P)= * / usb * / *]] && echo $ i;  DONE
 SDE
 SDF
 SDG
 SDH
 SDI
 SDJ
 sdj1

看了这个关于做ubuntu与鹦鹉螺做什么的线程 ,我发现了一些建议,并决定通过shell命令访问udisk。

大容量存储设备类是你想要的。 只要给它的设备文件。 即:/ dev / sdb,然后可以执行d.mount()和d.mount_point来获取已安装的位置。

之后,这也是一个寻找许多相同的USB设备,以控制安装,卸载和弹出所有具有相同标签的设备的大列表的类。 (如果你运行的是没有参数,它将适用于所有的SD设备。可以方便地“自动安装一切”脚本

 import re import subprocess #used as a quick way to handle shell commands def getFromShell_raw(command): p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) return p.stdout.readlines() def getFromShell(command): result = getFromShell_raw(command) for i in range(len(result)): result[i] = result[i].strip() # strip out white space return result class Mass_storage_device(object): def __init__(self, device_file): self.device_file = device_file self.mount_point = None def as_string(self): return "%s -> %s" % (self.device_file, self.mount_point) """ check if we are already mounted""" def is_mounted(self): result = getFromShell('mount | grep %s' % self.device_file) if result: dev, on, self.mount_point, null = result[0].split(' ', 3) return True return False """ If not mounted, attempt to mount """ def mount(self): if not self.is_mounted(): result = getFromShell('udisks --mount %s' % self.device_file)[0] #print result if re.match('^Mounted',result): mounted, dev, at, self.mount_point = result.split(' ') return self.mount_point def unmount(self): if self.is_mounted(): result = getFromShell('udisks --unmount %s' % self.device_file) #print result self.mount_point=None def eject(self): if self.is_mounted(): self.unmount() result = getFromShell('udisks --eject %s' % self.device_file) #print result self.mount_point=None class Mass_storage_management(object): def __init__(self, label=None): self.label = label self.devices = [] self.devices_with_label(label=label) def refresh(self): self.devices_with_label(self.label) """ Uses udisks to retrieve a raw list of all the /dev/sd* devices """ def get_sd_list(self): devices = [] for d in getFromShell('udisks --enumerate-device-files'): if re.match('^/dev/sd.$',d): devices.append(Mass_storage_device(device_file=d)) return devices """ takes a list of devices and uses udisks --show-info to find their labels, then returns a filtered list""" def devices_with_label(self, label=None): self.devices = [] for d in self.get_sd_list(): if label is None: self.devices.append(d) else: match_string = 'label:\s+%s' % (label) for info in getFromShell('udisks --show-info %s' % d.device_file): if re.match(match_string,info): self.devices.append(d) return self def as_string(self): string = "" for d in self.devices: string+=d.as_string()+'\n' return string def mount_all(self): for d in self.devices: d.mount() def unmount_all(self): for d in self.devices: d.unmount() def eject_all(self): for d in self.devices: d.eject() self.devices = [] if __name__ == '__main__': name = 'my devices' m = Mass_storage_management(name) print m.as_string() print "mounting" m.mount_all() print m.as_string() print "un mounting" m.unmount_all() print m.as_string() print "ejecting" m.eject_all() print m.as_string() 

你为什么不简单地使用udev规则? 我不得不处理类似的情况,我的解决方案是在/etc/udev/rules.d中创建一个包含以下规则的文件:

 SUBSYSTEMS=="scsi", KERNEL=="sd[bh]1", RUN+="/bin/mount -o umask=000 /dev/%k /media/usbdrive" 

这里的一个假设是,没有人在一次插入多个USB棒。 但它的优点是,我预先知道哪里安装的棒(/ media / usbdrive)。

你可以相当详细地阐述一下,使它更聪明,但我个人从来没有改变它,它仍然在几台计算机上工作。

然而,据我所知,当插入一根棍子时,你想要以某种方式被警告,也许这种策略给你一些麻烦,我不知道,没有调查…