2010-03-05 58 views
4

我正在爲與用戶提供的USB記憶棒交互的設備編寫python模塊。用戶可以將USB記憶棒插入設備的USB插槽,設備將數據轉儲到記憶棒上,無需用戶干預。如果設備在用戶插入USB記憶棒時運行,我已經連接到D-Bus並且有一個自動安裝程序全部解決。新的問題是,如果在設備斷電的情況下插入棒,該怎麼辦?在設備開機後,我沒有收到D-Bus插入事件或任何關於記憶棒的信息。在Linux中更好地腳本安裝USB設備

我已經摸索出一套方法來獲得從掃描在/ proc的USB設備的設備節點(的/ dev/SD?),通過調用:

ls /proc/scsi/usb-storage

這給瞭如果SCSI設備信息你會捕獲該文件夾中的每個文件。

我然後採取供應商,產品,和從USB存儲記錄序列號字段,生成的標識符字符串,我然後在

ll /dev/disc/by-id/usb_[vendor]_[product] _ [SERIAL_NUMBER] -0使用:0

所以,我可以通過分析結果得到的相對路徑

../../sdc

然後,我可以掛載USB棒。

這是一個繁瑣的過程,幾乎所有的文本爲基礎,並準備好當有人引入一個奇怪的字符或非標準序列號字符串的錯誤。它適用於我擁有的全部2個USB記憶棒。我試圖映射來自/ var/log/messages的輸出,但最終也是文本比較。來自lsusb,fdisk,udevinfo,lsmod等的輸出僅顯示所需數據的一半。

我的問題:如何在沒有用戶干預的情況下確定在沒有D-Bus消息的情況下分配給USB記憶棒的/ dev設備,還是事先知道所插入設備的細節?

謝謝,對小說抱歉。

回答

2

這似乎是工作相結合/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也可能不是找到磁盤本身並過濾分區的最佳方法,但它對我來說目前爲止還是有效的。

+0

我實際上採用了一種更簡單的方法。我在 /dev/disk/by-id/usb - * - part * 其中每個條目都鏈接到/ dev設備。快速調用os.path.realpath獲取鏈接的設備。 – Therealstubot 2010-03-10 18:21:00

1

我不完全確定這是多麼便攜。此外,這些信息大概也可通過D-Bus從udisksHAL獲得,但這些信息都不在我的系統中,因此我無法嘗試。這似乎是合理的準確位置,無論:

 
$ 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 
0

looking at this thread在做了關於ubuntu使用nautilus的操作後,我發現了一些建議,並決定通過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() 
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)。

你可以肯定地詳細說明它,使它更聰明,但我個人從來沒有改變它,它仍然可以在幾臺電腦上工作。

但是,據我瞭解,你想以某種方式提醒當棒插入,也許這種策略讓你在那邊有些麻煩,我不知道,沒有調查...