Bagaimana cara mengganti atau mengkonfigurasi layanan systemd?

109

Banyak skrip init sysv menggunakan file yang sesuai /etc/defaultuntuk memungkinkan administrator untuk mengkonfigurasinya. Pekerjaan pemula dapat dimodifikasi menggunakan .overridefile. Bagaimana cara menimpa atau mengkonfigurasi unit systemd, sekarang systemd adalah default di Ubuntu?

muru
sumber
Perhatikan bahwa ketika menghapus ExecStart=entri kosong Anda tidak dapat memberikan komentar setelahnya seperti: ExecStart= # Empty line to clear previous entries.Ini akan diambil sebagai ExecStart=entri lain dan ditambahkan ke daftar. PS. Saya tidak bisa menambahkan komentar pada jawaban muru karena reputasi saya yang rendah.
tysik

Jawaban:

185

systemdunit tidak perlu mematuhi file di /etc/default. systemdmudah dikonfigurasi, tetapi mengharuskan Anda tahu sintaks file unit systemd.

Paket mengirimkan file unit biasanya di /lib/systemd/system/. Ini tidak boleh diedit. Sebagai gantinya, systemdAnda dapat mengganti file-file ini dengan membuat file yang sesuai di /etc/systemd/system/.

Untuk layanan yang diberikan foo, paket akan menyediakan /lib/systemd/system/foo.service. Anda dapat memeriksa statusnya menggunakan systemctl status foo, atau melihat log menggunakan journalctl -u foo. Untuk mengganti sesuatu dalam definisi foo, lakukan:

sudo systemctl edit foo

Ini membuat direktori dengan /etc/systemd/systemnama setelah unit, dan override.conffile dalam direktori itu ( /etc/systemd/system/foo.service.d/override.conf). Anda dapat menambah atau mengabaikan pengaturan menggunakan file ini (atau .conffile lain di /etc/systemd/system/foo.service.d/).

Mengganti argumen perintah

Ambil gettylayanan misalnya. Katakanlah saya ingin memiliki TTY2 autologin kepada pengguna saya (ini tidak disarankan, tetapi hanya sebuah contoh). TTY2 dijalankan oleh getty@tty2layanan ( tty2menjadi contoh dari templat /lib/systemd/system/getty@service). Untuk melakukan ini, saya harus memodifikasi getty@tty2layanan.

$ 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

Secara khusus, saya harus mengubah ExecStartjalur, yang saat ini adalah:

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

Untuk mengesampingkan ini, lakukan:

sudo systemctl edit getty@tty2

Dan tambahkan:

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

Perhatikan bahwa:

  1. Saya harus menghapus secara eksplisit ExecStartsebelum mengaturnya lagi, karena ini merupakan pengaturan tambahan, mirip dengan After, Environment(secara keseluruhan, bukan per-variabel) dan EnvironmentFile, dan menentang pengaturan utama seperti RestartSecatau Type. ExecStartdapat memiliki beberapa entri hanya untuk Type=oneshotlayanan.
  2. Saya harus menggunakan header bagian yang tepat. Di file asli, ExecStartada di [Service]bagian, jadi penggantian saya harus dimasukkan ExecStartke [Service]bagian juga. Seringkali, melihat file layanan yang sebenarnya menggunakan systemctl catakan memberi tahu Anda apa yang perlu Anda timpa dan di bagian mana.

Biasanya, jika Anda mengedit file unit systemd, agar bisa berlaku, Anda perlu menjalankan:

sudo systemctl daemon-reload

Namun, systemctl editsecara otomatis melakukan ini untuk Anda.

Sekarang:

$ 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 ; ... }

Dan jika saya melakukannya:

sudo systemctl restart getty@tty2

dan tekan CtrlAltF2, presto! Saya akan masuk ke akun saya di TTY itu.

Seperti yang saya katakan sebelumnya, getty@tty2adalah contoh dari sebuah template. Jadi, bagaimana jika saya ingin mengganti semua contoh template itu? Itu dapat dilakukan dengan mengedit templat itu sendiri (menghapus pengidentifikasi contoh - dalam kasus ini tty2):

systemctl edit getty@

Mengesampingkan lingkungan

Kasus penggunaan umum /etc/defaultfile adalah pengaturan variabel lingkungan. Biasanya, /etc/defaultini adalah skrip shell, jadi Anda bisa menggunakan konstruksi bahasa shell di dalamnya. Dengan systemd, bagaimanapun, ini tidak terjadi. Anda dapat menentukan variabel lingkungan dengan dua cara:

Melalui file

Katakanlah Anda telah menetapkan variabel lingkungan dalam file:

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

Kemudian, Anda dapat menambahkan ke override:

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

Secara khusus, jika Anda /etc/default/grubhanya berisi tugas dan tidak ada sintaks shell, Anda dapat menggunakannya sebagai EnvironmentFile.

Melalui Environmententri

Hal di atas juga dapat dilakukan dengan menggunakan penggantian berikut:

[Service]
Environment=FOO=bar

Namun, ini bisa menjadi rumit dengan beberapa variabel, spasi, dll. Lihatlah salah satu jawaban saya yang lain untuk contoh dari contoh seperti itu.

Bacaan lebih lanjut

Melalui mekanisme ini, menjadi sangat mudah untuk menimpa systemdunit, serta membatalkan perubahan tersebut (hanya dengan menghapus file override). Ini bukan satu-satunya pengaturan yang dapat dimodifikasi.

Tautan berikut akan bermanfaat:

muru
sumber
1
Anda harus menghapus variabel sebelum mengaturnya untuk layanan yang bukan dari jenis oneshot. Ini menyelesaikan masalah saya.
Colin
3
@ MarkEdington dari systemd.service(5)manual, bagian pada ExecStart: "Kecuali Type = oneshot, tepat satu perintah harus diberikan. Ketika Type = oneshot digunakan, nol atau lebih perintah dapat ditentukan. Perintah dapat ditentukan dengan menyediakan beberapa baris perintah di sama arahan, atau alternatifnya, arahan ini dapat ditentukan lebih dari sekali dengan efek yang sama. Jika string kosong ditetapkan untuk opsi ini, daftar perintah untuk memulai diatur ulang, penugasan sebelumnya dari opsi ini tidak akan berpengaruh. "
muru
1
@Orient Anda dapat sudo rmmenimpa file lalu systemctl daemon-reload, atau Anda dapat systemctl editdan mengganti semua yang di override dengan komentar. Komentar dalam file layanan dimulai dengan #.
muru
3
@Orientsystemctl revert foo
Ayell
1
Apa urutan prioritas untuk tiga metode (menimpa file, file lingkungan, variabel lingkungan)? Yaitu, untuk variabel yang didefinisikan dalam ketiganya, nilai mana yang akan efektif?
Nikolaos Kakouros