我正在为一个与用户提供的USB记忆棒交互的设备编写python模块。用户可以在设备USB插槽中插入USB记忆棒,设备将数据转储到记忆棒上,无需用户干预。如果设备在用户插入USB记忆棒时正在运行,我已经连接到D-Bus并且已经完成了自动安装程序。新问题是,如果在设备断电时插入插杆怎么办?在设备开机后,我没有得到任何D-Bus插入事件或任何关于记忆棒的相关信息。
我已经找到了一种方法来通过调用以下方法来扫描设备节点(/ dev / sd?)来扫描/ proc中的USB设备:
ls /proc/scsi/usb-storage
如果您捕获该文件夹中的每个文件,则会提供scsi设备信息。
然后我从usb-storage记录中获取供应商,产品和序列号字段,生成一个标识符字符串,然后我在
中使用 ll /dev/disc/by-id/usb_[vendor]
_[product]
_[serial_number]-0:0
所以我可以解析结果以获得相对路径
_[product]
然后,我可以安装USB记忆棒。
这是一个繁琐的过程,基本上都是基于文本的,并且当有人引入奇怪的字符或非标准的序列号字符串时就准备好了。它适用于我拥有的所有2个USB记忆棒。我试图映射/ var / log / messages的输出,但最终也是文本比较。 lsusb,fdisk,udevinfo,lsmod等的输出仅显示所需数据的一半。
我的问题:在没有D-Bus消息的情况下,如何在没有用户干预的情况下确定分配给USB记忆棒的/ dev设备,或者事先知道所插入设备的具体情况?
谢谢,对这部小说感到抱歉。
答案 0 :(得分:4)
这似乎可以将/proc/partitions
与/sys/class/block
方法相结合。
#!/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也可能不是找到磁盘本身并过滤掉分区的最佳方法,但到目前为止它对我有用。
答案 1 :(得分:1)
我不完全确定这是多么便携。此外,这些信息可能也可以通过D-Bus从udisks或HAL获得,但我的系统上都没有这些信息,因此我无法尝试。无论如何,这里似乎相当准确:
$ for i in /sys/class/block/*; do > /sbin/udevadm info -a -p $i | grep -qx ' SUBSYSTEMS=="usb"' && > echo ${i##*/} > done 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
答案 2 :(得分:0)
在looking at this thread关于做ubuntu对nautilus的处理之后,我找到了一些建议并决定通过shell命令访问udisks。
大容量存储设备类是您想要的。只需给它设备文件。即:/ 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()
答案 3 :(得分:0)
为什么不简单地使用udev规则?我不得不处理类似的情况,我的解决方案是在/etc/udev/rules.d中创建一个包含以下规则的文件:
SUBSYSTEMS=="scsi", KERNEL=="sd[b-h]1", RUN+="/bin/mount -o umask=000 /dev/%k /media/usbdrive"
这里的一个假设是,没有人会及时插入多个usb棒。然而,它有一个优点,我事先知道将安装杆(/ media / usbdrive)。
你可以肯定地说明它有点聪明,但我个人从来没有改变它,它仍然适用于几台电脑。
然而,据我所知,你想在插入一根棍子时以某种方式收到警报,也许这个策略会给你带来一些麻烦,我不知道,没有调查......
答案 4 :(得分:0)
我认为最简单的方法是使用lsblk:
lsblk -d -o NAME,TRAN | grep usb