Em um sistema baseado em Debian, tenho um trabalho agendado (por exemplo, cron job ou timer/serviço do systemd) que é executado a cada 30 minutos. No entanto, não quero que isso aconteça simultaneamente com a instalação ou atualização de pacotes.
A instalação do pacote pode acontecer manualmente ou de forma programada, mas neste último caso há um atraso aleatório considerável. Eu poderia adaptar o cronograma do meu trabalho para não interferir em uma possível atualização de pacote (esteja algo realmente instalado ou não) e lembrar de desabilitar o trabalho ao instalar pacotes manualmente e lembrar de habilitá-lo depois - mas isso não é realmente satisfatório .
Portanto, estou procurando uma maneira confiável de informar que a instalação do pacote está em andamento, para que meu trabalho possa verificá-lo e sair (ou atrasar a execução), se for esse o caso. Se as informações do repositório estiverem sendo atualizadas ou os pacotes estiverem sendo baixados em segundo plano simultaneamente com o meu trabalho, isso não é realmente um problema, mas meu trabalho não deve ser executado enquanto a instalação está acontecendo (cópia de arquivos, configuração, scripts pré/pós-instalação e semelhante).
No OPNsense (que é baseado no FreeBSD), o atualizador do sistema adquire um bloqueio em um arquivo específico, então envolvi meu trabalho dentro do arquivo flock
. Se uma atualização estiver em andamento, meu trabalho será ignorado. Se uma atualização fosse acionada enquanto meu trabalho estivesse em execução, provavelmente a atualização falharia com uma mensagem indicando que outra atualização está em andamento.
Gostaria de saber se o apt no Debian tem algo semelhante, como um arquivo de bloqueio que eu possa verificar. Se sim – esse mecanismo é exclusivo para um determinado frontend de gerenciamento de pacotes ou funcionaria com todas as ferramentas padrão para pacotes .deb (por exemplo, dpkg, apt, aptitude, synaptic e similares)?
Vejo que quando o Synaptic está aberto e tento executar sudo apt-get upgrade
, recebo:
E: Could not get lock /var/lib/dpkg/lock-frontend. It is held by process 1234 (synaptic)
N: Be aware that removing the lock file is not a solution and may break your system.
E: Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend), is another process using it?
No entanto, sudo flock -n /var/lib/dpkg/lock-frontend sleep 10 || echo File is locked
é bem-sucedido (ou seja, flock
retorna true
, indicando que obtive o bloqueio, sleep
é executado enquanto echo
não) mesmo enquanto o Synaptic está em execução (embora não esteja instalando nada no momento). Mesmo comportamento com /var/lib/dpkg/lock
.
Então, como posso obter um “bloqueio na instalação do pacote”?
Gerenciadores de pacotes no Debian – a julgar pelos resultados dos meus testes, isso
apt
também é verdade para frontendsdpkg
– bloqueia dois arquivos/var/lib/dpkg/lock
e/var/lib/dpkg/lock-frontend
. De acordo com meus testes, o Synaptic bloqueia os dois arquivos assim que a GUI é ativada e os mantém até sair.No entanto, existem diferentes tipos de bloqueios no Linux, que não têm garantia de compatibilidade entre si, portanto, ambos os métodos podem adquirir um bloqueio exclusivo no mesmo arquivo ao mesmo tempo:
flock(1)
, que chamaflock(2)
internamente, elockf(3)
, que chamafcntl(2)
internamenteConforme detalhado nesta resposta ,
dpkg
usa e sempre usoufcntl(2)
internamente. Infelizmente, emboraflock(2)
venha com um wrapper de linha de comando disponível na maioria dos sistemas Debian, não consegui encontrar um equivalente parafcntl(2)
. Suas opções são instalarchiark-utils-bin
, o que fornecewith-lock-ex(1)
, ou escrever algum código Python. O seguinte funcionou para mim, na medida em que relata o arquivo como bloqueado quando o Synaptic está em execução, mas relata sucesso quando nenhuma ferramenta apt está em execução:Após o teste, posso confirmar que isso impede a execução simultânea do programa Python em questão e do gerenciador de pacotes – quem tentar adquirir o bloqueio primeiro o consegue, outros processos terão que tentar novamente mais tarde. O Atualizador de Software exibe
Waiting for python3 to finish
se o programa Python mantém o bloqueio; o programa Python exibirá a mensagem de erro se o Synaptic estiver em execução ou o Update Manager estiver instalando atualizações.Não há necessidade de liberar explicitamente o bloqueio – isso acontece automaticamente quando o processo que o mantém é encerrado.