lsof
é a ferramenta certa para esse trabalho, mas, por padrão, ele examina todos os PIDs por isso é lento e exige muita CPU. Felizmente, existem algumas maneiras de acelerá-lo.
BTW, virt-manager
não será o processo que mantém o arquivo de imagem / dispositivo de disco da VM aberto. Esse será um dos binários qemu
, por exemplo qemu-system-x86_64
Se você sabe que apenas processos específicos podem ter seu arquivo aberto e você sabe ou pode obter seus PIDs, você pode fornecê-los como uma lista separada por vírgula para lsof -p
. por exemplo.
pids=$(pgrep qemu-system | paste -sd,)
[ -n "$pids" ] && lsof -p "$pids" | grep -i filename
Ainda melhor do que isso, você pode fornecer o nome do processo para lsof
com a opção -c
. -c
não requer uma correspondência exata do nome do processo, ele usa um padrão (com um comprimento máximo de 15 caracteres). Você pode usar -c
várias vezes, se necessário, em uma linha de comando. veja man lsof
e a FAQ do lsof para detalhes.
Se você usa > 15 caracteres, você receberá uma mensagem de erro como esta:
# lsof -c qemu-system-x86_64
lsof: "-c qemu-system-x86_64" length (18) > what system provides (15)
De qualquer forma, um exemplo:
# lsof -c qemu-system | grep -i FreeBSD-10.2-RELEASE-amd64.qcow2
qemu-syst 4770 libvirt-qemu 20u REG 8,3 1837236224 403730954 /var/lib/libvirt/images/FreeBSD-10.2-RELEASE-amd64.qcow2
Em um loop while
, seria algo assim:
pname='qemu-system'
fname='FreeBSD-10.2-RELEASE-amd64.qcow2'
while lsof -c "$pname" | grep -qi "$fname" ; do
sleep 0.1 # don't need to sleep for as long between checks
# but if you're not impatient, leave it at 1 second
# rather than 0.1.
done
echo "$fname is not in use"
Isso também funciona se você estiver usando uma partição bruta para sua VM, por exemplo, use fname='/dev/sda5'
no fragmento de script acima.
Se você estiver usando ZVOLs ZFS ou LVs LVM ou similares em vez de imagens baseadas em arquivos, fica um pouco mais complicado. lsof
exibe o nome real do dispositivo de bloco depois que qualquer link simbólico é resolvido, então você também precisa resolver os links simbólicos (por exemplo, usando readlink -f
) e grep para isso.
por exemplo. para o ZFS, com um ZVOL chamado freedos
no pool volumes
:
# fname=$(readlink --n f /dev/zvol/volumes/freedos)
# echo "$fname"
/dev/zd32
e para o LVM com um LV chamado centos7
:
# fname=$(readlink -n -f /dev/mapper/centos7)
# echo $fname
/dev/dm-1
NOTA: /dev/vg/centos7
em vez de /dev/mapper/centos7
também funciona.
Eu originalmente comecei a escrever este método find
-based como uma resposta, mas percebi que o método lsof -c
é melhor. Deixarei para documentar outra alternativa razoavelmente rápida.
find -lname
é muito mais rápido e leve no sistema do que executar lsof
sem a opção -p
PID.
por exemplo,
# sleep 10000 > /tmp/foo &
[1] 31077
# find /proc/[0-9]*/fd/ -lname '/tmp/foo'
/proc/31077/fd/1