Como gravar um arquivo .service systemd executando systemd-tmpfiles

16

Eu preciso executar systemd-tmpfiles --createdurante o processo de inicialização com uma distribuição systemd. Então, eu preciso criar um arquivo .service systemd fazendo esse trabalho.

Nesta pergunta, você pode ler todos os detalhes sobre o que eu preciso e por quê: Como o systemd-tmpfiles funciona?

Li alguns documentos e estou escrevendo o seguinte teste:

[Unit]
Description=Execute tmpfiles to disable usb-wakeup # see details in the link above
Requires=multi-user.target # see details in the link above
After=multi-user.target    # see details in the link above

[Service]
Type=oneshot
ExecStart=/usr/bin/systemd-tmpfiles --create

[Install]
WantedBy=multi-user.target

Mas não tenho certeza, porque systemd-tmpfilesnão é um programa simples, mas um pedaço do próprio systemd. Eu não gostaria de quebrar meu sistema.

Alguma dica sobre um arquivo .service correto?

eang
fonte
Verifique a documentação abundante no systemd em freedesktop.org/wiki/Software/systemd . Você pode substituir os padrões do sistema por seus próprios arquivos.
vonbrand

Respostas:

30

[Isso não aborda diretamente a questão dos systemd-tmpfiles, mas acho que você já reconheceu que, nesse caso em particular, é melhor usar echo.]

Primeiro, "multi-user.target" pode ou não ser o que você deseja usar. Se você está familiarizado com o conceito de níveis de execução do material init do estilo SysV, multiusuário é o equivalente do sistema ao nível de execução 3, que é um sistema multiusuário que inicializa em um console, não em uma GUI. O equivalente ao nível de execução 5, inicializado no X, é graphical.target . O padrão é determinado por um link simbólico em /etc/systemd/system(e / ou /lib/systemd/system; aquele /etcque substituirá o que está dentro /lib) chamado default.target , use ls para descobrir onde aponta:

»ls -l /etc/systemd/system/default.target
default.target -> /usr/lib/systemd/system/multi-user.target

Para desktops linux normais, isso será graphical.target. Na verdade, isso não é importante se você deseja que o serviço de inicialização que você está criando inicie, independentemente do nível de execução / destino padrão - nesse caso, podemos apenas usar default.target e não se preocupar com o que é um alias. Se você usa multiusuário, no entanto, e seu padrão é gráfico, seu serviço não acontecerá.

Dependendo do serviço, pode haver destinos ou serviços mais apropriados e específicos aos quais você deseja iniciar este em relação. Com base na sua outra pergunta, o default.target provavelmente está bom. Como observação, a diferença entre um "destino" e um "serviço" é que um serviço contém uma [Service]seção que realmente executa um processo; um destino é apenas uma maneira de agrupar serviços por meio das várias diretivas "depende" e "requer"; não faz nada por si próprio além de disparar outros alvos ou serviços.

Quando um serviço é iniciado, é determinado pelo que outros serviços explicitamente dependem dele. No caso de um evento simples e autônomo como este, que queremos executar mais tarde no processo de inicialização, podemos usar esta combinação de diretivas:

[Unit]
After=default.target

[Install]
WantedBy=default.target

A seção "Instalar" é usada quando o serviço é instalado; "WantedBy" especifica um destino com o qual queremos que este serviço seja incluído (o que significa que ele será executado se esse destino for, mas, nb. Isso não determina quando será executado em relação a outros ). Como na verdade queremos que esse serviço seja executado mais tarde do que antes, especificamos uma cláusula "Depois". Na verdade, isso não precisa ser o mesmo que o destino WantedBy (geralmente não é) e pode ser completamente omitido se você não se importar quando isso acontece; Estou usando apenas o pressentimento de que a maioria das outras coisas será executada em relação a coisas que estão em algum lugar acorrentadas a algo que foi especificado Before=default.target(o que também poderíamos ter usado; as necessidades de um alvo são avaliadas antes que o alvo seja executado).

Por exemplo, apenas ecoarei "olá mundo" para o console. O serviço em si é descrito na [Service]seção:

[Service]
Type=forking
ExecStart=/usr/local/bin/helloworld

O comando precisa de um caminho completo. A razão pela qual eu não usei apenas /usr/bin/echo "hello world"é que ele não funcionará (a saída vai para / dev / null, eu acho) e, enquanto um serviço faz um echo "hello world" > /dev/consoletestamento, a experimentação demonstra que o uso do redirecionamento de shell em uma diretiva ExecStart não funciona. . Então / usr / local / bin / helloworld é um script de shell com essa linha echo "hello world" > /dev/console,.

Observe o Type=forkingque é necessário para um script de shell.

Nossa, arquivo de serviço mínimo completo é apenas essas três seções ( [Unit], [Service], e [Install]). Para instalar, coloque o arquivo ou um link simbólico para ele / etc / systemd / system ou / usr / lib / systemd / system e:

systemctl --system enable helloworld

Deve imprimir ln -s .... Isso não executa o serviço, apenas o configura para ser executado na inicialização, conforme discutido acima.

É isso em poucas palavras. man systemd.unite man systemd.servicetenha mais detalhes.

Cachinhos Dourados
fonte
11
Obrigado, resposta muito útil e problema resolvido. Apenas uma nota, na minha distro (Chakra Linux) default.targetnão está na /etc/systemd/system, mas é apenas em/usr/lib/systemd/system
Eang
A saída dos comandos é registrada (para onde mais poderia ir)?
vonbrand
O diretório / usr / lib / systemd / ... arquivos são fallback (padrão), você é suposto a cair seu em / etc / systemd / ...
vonbrand
Estes dias default.targetpodem ser encontrados em/lib/systemd/system/default.target
czerasz
11
@czerasz Eu noto no Fedora 27, se eu systemctl set-default ...deixar um link simbólico /etc/systemd/system, mas ele não muda aquele /lib, ou seja, eles apontam para diferentes alvos, mas as coisas no primeiro devem substituir o último. Se você mesmo configurou, é isso que pode acontecer. Enfim, editei nos dois locais.
goldilocks
2

Para o serviço systemd-tmpfiles: ele deve ser enviado com sua distribuição, mas você sempre pode obter o arquivo de serviço do repositório git upstream

SimonPe
fonte