Como substituir ou configurar serviços systemd?

109

Muitos scripts sysv init usavam um arquivo correspondente /etc/defaultpara permitir que o administrador o configurasse. Trabalhos iniciados podem ser modificados usando .overridearquivos. Como substituir ou configurar unidades systemd, agora que systemd é o padrão no Ubuntu?

muru
fonte
Observe que, ao limpar a ExecStart=entrada com um espaço em branco, você não pode colocar um comentário depois da seguinte forma: ExecStart= # Empty line to clear previous entries.Isso será tomado como outra ExecStart=entrada e adicionado à lista. PS. Não pude comentar a resposta de muru por causa de minha baixa reputação.
tysik 23/08

Respostas:

185

systemdas unidades não precisam obedecer aos arquivos /etc/default. systemdé facilmente configurável, mas requer que você conheça a sintaxe dos arquivos da unidade systemd.

Os pacotes enviam arquivos de unidade normalmente /lib/systemd/system/. Estes não devem ser editados. Em vez disso, systemdpermite substituir esses arquivos criando arquivos apropriados no /etc/systemd/system/.

Para um determinado serviço foo, o pacote forneceria /lib/systemd/system/foo.service. Você pode verificar seu status usando systemctl status fooou visualizar seus logs usando journalctl -u foo. Para substituir algo na definição de foo, faça:

sudo systemctl edit foo

Isso cria um diretório com o /etc/systemd/systemnome da unidade e um override.confarquivo nesse diretório ( /etc/systemd/system/foo.service.d/override.conf). Você pode adicionar ou substituir configurações usando este arquivo (ou outros .confarquivos /etc/systemd/system/foo.service.d/).

Substituindo argumentos de comando

Veja o gettyserviço, por exemplo. Digamos que eu queira ter o logon TTY2 automático para meu usuário (isso não é aconselhável, mas apenas um exemplo). O TTY2 é executado pelo getty@tty2serviço ( tty2sendo uma instância do modelo /lib/systemd/system/getty@service). Para fazer isso, eu tenho que modificar o getty@tty2serviço.

$ systemctl cat getty@tty2
# /lib/systemd/system/[email protected]
#  This file is part of systemd.
#
#  systemd is free software; you can redistribute it and/or modify it
#  under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation; either version 2.1 of the License, or
#  (at your option) any later version.

[Unit]
Description=Getty on %I
Documentation=man:agetty(8) man:systemd-getty-generator(8)
Documentation=http://0pointer.de/blog/projects/serial-console.html
After=systemd-user-sessions.service plymouth-quit-wait.service
After=rc-local.service

# If additional gettys are spawned during boot then we should make
# sure that this is synchronized before getty.target, even though
# getty.target didn't actually pull it in.
Before=getty.target
IgnoreOnIsolate=yes

# On systems without virtual consoles, don't start any getty. Note
# that serial gettys are covered by [email protected], not this
# unit.
ConditionPathExists=/dev/tty0

[Service]
# the VT is cleared by TTYVTDisallocate
ExecStart=-/sbin/agetty --noclear %I $TERM
Type=idle
Restart=always
RestartSec=0
UtmpIdentifier=%I
TTYPath=/dev/%I
TTYReset=yes
TTYVHangup=yes
TTYVTDisallocate=yes
KillMode=process
IgnoreSIGPIPE=no
SendSIGHUP=yes

# Unset locale for the console getty since the console has problems
# displaying some internationalized messages.
Environment=LANG= LANGUAGE= LC_CTYPE= LC_NUMERIC= LC_TIME= LC_COLLATE= LC_MONETARY= LC_MESSAGES= LC_PAPER= LC_NAME= LC_ADDRESS= LC_TELEPHONE= LC_MEASUREMENT= LC_IDENTIFICATION=

[Install]
WantedBy=getty.target
DefaultInstance=tty1

Em particular, eu tenho que mudar a ExecStartlinha, que atualmente é:

$ systemctl cat getty@tty2 | grep Exec     
ExecStart=-/sbin/agetty --noclear %I $TERM

Para substituir isso, faça:

sudo systemctl edit getty@tty2

E adicione:

[Service]
ExecStart=
ExecStart=-/sbin/agetty -a muru --noclear %I $TERM

Observe que:

  1. Eu tinha que explicitamente claro ExecStartantes de defini-lo novamente, já que é um cenário aditivo, semelhante a After, Environment(como um todo, não per-variável) e EnvironmentFile, e oposição a substituição de configurações de como RestartSecou Type. ExecStartpode ter várias entradas apenas para Type=oneshotserviços.
  2. Eu tive que usar o cabeçalho de seção apropriado. No arquivo original, ExecStartestá na [Service]seção, então minha substituição também deve ser incluída ExecStartna [Service]seção. Muitas vezes, ver o arquivo de serviço real usando systemctl catindica o que você precisa substituir e em qual seção ele está.

Geralmente, se você editar um arquivo de unidade systemd, para que ele entre em vigor, será necessário executar:

sudo systemctl daemon-reload

No entanto, systemctl editisso é feito automaticamente por você.

Agora:

$ systemctl cat getty@tty2 | grep Exec
ExecStart=-/sbin/agetty --noclear %I $TERM
ExecStart=
ExecStart=-/sbin/agetty -a muru --noclear %I $TERM

$ systemctl show getty@tty2 | grep ExecS
ExecStart={ path=/sbin/agetty ; argv[]=/sbin/agetty -a muru --noclear %I $TERM ; ... }

E se eu fizer:

sudo systemctl restart getty@tty2

e pressione CtrlAltF2, pronto! Vou entrar na minha conta nesse TTY.

Como eu disse antes, getty@tty2é uma instância de um modelo. Então, e se eu quisesse substituir todas as instâncias desse modelo? Isso pode ser feito editando o próprio modelo (removendo o identificador da instância - neste caso tty2):

systemctl edit getty@

Substituindo o ambiente

Um caso de uso comum de /etc/defaultarquivos é definir variáveis ​​de ambiente. Geralmente, /etc/defaulté um script de shell, então você pode usar construções de linguagem de shell nele. Com systemd, no entanto, este não é o caso. Você pode especificar variáveis ​​de ambiente de duas maneiras:

Via um arquivo

Digamos que você configurou as variáveis ​​de ambiente em um arquivo:

$ cat /path/to/some/file
FOO=bar

Em seguida, você pode adicionar à substituição:

[Service]
EnvironmentFile=/path/to/some/file

Em particular, se o seu /etc/default/grubcontiver apenas atribuições e nenhuma sintaxe do shell, você poderá usá-lo como o EnvironmentFile.

Via Environmententradas

O procedimento acima também pode ser realizado usando a seguinte substituição:

[Service]
Environment=FOO=bar

No entanto, isso pode ser complicado com várias variáveis, espaços etc. Veja uma das minhas outras respostas para um exemplo de uma instância desse tipo.

Leitura adicional

Por meio desse mecanismo, fica muito fácil substituir systemdunidades e desfazer essas alterações (simplesmente removendo o arquivo de substituição). Essas não são as únicas configurações que podem ser modificadas.

Os seguintes links seriam úteis:

muru
fonte
1
Você precisa limpar a variável antes de configurá-la para serviços que não sejam do tipo oneshot. Isso resolveu meu problema.
Colin
3
@MarkEdington na página de systemd.service(5)manual, seção sobre ExecStart: "A menos que Type = oneshot, seja necessário exatamente um comando. Quando Type = oneshot é usado, zero ou mais comandos podem ser especificados. Comandos podem ser especificados fornecendo várias linhas de comando na mesma diretiva ou, alternativamente, esta diretiva pode ser especificada mais de uma vez com o mesmo efeito. Se a sequência vazia for atribuída a esta opção, a lista de comandos a ser iniciada será redefinida, as atribuições anteriores dessa opção não terão efeito. "
muru 31/08/19
1
@Orient, você pode sudo rmsubstituir o arquivo e systemctl daemon-reload, em seguida , systemctl editsubstituir todos os itens da substituição por comentários. Os comentários nos arquivos de serviço começam com #.
Muru
3
@Orientsystemctl revert foo
Ayell 16/04
1
Qual é a ordem de precedência para os três métodos (arquivo de substituição, arquivo de ambiente, variável de ambiente)? Ou seja, para uma variável definida nos três, qual será o valor efetivo?
Nikolaos Kakouros 16/06