No systemd, qual é a diferença entre After = e Requer =?

54

Estou criando um arquivo .service systemd e preciso de ajuda para entender a diferença entre Requires=e After=. A página do manual diz que Requires="Configura dependências de requisitos em outras unidades". e After="Configura dependências de pedidos entre unidades". Qual é a diferença?

TomOnTime
fonte

Respostas:

44

After=configura a ordem de serviço (execute X somente após Y), enquanto Requires=as dependências de estado. Se você não especificar um pedido, um serviço dependendo de outro será iniciado ao mesmo tempo em que ele depende. Além disso, o modo como o entendo (embora não possa testar isso agora e não encontre uma referência) After=é um "acoplamento flexível", e um serviço com essa instrução ainda seria executado se o nomeado na After=linha não não foi iniciado, mas Require=impediria o início se o requisito não fosse atendido.

Citando https://www.freedesktop.org/software/systemd/man/systemd.unit.html :

Requer =

Configura dependências de requisitos em outras unidades. Se esta unidade for ativada, as unidades listadas aqui também serão ativadas. Se uma das outras unidades for desativada ou sua ativação falhar, esta unidade será desativada. Essa opção pode ser especificada mais de uma vez ou várias unidades separadas por espaço podem ser especificadas em uma opção. Nesse caso, serão criadas dependências de requisitos para todos os nomes listados. Observe que as dependências de requisitos não influenciam a ordem na qual os serviços são iniciados ou parados. Isso deve ser configurado independentemente com as opções After = ou Before =. Se uma unidade foo.service exigir uma unidade bar.service conforme configurado com Requer = e nenhuma ordem for configurada com After = ou Before =, as duas unidades serão iniciadas simultaneamente e sem nenhum atraso entre elas se foo.service estiver ativado. Frequentemente,

e

Antes =, Depois =

Uma lista separada por espaços de nomes de unidades. Configura dependências de pedidos entre unidades. Se uma unidade foo.service contiver uma configuração Antes = bar.service e as duas unidades estiverem sendo iniciadas, a inicialização do bar.service será adiada até que foo.service seja iniciado. Observe que essa configuração é independente e ortogonal às dependências de requisitos, conforme definido por Requer =. É um padrão comum incluir um nome de unidade nas opções Depois = e Requer =; nesse caso, a unidade listada será iniciada antes da unidade configurada com essas opções. Essa opção pode ser especificada mais de uma vez; nesse caso, as dependências de pedidos para todos os nomes listados são criadas. After = é o inverso de Before =, ou seja, enquanto After = garante que a unidade configurada seja iniciada após a unidade listada terminar de iniciar, Before = garante o oposto, ou seja que a unidade configurada foi totalmente inicializada antes da unidade listada ser iniciada. Observe que quando duas unidades com uma dependência de pedidos entre elas são desligadas, o inverso da ordem de inicialização é aplicado. ou seja, se uma unidade estiver configurada com After = em outra unidade, a primeira será parada antes da segunda se ambas forem desligadas. Dadas duas unidades com qualquer dependência de pedidos entre elas, se uma unidade for desligada e a outra inicializada, o desligamento será solicitado antes da inicialização. Não importa se a dependência do pedido é Depois = ou Antes =. Também não importa qual dos dois está desligado, desde que um esteja desligado e o outro iniciado. O desligamento é ordenado antes da inicialização em todos os casos. Se duas unidades não tiverem dependências de pedidos entre elas, elas serão encerradas ou inicializadas simultaneamente,

Sven
fonte
7
O que é uma dependência, se não uma declaração de ordem? (sério ... eu não entendo a diferença)
TomOnTime
Veja minha edição. Meu entendimento: After=Xsignificaria "Faça isso depois de X se X for feito", enquanto Require=Xsignificaria "não faça isso de jeito nenhum se você não puder fazer X".
Sven
A Before=seção da página de manual parece confirmar isso. If a unit foo.service contains a setting Before=bar.service and both units are being started, bar.service's start-up is delayed until foo.service is started up Pelo que entendi, a ordem não seria aplicada se bar.servicenão fosse iniciada de qualquer maneira e foo.serviceseria iniciada normalmente.
Sven
10

Uma das principais diferenças é,

  • After verifica apenas se a unidade já está ativada e não ativa explicitamente as unidades especificadas.
  • As unidades listadas em Requiressão ativadas junto com a unidade. Se alguma das unidades necessárias falhar ao iniciar, a unidade não será ativada.

Considere que eu tenho um arquivo de unidade test-app.service,

[Unit]
Description=test app
After=network-online.target

Aqui está o que acontecerá quando esta instrução for executada,

  • Afterverifica se network-online.target.
  • se network-online.targetnão iniciado, ele aguardará.
  • test-appinicia somente depois que network-online.targetestá ativo

Se eu tivesse Requires,

[Unit]
Description=test app
Requires=network-online.target

Aqui está o que acontecerá quando esta instrução for executada,

  • network-online.targete test-appsão ativados juntos
  • se network-online.targetfalhar ao iniciar test-app, não será ativado.
Sufiyan Ghori
fonte
2

systemd é um gerenciador de tarefas. A página de manual não é muito precisa sobre como as coisas funcionam.

Quando você inicializa, o que o systemd faz é criar uma transação composta por trabalhos para o trabalho âncora (por exemplo, iniciar trabalho para default.target). O que todas essas dependências e relacionamentos fazem é definir como e quais tarefas serão acionadas. A encomenda define em quais trabalhos todos os outros trabalhos aguardarão. Portanto, a unidade default.target está no centro de tudo isso, e é por isso que ao ativar as unidades, você usa uma dependência reversa que, através do systemctl enable, cria um link simbólico do sistema de arquivos que indica uma dependência direta que systemd pode seguir (também porque você precisa de links simbólicos do sistema de arquivos no diretório primeiro lugar). Semelhante é quando você inicia manualmente alguma unidade, essa unidade é âncora e a transação é calculada nela.

Não entrando em muitos detalhes, explicarei o que Requer = e Depois = faz.

Requer = fará com que o systemd inicie um trabalho inicial para a unidade necessária quando você iniciar um trabalho inicial (explicitamente ou através de uma dependência: não há distinção internamente). Ele também tem a propriedade de acionar um trabalho de interrupção em você quando esta unidade é parada (nota: parada, não diminuindo sozinha) ou reiniciada. Isso significa que, se alguma dependência / systemctl fizer com que ela pare / reinicie, você também irá parar / reiniciar. No entanto, se tudo der errado, você não irá parar, pois não havia emprego, e a mudança de estado aconteceu sem o envolvimento do systemd. É aqui que você usaria BindsTo = (semelhante às unidades de dispositivo, que podem ficar inativas sem o envolvimento do systemd, por razões óbvias).

Agora, o uso de After = é recomendado, pois Requer = sozinho é atrevido para o que faz: cancele o necessário se o trabalho inicial falhar. Esse cancelamento, no entanto, funciona apenas em trabalhos errados, ou seja, se a outra unidade não definir a ordem, o systemd será acionado em paralelo e se o trabalho inicial terminar antes que o trabalho inicial falhe, ele não será cancelado (na verdade, não pode ser cancelado) . O uso de Após = significa que outro trabalho fica aguardando até o trabalho inicial da unidade necessária terminar e, dependendo do resultado, se falhar, o trabalho inicial de 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 é indeterminado 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 por lá, não há corrida. Nesse caso, não passa de um mecanismo de sincronização.

Além disso, você também pode ativar ambos na inicialização, e não exigir um ao outro, e apenas definir a ordem, nesse caso, quando ambos forem puxados como parte da mesma transação, eles serão solicitados (ou se o trabalho para o outro for acionado enquanto o trabalho da unidade que deseja executar estiver em execução, ele primeiro esperará 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 trabalho, como conseqüência do uso de dependências como Requer = e Quer =, ou ambos são puxados de cada vez e definem algumas ordens; nesse caso, eles esperam no (s) trabalho (s) da outra unidade.

Jonathan Kowalski
fonte