Existe uma maneira mais rápida de verificar se um arquivo está em uso?

8

Estou procurando uma função de linha de comando ou função c que me informe se um arquivo está aberto / em uso por algo.

lsofe fuserconte isso, mas eles fornecem muitas outras informações que resultam em até 300ms em algumas situações (como quando eu uso esse código no MAC OS X, estou desenvolvendo para Linux e OS X) (eu tenho um windows solução que leva 5ms, então estou tentando encontrar algo no Unix que também seja muito rápido e retorne verdadeiro ou falso se o arquivo estiver em uso)

Noitidart
fonte

Respostas:

9

Se você estiver usando isso como um bloqueio, não vai funcionar como nenhum lsofou fuserevitar condições de corrida.

O processo básico lsofé vasculhar todos os processos que /proc/*/fsprocuram descritores de arquivos abertos. Isso vai levar tempo, não importa o que você faça.

Você pode fazer isso sozinho, mas não é provável que seja mais rápido, pois você deve verificar todos os processos abertos no sistema.

Se o que você está fazendo é crítico em termos de tempo, descubra outra maneira de fazê-lo.

  • Se você controla o arquivo através de um programa que você escreveu; use um arquivo de bloqueio.
  • Se você estiver executando algum comando que opera no arquivo, veja e veja a documentação que esse comando / programa oferece e veja se ele não pode criar um arquivo de bloqueio. Caso contrário, verifique se ele não pode criar um arquivo com seu PID dentro dele. Em seguida, você pode /proc/<PID>/fsver se seu arquivo está aberto ou não. Analisar apenas um dos descritores de arquivo aberto dos processos será muito mais rápido que o mapeamento em todos eles.
  • Caso contrário, para ajudá-lo, precisarei de mais informações sobre o que você está fazendo.

Você forneceu mais informações em um comentário que deseja determinar se o Firefox está sendo executado em um determinado sistema. A melhor maneira de fazer isso é procurar os arquivos de bloqueio do Firefox. Eles são armazenados nos locais padrão especificados no wiki do Mozilla.

Por exemplo, no linux, faça com que seu programa faça o seguinte:

  • abra o ~/.mozilla/firefox/diretório
  • Liste todos os diretórios, filtrando os diretórios que terminam em .default. (Acho que todos os perfis terminam com .default, se não apenas rastrear todos os diretórios.)
  • Em cada diretório acima, procure a existência de um arquivo chamado lockor .parentlock. Se você vir um ou ambos os arquivos, o Firefox está aberto.

Esse algoritmo deve executar mais rapidamente do que o que você faz no Windows atualmente.

nixeagle
fonte
Excelente resposta obrigado. Existe alguma maneira de dizer ao lsof e ao fuser para verificar apenas a pasta pid se for o firefox? Isso tornaria ignorar todo o conteúdo de pastas, exceto para pastas de firefox (eu tenho 3 instâncias separadas de modo que significa que apenas cheques 3 pastas né?)
Noitidart
O arquivo está bloqueado, mas não consigo descobrir como testar se está bloqueado. Está sendo aberto com êxito para leitura / gravação. Isto é tão estranho. Eu tentei fcntl de c, mas está sempre retornando -1 :(
Noitidart
3
@Noitidart Qual é o seu problema real que você está tentando resolver? Para pesquisar os descritores de arquivos abertos de qualquer processo, é necessário conhecer seu PID. Isso muda para cada instância do programa. Uma maneira simples de obtê-lo "manualmente" é com ps aux firefox. Pegue esses PIDs e procure-os no /proc/sistema de arquivos.
Nixeagle 23/09/14
ah obrigado, é uma boa ideia ps aux firefox. Bem, minha situação exata é: eu tenho o caminho para um arquivo. Está bloqueado se o Firefox estiver em execução. Eu quero ver se está bloqueado ou não para dizer se o Firefox está em execução.
Noitidart 23/09/14
1
@Noitidart Eu editei meu comentário para incluir como detectar o Firefox olhando os arquivos de bloqueio. Você pode repetir esse processo em todos os sistemas.
Nixeagle 23/09/14
1

TL; DR

Em um de seus comentários , você declara:

Bem, minha situação exata é: eu tenho o caminho para um arquivo. Está bloqueado se o Firefox estiver em execução. Eu quero ver se está bloqueado ou não para dizer se o Firefox está em execução.

Sua pergunta original sobre arquivos de bloqueio parece ser o longo caminho, quando há maneiras mais fáceis de descobrir se o Firefox está sendo executado para um determinado usuário e inspecionar o estado do processo.

Examinando o estado do processo

Uma maneira mais sensata de encontrar o PID de um determinado processo é usar o pgrep do pacote procps . Por exemplo:

$ pgrep -u $LOGNAME firefox
5671

Você pode inspecionar o estado do PID com ps :

$ ps 5671
  PID TTY      STAT   TIME COMMAND
 5671 ?        Sl   105:47 /usr/lib/firefox/firefox

ou apenas obtenha as bandeiras de estado sem nenhum outro problema:

$ ps -ho stat $(pgrep -u $LOGNAME firefox)
Sl

No meu sistema, o one-liner acima leva consistentemente apenas 1,4 milissegundos para ser concluído. Sua milhagem pode variar.

Códigos de estado do processo

A seção PROCESS STATE CODES do ps (1) detalha o que significam os vários sinalizadores de estado. No Ubuntu 14.04, a página do manual diz:

PROCESS STATE CODES
       Here are the different values that the s, stat and state output
       specifiers (header "STAT" or "S") will display to describe the state of
       a process:

               D    uninterruptible sleep (usually IO)
               R    running or runnable (on run queue)
               S    interruptible sleep (waiting for an event to complete)
               T    stopped, either by a job control signal or because it is
                    being traced
               W    paging (not valid since the 2.6.xx kernel)
               X    dead (should never be seen)
               Z    defunct ("zombie") process, terminated but not reaped by
                    its parent

       For BSD formats and when the stat keyword is used, additional
       characters may be displayed:

               <    high-priority (not nice to other users)
               N    low-priority (nice to other users)
               L    has pages locked into memory (for real-time and custom IO)
               s    is a session leader
               l    is multi-threaded (using CLONE_THREAD, like NPTL pthreads
                    do)
               +    is in the foreground process group
CodeGnome
fonte
1
o problema é que ele precisa saber em qual sessão do firefox está atualmente. No linux, você simplesmente procura ~/.mozilla/firefox/*/lock. Você pode identificar a sessão observando o nome do diretório pai de cada arquivo de bloqueio. Em outras plataformas, isso não funciona. Nosso bate-papo aborda mais como fazê-lo funcionar em macs (o que é meio irrelevante para o ubuntu, mas você já sabe). Para ser justo, ele realmente deve atualizar a pergunta para ser mais específica. : P
nixeagle 24/09