Como posso determinar qual processo tem um arquivo aberto no Linux?

124

Eu gostaria de determinar qual processo possui a propriedade de um arquivo de bloqueio. Os arquivos de bloqueio são simplesmente um arquivo com um nome específico que foi criado.

Então, como posso determinar qual processo tem um arquivo específico aberto no Linux? De preferência, um tipo de uma linha ou uma solução específica de ferramenta Linux seria ideal.

Danny
fonte

Respostas:

55

Você também pode usar fuserpara isso:

~> less .vimrc
# put in background
~> fuser .vimrc
.vimrc:              28135
~> ps 28135
  PID TTY      STAT   TIME COMMAND
28135 pts/36   T      0:00 less .vimrc
Nathan Fellman
fonte
isso foi ótimo, mas para usá-lo em um script eu tive que verificar o comprimento da saída.
Chovy
o que você quer dizer com comprimento de saída?
Nathan Fellman
if [ fusor "$ file" `]; então exit`
chovy
1
O fusor tem um comportamento estranho com os códigos de saída. retorna 1 código de saída com dois estados: A / algum erro interno, arquivo verificado não encontrado etc., B / nenhum processo abriu o arquivo especificado. Na situação, uma / alguma mensagem de erro é impressa na saída. Infelizmente, quando o arquivo está disponível e é aberto por alguma coisa, a saída é gerada, mas com o código de saída 0. Seria melhor se o fusor sair com três códigos, não dois como atualmente. lsoft é um pouco pior, porque isso está funcionando mais devagar.
Znik 11/11
Esse é essencialmente o mesmo padrão a lsseguir - retorna o código de saída 2 se houver um erro (por exemplo, opção inválida especificada) ou arquivo não encontrado (e 0 se relatar informações com êxito).
Scott
144

Na maioria dos sistemas Linux, lsof NAMEo trabalho é:

fin@r2d2:~$ lsof /home/fin
COMMAND   PID USER   FD   TYPE DEVICE SIZE    NODE NAME
bash    21310  fin  cwd    DIR    8,1 4096 5054467 /home/fin
lsof    21320  fin  cwd    DIR    8,1 4096 5054467 /home/fin
lsof    21321  fin  cwd    DIR    8,1 4096 5054467 /home/fin
fin@r2d2:~$
barbatana
fonte
4
E se você não tiver lsof?
JoseLSegura
3
@ JosephLSegura: Suponho que você tenha recursos suficientes para que a resposta 'instale lsof' seja inútil para você. Você pode elaborar seu problema? Se você não possui root, provavelmente não possui privs para descobrir se outro usuário tem o arquivo aberto de qualquer maneira.
Michael Scheper
isso parece não funcionar para arquivos, apenas para dirs
Jason
@ Jason: ele funciona para arquivos, mas as cwdlinhas (que relatam usar como o diretório de trabalho atual de um processo) apenas reportam diretórios.
reinierpost
9

Ter um arquivo aberto não é um bloqueio, porque, se cada processo precisar verificar se o arquivo está aberto primeiro e não continuar se estiver, ou criar / abrir se não estiver, dois processos poderão verificar simultaneamente, ambos encontrarão que não está aberto, crie-o ou abra-o.

Para usar um arquivo como um bloqueio, a operação de verificação e bloqueio deve ser uma única operação ininterrupta. Você pode conseguir isso em um sistema de arquivos Unix criando um arquivo no modo somente leitura e removendo-o para desbloquear. Se o arquivo existir (e for somente leitura), a criação do arquivo falhará, portanto você poderá verificar e bloquear em uma única operação atômica.

Se o seu processo de bloqueio for um script de shell que será executado como um daemon, você poderá obter esse efeito usando umaskuma configuração por processo que define as permissões com as quais os novos arquivos são criados:

oldumask = $ (umask)
umask 222 # também cria arquivos graváveis ​​para o proprietário
se eco $$> / var / lock / foo
então
    : bloqueio bem-sucedido
outro
    : bloqueio falhou
fi
umask $ oldumask
Isso também grava o processo de propriedade 'PID no arquivo, o que resolve seu outro problema: cat /var/lock/foo
No que diz respeito à pergunta específica "Quais processos têm esse arquivo aberto?", Isso pode ser útil quando você deseja desmontar um sistema de arquivos, mas não pode porque alguns processos têm um arquivo aberto. Se você não possui esses comandos disponíveis, pode perguntar /proccomo root:

ls -l /proc/*/cwd | grep '/var/lock/foo$'

ou, como usuário mortal:

ls -l /proc/*/cwd 2>/dev/null | grep '/var/lock/foo$'

martinwguy
fonte
o método `ls -l 'funciona no Linux, mas parece não estar funcionando para o CygWin: não há informações sobre o bloqueio de arquivos. Você não saberia resolver? Obrigado.
Sopalajo de Arrierez
Não, você não cria um arquivo somente leitura para um bloqueio, porque quando o aplicativo falha, o arquivo ainda estará lá. Forçar o usuário a esclarecer a porcaria depois que seu aplicativo travado é mental.
polkovnikov.ph
6

Se você deseja saber qual descritor de arquivo do processo exato está vinculado ao seu arquivo sem lsofou fuser- pesquise por /proc:

$ find /proc -regex '\/proc\/[0-9]+\/fd\/.*' -type l -lname "*$1*" -printf "%p -> %l\n" 2> /dev/null

Substitua $1pelo nome do arquivo aberto que você está procurando. Você pode alterar o -printfque você deseja ver ou canalizar egrep -o '[0-9]+' | head -1para usar nas informações desse processo.ps -Fp <pid>

A resposta de @fin é a melhor resposta, obviamente, mas para responder ao comentário de @ JoseLSegura , se não estiver disponível, a solução acima foi minha resposta.$ lsof <filename>

Scott
fonte
2

Eu descobri que o uso da resposta aceita não listou os processos que estavam usando meu diretório (ubuntu 14.04).

No final, usei lsof (listar arquivos abertos) e dei uma olhada em sua saída para encontrar o processo incorreto:

lsof | egrep "<regexp-for-your-file>"
Eosis
fonte
Uma maneira mais limpa e rápida para esse uso lsofé a sua opção -R. por exemplo: lsof -R [filename]
tron5