Estou tentando implementar uma função personalizada que, ao anexar uma unidade USB, verifica todos os sistemas de arquivos que ela contém e, em seguida, executa operações com base no tipo de sistema de arquivos detectado. Eu segui o caminho "recomendado" para escrever uma udev
regra que aciona um systemd
serviço "oneshot" instanciado para o nó do dispositivo, que por sua vez executa o script de shell que "faz toda a mágica (TM)" (por razões de independência de plataforma, um compilado programa não foi considerado uma opção aqui).
ACTION=="add", SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", RUN{program}="/bin/systemctl start usb-drive-manager@$devnode.service"
com
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/local/bin/usb_drive_manager.sh attach %I
ExecStop=/usr/local/bin/usb_drive_manager.sh detach %I
Dentro do script de shell, executo um ls /sys/.../sdX/sdX*
caminho no dispositivo da unidade para localizar quaisquer partições e, em seguida, consultar informações sobre essas partições chamando
udevadm info /dev/sdXn
(onde n
é o número da partição) para cada partição processada.
O problema agora é que, embora isso funcione durante os testes "coldplug" do script de shell, não funciona quando o script é acionado a partir da udev
regra, porque no momento em que o udev
evento para a unidade é processado, as informações sobre as partições na unidade são ainda não coletado pelo kernel, ou seja, a chamada para udevadm info
retorna apenas informações rudimentares:
P: /devices/.../block/sdb/sdb1
N: sdb1
E: DEVNAME=/dev/sdb1
E: DEVPATH=/devices/.../block/sdb/sdb1
E: DEVTYPE=partition
E: MAJOR=8
E: MINOR=17
E: SUBSYSTEM=block
e todas as informações relevantes, em particular as variáveis de ambiente ID_FS_TYPE
e estão (ainda) ausentes. ID_FS_LABEL
Como chamar udevadm settle
durante o processamento de udev
eventos é uma má ideia (e também não ajudou), e até mesmo um loop de pesquisa com 0,5s de sono entre as chamadas para udevadm info
não funcionou (demorou cerca de 1 minuto até que a informação estivesse finalmente disponível), eu estou um pouco perdido aqui.
Infelizmente, reescrever a udev
regra para que ela se aplique a partições em vez de unidades também é indesejável, pois há casos em que as pessoas criam o sistema de arquivos em todo o dispositivo USB em vez de criar uma única partição que abrange todo o dispositivo que contém o sistema de arquivos.
A questão agora é se
- é possível atrasar o processamento de uma
udev
regra para um determinado dispositivo até que todos os filhos desse dispositivo tenham sido processados, ou - há uma chamada de sistema que eu poderia usar dentro do script de shell que "espera" que todos os eventos filho (se houver!
udev
)
Acho que esta é uma pergunta bastante longa agora; toda a ajuda é muito apreciada.
Depois de mais algumas pesquisas, que me apontaram para o uso de regras
blkid
no udev (veja, por exemplo , este artigo do ArchLinux-Wiki , infelizmente disponível apenas em alemão), descobri que chamandoao invés de
dentro do
systemd
script -triggered é possível recuperar informações completas até mesmo sobre os dispositivos filhos do pendrive cuja regra "add" está sendo processada.Parece que a
-p
opção aqui é a chave, pois muda para um modo de sondagem ativo no qual o dispositivo é realmente lido, em vez de depender de informações armazenadas em cache (por exemplo, a página de manual ou o código-fonte deblkid
).A
-o udev
opção simplesmente serve para formatar a saída de maneira semelhante àudevadm
chamada, embora não seja uma substituição 100% imediata, pois os rótulos identificadores principais daudevadm
saída (comoE:
,P:
, etc.) estão ausentes aqui.