2015-02-10 36 views
3

我有2台PC(Linux和Windows)连接到不同楼层的本地网络。那个楼层的人们将他们的USB Pen-Drive连接到任一台PC上,我想将不同的特定文件复制给不同的人。是否有可能使用python获取pendrive的挂载点以了解其序列号?

此前,

  • 我所做的就是这么难(得到了地板上,做手工)
  • 后,我写了一个Python程序,我决定副本组特定的文件来 特定的人通过ssh。 (即我通过ssh登录到 特定机器,请求用户(通过电话)逐个插入他们的 笔式驱动器,然后我执行接受 参数的python程序。只不过是一个我想复制的名字, 以及通过接收程序决定将哪些文件复制到笔驱动器的参数 )。
    仍然这个过程有点乏味,.. 因为只有一个笔驱动器可以连接,我不得不为每个用户重复这样做。

因此,为了减少总消耗时间,我在两个系统上连接了USB集线器,以便在给定时间内插入多个笔驱动器。问题出在这里,决定哪个设备属于谁。

问题:是否可以使用python从SerialNumber找到笔式驱动器的安装点? (这将是如果蟒巨大的,因为主程序是用Python编写)

原因我正在考虑SerialNumber过,

  • UUID - 当设备被格式化
  • Vendor它改变, ProdIDManufacturer - 不确定,如果他们将 不同。 (IE中。如果其来自同一制造商和相同 模型)

我试图wmi窗户..从SO得到这个代码,(对不起,我没有联系。把它长回)

import win32com.client 

wmi = win32com.client.GetObject ("winmgmts:") 
for usb in wmi.InstancesOf ("Win32_USBHub"): 
    print usb.DeviceID 

输出我得到的是

USB\VID_5986&PID_0292\6&4817B6D&0&6 
USB\VID_8087&PID_0024\5&55D1EEC&0&1 
USB\VID_8087&PID_0024\5&88B8ABA&0&1 
USB\ROOT_HUB20\4&11F77F7&0 
USB\ROOT_HUB20\4&62BF53D&0 
USB\VID_03F0&PID_3307\JN0W5LAB0ZHQ5VK8 

其在Linux中类似的情况下,所有我能得到的是SERIALNUMBER,使用usb-devices。但无法获得其相应的挂载点

任何想法请......

+0

请参阅[这为最近Linuxen上的D-Bus解决方案](http://stackoverflow.com/a/5081937/918959) – 2015-02-10 11:48:52

+0

对不起,udisk已现在不推荐使用[此方法代替](http://stackoverflow.com/q/23244245/918959) – 2015-02-10 11:59:40

+1

请注意,使用udev时,在连接USB设备时自动运行的Linux上运行命令非常简单可以将每个设备安装到不同的路径,甚至可以自动执行复制命令;不需要python也不需要轮询 – 2015-02-10 12:14:59

回答

3

要做到这一点就Linux的你需要解析/proc/mounts以确定设备名称映射到挂接点,即/dev/sdc2 - >/var/run/media/myaut/hyperx

诀窍是找出哪些设备名称需要序列号。这样做最简单的方法是使用udev - 它采用串行时/dev/disk/by-id产生的符号链接:

/dev/disk/by-id/usb-Generic_Flash_Disk_12345678-0:0 -> ../../sdd 

但我们并没有寻求最简单的解决方案,我们是什么?诀窍是udev规则可能会改变,并且sysfs(来自内核)更可靠。我实现了一个脚本,它是:

import os 
import sys 
import glob 

SYS_USB_DEVICES = '/sys/bus/usb/devices' 
SYS_BLOCK_DEVICES = '/sys/class/block' 

try: 
    serial = sys.argv[1] 
except IndexError: 
    print >> sys.stderr, "Usage: findflash.py SERIAL" 
    sys.exit(1) 

# PASS 1 Find USB node with corresponding to serial 

for usbid in os.listdir(SYS_USB_DEVICES): 
    usbserpath = os.path.join(SYS_USB_DEVICES, usbid, 'serial')  
    if not os.path.exists(usbserpath): 
     continue  
    with open(usbserpath) as f: 
     usb_serial = f.read().strip() 

    if serial == usb_serial: 
     # Found it! 
     break 
else: 
    print >> sys.stderr, "Cannot find usb device with serial {0}".format(serial) 
    sys.exit(1) 

# Find SCSI ids corresponding to this device 
# I didn't check SYSFS documentation, but tested it on openSUSE 13.1 
# The form of path is: 
# <SUBDEVICE>/host<SCSI_HOST_ID>/target<SCSI_TARGET_ID>/<CTRL><CHANNEL>:<TGT>:<LUN> 
# We need only basename 

devs = glob.glob(os.path.join(SYS_USB_DEVICES, usbid, 
          '*/host*/target*/*:*:*:*')) 

devs = map(os.path.basename, devs) 

# PASS 2 - find mountpoints for devices with SCSI ids we discover earlier 

# Parse mountpoint formatted as "/dev/... /path/to/mntpt ..." 
def parse_mntpt(line): 
    dev, mntpt, _ = line.split(None, 2) 
    dev = os.path.basename(dev) 
    return dev, mntpt 

mntpts = {} 
with open('/proc/mounts') as f: 
    mntpts = dict(map(parse_mntpt, f.readlines())) 

# List of ('scsi id', 'dev name', 'mnt pt (if exists)') 
devlist = [] 

def create_dev(scsiid, devname): 
    global mntpts 
    devlist.append((scsiid, devname, mntpts.get(devname))) 

for devname in os.listdir(SYS_BLOCK_DEVICES): 
    devpath = os.path.join(SYS_BLOCK_DEVICES, devname) 
    devlink = os.path.join(devpath, 'device') 

    # Node is "virtual", i.e. partition, ignore it 
    if not os.path.islink(devlink): 
     continue 

    scsiid = os.path.basename(os.readlink(devlink))  
    if scsiid not in devs: 
     continue 

    create_dev(scsiid, devname) 

    # Find partition names 
    parts = glob.glob(os.path.join(devpath, '*/partition')) 

    for partpath in parts: 
     partname = os.path.basename(os.path.dirname(partpath)) 
     create_dev(scsiid, partname) 

# END - print results 
fmtstr = '{0:8} {1:5} {2}' 
print fmtstr.format('SCSI ID', 'DEV', 'MOUNT POINT') 
for scsiid, devname, mntpt in devlist: 
    print fmtstr.format(scsiid, devname, mntpt) 

下面是输出示例:

$ python findflash.py 12345678 
SCSI ID DEV MOUNT POINT 
8:0:0:0 sdd None 
8:0:0:0 sdd1 /var/run/media/myaut/Debian\040wheezy\04020140723-17:30 
8:0:0:0 sdd2 None 
8:0:0:0 sdd5 None 
8:0:0:1 sr0 None 

的Windows我不能说,在这将是容易的。我有一个能够从系统中收集所有磁盘设备的代码(在C/WinAPI中),但它的逻辑远离文件系统表示,所以我仍然没有找到解决方案。

复杂的Windows都来自:

  • 没有设置像的SetupDi *功能,让您枚举磁盘设备。他们的名字以PnP风格出现,与卷名无关。
  • 有DOS风格的API(即在A级和C级上工作)
  • 有WinNT风格的API知道卷和挂载点。

当然,连接这三层并不明显(有办法按大小/偏移量匹配分区,但这是疯狂的)。我仍然害怕在我的库中实现它:(

+0

,..非常感谢,这很有用,而且您的意见很好地解释了这个过程,谢谢为您的详细解释,.. – arvindh 2015-02-11 05:05:33