Script Bash para o caminho de saída para o stick de memória flash USB

3

Como eu retornaria (saída) o caminho para qualquer pendrive (s) USB conectado ao computador local usando o bash (Ubuntu e Linux Mint)?

Antecedentes:

Estou fornecendo aos usuários um script de backup automatizado. (O software de backup real já está instalado em seu computador.)

O trabalho do usuário é conectar um pen drive USB e digitar um comando no terminal (sem parâmetros, opções ou qualquer outra informação variável).

Eu preciso de um script bash que possa encontrar o caminho para o pen drive USB. Se mais de um desses caminhos for encontrado, provavelmente irei apenas abortar e abrir uma mensagem para entrar em contato comigo. Em vez de criar um script complicado, é mais fácil dizer a eles para garantir que apenas um cartão de memória esteja conectado ao computador no momento em que ele deseja executar um backup.

    
por MountainX 12.03.2014 / 03:08

4 respostas

5

Depois de conectar um dispositivo USB, você pode saber o que foi instalado, basta olhar para este caminho:

$ ls -l /dev/disk/by-id/usb*

Exemplo

$ ls -l /dev/disk/by-id/usb*
lrwxrwxrwx. 1 root root  9 Mar 12 01:01 /dev/disk/by-id/usb-JMTek_USBDrive-0:0 -> ../../sdb
lrwxrwxrwx. 1 root root 10 Mar 12 01:01 /dev/disk/by-id/usb-JMTek_USBDrive-0:0-part1 -> ../../sdb1

Com as informações acima, seu script pode simplesmente olhar para essas entradas usando algo como readlink :

$ readlink -f /dev/disk/by-id/usb-JMTek_USBDrive-0:0*
/dev/sdb
/dev/sdb1

E, em seguida, usando o comando mount , caminhe para trás para descobrir em qual diretório o dispositivo foi montado automaticamente:

$ mount | grep '/dev/sdb\b'
$ mount | grep '/dev/sdb1\b'
/dev/sdb1 on /run/media/saml/HOLA type vfat (rw,nosuid,nodev,relatime,uid=1000,gid=1000,fmask=0022,dmask=0077,codepage=437,iocharset=ascii,shortname=mixed,showexec,utf8,flush,errors=remount-ro,uhelper=udisks2)

Isso pode ser expandido para um liner como este:

$ readlink -f /dev/disk/by-id/usb-JMTek_USBDrive-0:0* | \
    while read dev;do mount | grep "$dev\b" | awk '{print $3}';done
/run/media/saml/HOLA

Obtendo o ID de um dispositivo

Você pode analisar isso da saída de /dev/disk/by-id/usb* , assim:

$ ls /dev/disk/by-id/usb* | sed 's/.*usb-\(.*\)-[0-9]:.*//'
JMTek_USBDrive
JMTek_USBDrive

A propósito, esta informação é uma concatenação das descrições do fabricante + produto do USB.

$ usb-devices
...
T:  Bus=02 Lev=02 Prnt=02 Port=01 Cnt=02 Dev#= 10 Spd=12  MxCh= 0
D:  Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs=  1
P:  Vendor=058f ProdID=9380 Rev=01.00
S:  Manufacturer=JMTek
S:  Product=USBDrive
C:  #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
I:  If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage
...

Você também pode acessá-lo assim que tiver estabelecido qual dispositivo ( /dev/sd* ) o dispositivo USB está usando, por meio do UDEV:

$ udevadm info --query=all --name=sdb | grep -E "MODEL=|VENDOR=|ID_SERIAL"
E: ID_MODEL=USBDrive
E: ID_SERIAL=JMTek_USBDrive-0:0
E: ID_VENDOR=JMTek
    
por 12.03.2014 / 06:12
2

Você pode escrever um script para passar pelo / etc / mtab e observar os dispositivos montados, depois usar o udevadm para verificar se eles são dispositivos USB. O / etc / mtab inclui o nome do dispositivo em / dev e seu ponto de montagem. Então você poderia fazer algo como:

IFS=$'\n'
for mtabline in 'cat /etc/mtab'; do 
  device='echo $mtabline | cut -f 1 -d ' ''
  udevline='udevadm info -q path -n $device 2>&1 |grep usb' 
  if [ $? == 0 ] ; then
    devpath='echo $mtabline | cut -f 2 -d ' ''
    echo "devpath: $devpath"
  fi
done

(Você precisa definir o IFS em seu script para que o mtab seja lido linha por linha, em vez de "palavra" por "palavra").

    
por 12.03.2014 / 06:49
0

Na minha área de trabalho sem dispositivos flash USB presentes:

% lsblk -o tran,name,mountpoint
> TRAN   NAME   MOUNTPOINT
> sata   sda
>        ├─sda1 /esp
>        ├─sda2 /
>        ├─sda3 /mnt/sda3
>        ├─sda4
>        └─sda5
> sata   sdb
> sata   sdc
> sata   sr0

No meu laptop com dois:

% lsblk -o tran,name,mountpoint
> TRAN   NAME   MOUNTPOINT
> usb    sda
>        ├─sda1 /esp
>        └─sda2 /
> usb    sdb
>        └─sdb1 /home
> sata   sr0

Isso deve ser tudo que você precisa.

Alguns outros também me disseram que alguns sistemas da família debian ainda não suportam a opção de transporte. Nesse caso, tente isto:

    ( set -- $(lsblk -ndo name,rm)
        while [ $# -ge 2 ] ; do {
            [ $2 -eq 1 ] && \
                udevadm info --query=all --name "/dev/$1"
        shift 2 
     } ; done )   

O comando acima primeiro consulta o lsblk para obter uma lista de dispositivos de blocos atuais (somente pai - somente sda e não sda1 ) por nome e uma coluna para o sinalizador removable . A saída se parece com:

sda 0
sdb 1
sdc 1

Apenas os dispositivos marcados com 1 são removíveis.

Portanto, set our ( subshell ) parâmetros posicionais para o conteúdo dividido que faz dois parâmetros por entrada. while temos pelo menos dois parâmetros posicionais nós [ teste ] $2 para o 1 sinalizador removível, && e, se estivermos presentes, consultamos udevadm o gerenciador de dispositivos do sistema para todas as informações que ele tem em nossa primeira posição posicional parâmetro, ou /dev/$1 . Próximo shift nossos primeiros 2 parâmetros posicionais e recomeçar com os próximos dois.

udevadm fornece muitas informações sobre os dispositivos em que você pode se interessar, mas, se você realmente quiser ir direto ao assunto, adicione o seguinte |pipe a udevadm ' stdout :

    udevadm info --name "/dev/$1" |\
        grep -q ID_BUS=usb && echo "/dev/$1"

Isso forneceria uma lista de apenas dispositivos de bloco usb removíveis / dev / $ DEV atualmente presentes no sistema no formato:

/dev/$DEV /dev/$ALSODEV

Se neste momento você estivesse interessado apenas em pontos de montagem de partições montadas dos links pai fornecidos acima, você poderia juntar tudo junto com findmnt da seguinte forma:

( set -- $(lsblk -ndo name,rm)
    while [ $# -ge 2 ] ; do {
        [ $2 -eq 1 ] &&
            udevadm info --query=all --name "/dev/$1" |\
            grep -q ID_BUS=usb &&
                 printf 'findmnt %s -no TARGET ;' "/dev/$1" /dev/"$1"[0-9]
        shift 2 ; } ; done ) |\ 
    . /dev/stdin

Isso deve fornecer uma lista como:

/removable/usb/device/mount/point/1
/ditto/2
/also/3
    
por 12.03.2014 / 16:12
0

Aqui está a abordagem que estou usando. Vem de:

link
link

export USBKEYS=($(
    for blk in $(lsblk -ndo name) ; do {
        udevadm info --query=all --name "/dev/$blk" |\
        grep -q ID_BUS=usb &&
            printf 'findmnt %s -no TARGET ;'\
                "/dev/$blk" /dev/"$blk"[0-9]
        } ; done 2>&- |. /dev/stdin 
))
echo "$USBKEYS"
export STICK
case ${#USBKEYS[@]} in
    0 ) echo "No USB stick found."; exit 0 ;;
    1 ) STICK=$USBKEYS; echo "STICK=$USBKEYS" ;;
    * ) NOTE: the code for this case is not included in the interest of brevity.
esac

Isso também está funcionando para mim. Provém principalmente do link

#!/bin/bash

while read mtabline
do
  device='echo $mtabline | awk '{print $1}''
  udevline='udevadm info -q path -n $device 2>&1 |grep usb' 
  if [ $? == 0 ] ; then
    echo "$device"
  fi
done < /etc/mtab
    
por 15.03.2014 / 07:06