Como escrever um arquivo systemd .service executando systemd-tmpfiles

16

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

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

Eu li alguns documentos sobre isso 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-tmpfiles não é um programa simples, mas uma parte do próprio systemd. Eu não gostaria de quebrar meu sistema.

Alguma dica sobre um arquivo de serviço correto?

    
por eang 15.01.2013 / 18:28

2 respostas

27

[Isto não trata diretamente do problema de systemd-tmpfiles mas eu acho que você já reconheceu que neste caso em particular você está melhor apenas usando echo.]

Primeiro, "multi-user.target" pode ou não ser o que você deseja usar. Se você estiver familiarizado com o conceito de runlevels do tipo SysV init, o multiusuário é o equivalente do runlevel 3, que é um sistema multiusuário que inicializa em um console, não em uma GUI. O equivalente do nível de execução 5, que é inicializado em X, é graphical.target . O padrão é determinado por um symlink em /etc/systemd/system (e / ou /lib/systemd/system ; o em /etc irá anular o em /lib ) chamado default.target , use ls para localizar onde aponta:

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

Para os desktops linux normais, isso será graphical.target. Na verdade, isso não é importante se você quiser que o serviço de inicialização que você está criando seja iniciado independentemente do nível de execução / destino padrão - nesse caso, podemos 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 alvos ou serviços mais apropriados e específicos com os quais você deseja iniciar este. Com base na sua outra pergunta, default.target provavelmente está bem. Como observação, a diferença entre um "destino" e um "serviço" é que um serviço contém uma seção [Service] que, na verdade, executa um processo; uma meta é apenas uma maneira de agrupar serviços por meio das várias diretivas "depende" e "exige"; ele não faz nada próprio além de acionar outros alvos ou serviços.

Quando um serviço é iniciado é determinado por outros serviços que dependem explicitamente dele. No caso de um evento simples e independente como esse que queremos executar atrasado no processo de inicialização, podemos usar essa combinação de diretivas:

[Unit]
After=default.target

[Install]
WantedBy=default.target

A seção "Install" é usada quando o serviço é instalado; "WantedBy" especifica um alvo no qual queremos que este serviço seja incluído (o que significa que ele será executado se o destino o fizer, mas nb. isso não determina quando ele será executado em relação aos outros ). Como na verdade queremos que esse serviço seja executado mais tarde, em vez de mais cedo, então especificamos uma cláusula "Depois". Na verdade, isso não precisa ser o mesmo que o alvo do WantedBy (geralmente não é) e pode ser completamente omitido se você não se importar quando isso acontece; Eu só estou usando isso no palpite de que a maioria das outras coisas serão executadas em relação a coisas que estão em algum lugar acorrentado a algo que tenha especificado Before=default.target (que também poderíamos ter usado; os desejos de um alvo são avaliados antes que o alvo seja executado ).

Para o exemplo, vou apenas ecoar "hello world" para o console. O serviço em si é descrito na seção [Service] :

[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, acho), e enquanto um serviço que faz um echo "hello world" > /dev/console , a experimentação demonstra que usar o redirecionamento de shell em uma diretiva ExecStart não. Então / usr / local / bin / helloworld é um script de shell com essa linha, echo "hello world" > /dev/console .

Observe o Type=forking , que é necessário para um script de shell.

Nosso arquivo completo e mínimo de serviço é apenas essas três seções ( [Unit] , [Service] e [Install] ). Para instalar, coloque o arquivo ou um link simbólico em / 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.unit e man systemd.service têm mais detalhes.

    
por 15.01.2013 / 21:39
2

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

    
por 28.03.2013 / 16:31