Como posso verificar se um arquivo de bloqueio do apt está bloqueado?

5

Eu estou escrevendo um script para fazer alguns comandos apt, mas estou com problemas em potencial dos bancos de dados apt / dpkg sendo bloqueados para que meu script seja corrigido. Eu quero verificar os arquivos de bloqueio (ou seja, / var / lib / dpkg / lock) antes de fazer qualquer coisa como o apt quando executa o comando, mas não consigo descobrir como o apt está executando o bloqueio.

O arquivo de trava está sempre lá, e o apt-get não está fazendo um bando no arquivo. De que outra forma seria verificar se está em uso? De um strace eu vejo que o apt-get abre o arquivo, mas é isso. No meu script, posso abrir o arquivo enquanto o apt-get também o abre.

    
por gondoi 13.01.2011 / 04:32

4 respostas

2

Eu descobri que apt está usando um fcntl. Como estou usando Ruby para a linguagem de script, tive que criar minha própria função para procurar por bloqueio. A razão para isso é que o Ruby não implementa totalmente a função fcntl. Apenas fornece a chamada de função e constantes. A capacidade de construir estruturas de floco e como passá-las é omitida ou não é documentada.

Aqui está a lista que encontrei falando sobre isso .

Aqui está a função que acabei escrevendo:

def flocked? &block
  flockstruct = [Fcntl::F_RDLCK, 0, 0, 0, 0].pack("ssqqi")
  fcntl Fcntl::F_GETLK, flockstruct
  status = flockstruct.unpack("ssqqi")[0]
  case status
    when Fcntl::F_UNLCK
      return false 
    when Fcntl::F_WRLCK|Fcntl::F_RDLCK
      return true
    else
      raise SystemCallError, status
  end
end
    
por 14.01.2011 / 16:04
4

Bem, eu pensei que haveria uma resposta simples aqui, mas não consigo encontrar nada. Primeiro, você tem 100% de certeza de que o arquivo de bloqueio está sempre lá? Tente executar

lsof /var/lib/dpkg/lock

como root para ver se algum processo o tem aberto.

Pelo que eu li, o apt-get faz um bloqueio fcntl, mas eu não olhei para o código para verificar. Eu acho que isso explicaria porque o arquivo está lá o tempo todo, apenas bloqueia quando necessário.

Que tal apenas fazer uma verificação da lista de processos quando o script é executado e sair se o apt estiver sendo executado ao mesmo tempo? Isso seria suficiente para seu uso?

Parece que este pessoa seguiu o mesmo caminho que você, sem muito sucesso.

    
por 13.01.2011 / 09:13
2

Eu vim aqui procurando uma solução semelhante ao que o gondoi acabou usando, mas escrito em Python ao invés de Ruby. O seguinte parece funcionar bem:

import fcntl

def is_dpkg_active():
    """
    Check whether ''apt-get'' or ''dpkg'' is currently active.

    This works by checking whether the lock file ''/var/lib/dpkg/lock'' is
    locked by an ''apt-get'' or ''dpkg'' process, which in turn is done by
    momentarily trying to acquire the lock. This means that the current process
    needs to have sufficient privileges.

    :returns: ''True'' when the lock is already taken (''apt-get'' or ''dpkg''
              is running), ''False'' otherwise.
    :raises: :py:exc:'exceptions.IOError' if the required privileges are not
             available.

    .. note:: ''apt-get'' doesn't acquire this lock until it needs it, for
              example an ''apt-get update'' run consists of two phases (first
              fetching updated package lists and then updating the local
              package index) and only the second phase claims the lock (because
              the second phase writes the local package index which is also
              read from and written to by ''dpkg'').
    """
    with open('/var/lib/dpkg/lock', 'w') as handle:
        try:
            fcntl.lockf(handle, fcntl.LOCK_EX | fcntl.LOCK_NB)
            return False
        except IOError:
            return True
    
por 04.08.2014 / 23:55
2

De um script de shell (consulte flock (1) ):

flock --timeout 60 --exclusive --close /var/lib/dpkg/lock apt-get -y -o Dpkg::Options::="--force-confold" upgrade
if [ $? -ne 0 ]; then
  echo "Another process has f-locked /var/lib/dpkg/lock" 1>&2
  exit 1
fi
    
por 16.06.2017 / 02:42