Estou criando um arquivo systemd .service e preciso de ajuda para entender a diferença entre Requires=
e After=
. A página man diz que Requires=
"Configura dependências de requisitos em outras unidades". e After=
"Configura as dependências de ordenação entre as unidades." Qual é a diferença?
After=
configura ordem de serviço (fazer X somente após Y), enquantoRequires=
estado de dependências. Se você não especificar um pedido, um serviço dependente de outro será iniciado ao mesmo tempo que aquele do qual depende. Além disso, a maneira como eu entendo (embora eu não possa testar isso agora e não encontre uma referência),After=
é um "acoplamento solto", e um serviço com essa instrução ainda seria executado se o nome daAfter=
linha fosse não foi iniciado, enquantoRequires=
impediria que fosse iniciado se o requisito não fosse atendido.Citando https://www.freedesktop.org/software/systemd/man/systemd.unit.html :
e
Uma das grandes diferenças é,
After
apenas verifica se a unidade já está ativada e não ativa explicitamente as unidades especificadas.Requires
são ativadas junto com a unidade. Se alguma das unidades necessárias não iniciar, a unidade não é ativada.Considere que eu tenho um arquivo de unidade
test-app.service
,Aqui está o que acontecerá quando esta instrução for executada,
After
verifica senetwork-online.target
.network-online.target
não for iniciado, ele irá esperar.test-app
inicia somente depois denetwork-online.target
ativoSe eu tivesse
Requires
em vez disso,Aqui está o que acontecerá quando esta instrução for executada,
network-online.target
etest-app
são ativados juntosnetwork-online.target
falhar ao iniciartest-app
não será ativado.systemd é um gerenciador de tarefas. A página man não é muito precisa sobre como as coisas funcionam.
Quando você inicializa, o que o systemd faz é construir uma transação composta de trabalhos para o trabalho âncora (ou seja, iniciar o trabalho para default.target). O que todas essas dependências e relacionamentos fazem é definir como e quais jobs serão acionados. A ordenação define qual(is) tarefa(s) cada outra tarefa aguardará. A unidade default.target, portanto, está no centro de tudo isso, e é por isso que ao habilitar unidades você usa uma dependência reversa que através do systemctl enable cria um link simbólico do sistema de arquivos denotando uma dependência direta que o systemd pode seguir (também por que você precisa de links simbólicos do sistema de arquivos no primeiro lugar). Semelhante é quando você inicia manualmente alguma unidade, então essa unidade é âncora e a transação é computada nela.
Sem entrar em muitos detalhes, vou explicar o que Requires= e After= fazem.
Requires= fará com que o systemd dispare um trabalho inicial para a unidade necessária quando você tiver um trabalho inicial acionado (explicitamente ou por meio de uma dependência: não há distinção internamente). Ele também tem a propriedade de acionar um trabalho de parada em você quando esta unidade é parada (nota: parada, não desligando sozinha) ou reiniciada. Isso significa que se alguma dependência/systemctl fizer com que ele pare/reinicie, você também irá parar/reiniciar. No entanto, se ele cair sozinho, você não vai parar, pois não houve trabalho e a mudança de estado aconteceu sem o envolvimento do systemd. É aí que você usaria BindsTo= (semelhante a unidades de dispositivo, que podem ficar inativas sem o envolvimento do systemd, por razões óbvias).
Agora, o uso de After= é recomendado, pois Requires= sozinho é atrevido para o que faz: cancelar o requiree se o trabalho inicial falhar. Este cancelamento no entanto só funciona wrt jobs, ou seja, se a outra unidade não definir a ordenação, o systemd aciona ambos em paralelo, e se o seu start job terminar antes do seu start job falhar, ele não será cancelado (não pode ser cancelado, na verdade) . O uso de After= significa que outro trabalho continua esperando até que o trabalho inicial da unidade necessária termine e, dependendo do resultado, se falhar, o trabalho inicial em espera da sua unidade é cancelado com o resultado do trabalho JOB_DEPENDENCY (por que você usa amarelo [DEPEND] na inicialização para esses casos). Portanto, esse efeito de invalidação é indeterminístico sem o uso de After=.
É por isso que usar Wants= sem After= é bom se você não quiser esperar pela inicialização da outra unidade: como não há invalidação lá, então não há corrida. Nesse caso, não passa de um mecanismo de sincronização.
Além disso, você também pode habilitar ambos na inicialização, e não exigir um do outro, e apenas definir a ordenação, nesse caso, quando ambos forem puxados como parte da mesma transação, eles serão ordenados (ou se o trabalho para o outro for acionado enquanto o trabalho para a unidade que deseja executar estiver em execução, ele primeiro aguardará sua conclusão, nas transações).
Agora, se não houver trabalho, o pedido não terá efeito para a referida unidade. No entanto, geralmente há um job, como consequência do uso de dependências como Requires= e Wants=, ou ambos sendo puxados ao mesmo tempo e definem algum pedido, caso em que eles esperam pelo job(s) da outra unidade.