Identifica programaticamente o dispositivo de bloco do sistema de arquivos [closed]

0

O código a seguir foi testado no RedHat 7 usando df verison 8.2 e lsblk version 2.23.2 . Isto é importante porque o utilitário lsblk tem significativamente mais opções de saída do que a versão 6 do RedHat (2.17.2)

É muito fácil determinar o sistema de arquivos que contém um arquivo:

df -h /path/to/file | tail -n 1 | awk '{print $1}'

No entanto, é surpreendentemente difícil determinar qual dispositivo de bloco contém esse sistema de arquivos. Claro, você pode determinar manualmente o dispositivo de bloco com lsblk -f , mas eu estou querendo saber como você faz isso de forma automatizada.

Eu tenho feito uma pesquisa bem profunda, mas não consegui encontrar uma maneira de fazer isso. O que é estranho porque parece que há um caso de uso comum (varrendo um diretório em uma unidade e retornando o número de série do disco físico que você digitalizou!)

Eu criei uma função bash recursiva que faz uma análise de texto feia, o que funciona, ela parece bastante hackish. Embora a documentação do lsblk pareça sugerir que, se você usar a opção --output , você terá scripts confiáveis nas atualizações de versão

function findBlockDevice {
  fileSystem="${1}"
  count="${2}"

  potentialBlockDeviceOutput=$(lsblk --paths --output name,type | grep "${fileSystem}" -B${count} | head -n 1)
  blockDevice=$(echo ${potentialBlockDeviceOutput} | awk '{print $1}')
  blockType=$(echo ${potentialBlockDeviceOutput} | awk '{print $2}')

  if [[ "${blockType}" != "disk" ]]; then
    count=$(( count + 1 ))
    findBlockDevice "${fileSystem}" "${count}"
  else
    echo "${blockDevice}"
  fi
}

Uso:

# Assume directory is on /dev/sda1
scanDirectory='/media/suspiciousDrive'
fileSystem=$(df -h ${scanDirectory} | tail -n 1 | awk '{print $1}')
blockDevice=$(findBlockDevice ${fileSystem} 0)

echo "${fileSystem}" # /dev/sda1
echo "${blockDevice}" # /dev/sda

# Now we can get the disk information to use in a report
lsblk --nodeps --paths --pairs --output NAME,SERIAL,MOUNTPOINT,VENDOR,\
    FSTYPE,UUID,MODEL,SIZE,TYPE,WWN,STATE ${fileSystem}

EDITAR: A saída de df não é suficiente, porque os resultados retornados do utilitário lsblk são diferentes quando é fornecido um sistema de arquivos versus um disco. O seguinte comando retorna informações muito diferentes quando dado o dispositivo de bloco inteiro, em oposição a apenas o sistema de arquivos

# Run this on your machine and notice the significant difference
lsblk --nodeps --paths --pairs --output NAME,SERIAL,VENDOR,MODEL /dev/sda
lsblk --nodeps --paths --pairs --output NAME,SERIAL,VENDOR,MODEL /dev/sda1
Em última análise, eu queria uma solução simples para resolver o problema com a natureza do  "Digitalize este disco rígido e também retorne automaticamente as informações sobre a unidade do dispositivo físico, independentemente de qual diretório você está digitalizando na unidade"

Eu tenho uma solução, é apenas bastante complexa e queria saber se havia algo mais fácil.

Outra edição: Estou surpreso que muitas pessoas pensam que isso é uma duplicata, ou estão confusas sobre o motivo pelo qual a saída de df não é suficiente. df retorna o sistema de arquivos, NÃO o dispositivo de bloco. Consultar informações no sistema de arquivos NÃO retorna nenhum metadado sobre o dispositivo de bloco, como seu número de série ou modelo. Por que eu programaticamente quero saber o número de série ou o modelo de disco rígido dos discos rígidos? Espero que isso não seja uma questão séria de acompanhamento de ninguém.

    
por Luke Pafford 12.06.2018 / 18:23

1 resposta

1

Olhando o código que você forneceu, parece que você quer poder mapear um arquivo em um sistema de arquivos de volta para um disco físico no qual ele reside. Parece não haver consideração de sistemas de arquivos RAID, LVM ou criptografados.

O código a seguir imprimirá o (s) dispositivo (s) de disco que contém o arquivo especificado. Para RAID e LVM, é possível que o arquivo esteja presente em mais de um dispositivo; nessa situação, todos os nomes de dispositivos de disco relevantes serão impressos, um por linha.

read -p 'Filename: ' file
devpart=$(mount | awk -v mount=$(stat --format '%m' "$file") '$3 == mount {print $1}')
lsblk --list | awk -v part="${devpart/#*\/}" '$6 == "disk" {disk = $1} $6 != "disk" && $1 == part {print disk}'
    
por 13.06.2018 / 00:08