V tomto článku se podíváme na to, jak spouštět vlastní shellové skripty po startu Linuxu se systemd a jak vytvářet vlastní systemd služby na systému Debian Linux.

Motivace:

  1. Potřebuji spouštět vlastní program na měření toku ethernotovými kartami, program má běžet od startu operačního systému neustále.

  2. Potřebuji po startu Linuxu nastavit wireguard VPN k jednotlivým zákazníkům a nechce se mi to pokaždé dělat ručně, vytvořím si na so službu.

Na většině Linuxových systémů s programem init [1] existuje něco jako /etc/rc.local, což je shellový skript, který se spouští při startu operačního systému (většinou jako poslední).

Poté, co byl na některých linuxových distribucích (Debian a jeho klony, Fedora, openSUSE …​ ) jednoduchý program init nahrazen složitým programem systemd, začalo být problematické spouštění vlastních skriptů po startu systému.

Program /sbin/init spustil všechno potřebné po startu podle tabulky /etc/inittab a veškerá konfigurace systému se dělala pomocí jednoduchých nebo složitých shellových skriptů, uložených většinou v /etc/rc.d/ adresáři.

Po nahrazení initu programem systemd byla zachována kompatibilita a bylo možné lokální skripty slouštět po startu z /etc/rc.local. Časem ale tato možnost na Debianu zmizela (verze 10.13 a vyšší ji již nemá) musíme si ji dodělat.

Kompatibilita /etc/rc.local je dosažená na systemd pomocí speciální služby zvané rc-local.service. Tato jednotka je automaticky volána do multi-user.target pomocí systemd-rc-local-generator, pokud je /etc/rc.local spustitelný soubor.

Spouštění vlastních skriptů po startu systému

Povolení skriptu /etc/rc.local shell na systemd při spouštění systému Linux uděláme takto:

Vytvoříme soubor /etc/rc.local pomocí textového editoru
#!/bin/bash

/usr/local/sbin/x86_64_mereni_ethernet -d 172.16.100.1 27002 (1)

exit 0 (2)
1 Tady je to, co potřebujeme spustit po startu operačního systému.
2 Důežité je, aby skript vracel návratovou hodnotu 0
Zajistíme, aby byl /etc/rc.local spustítelný
root@server:~# chmod +x /etc/rc.local
Vytvoříme službu rc-local.service
root@server:~# systemctl is-enabled rc-local.service
Spustíme službu rc-local.service
root@server:~# systemctl start rc-local.service
Můžeme se přesvědčit, v jakém je služba stavu
root@server:~# systemctl status rc-local.service
* rc-local.service - /etc/rc.local Compatibility
   Loaded: loaded (/lib/systemd/system/rc-local.service; enabled-runtime; vendor preset: enabled)
  Drop-In: /lib/systemd/system/rc-local.service.d
           `-debian.conf
   Active: active (running) since Tue 2023-08-08 07:53:17 UTC; 2s ago
     Docs: man:systemd-rc-local-generator(8)
  Process: 19847 ExecStart=/etc/rc.local start (code=exited, status=0/SUCCESS)
    Tasks: 1 (limit: 115904)
   Memory: 120.0K
      CPU: 4ms
   CGroup: /system.slice/rc-local.service
           `-19849 /usr/local/sbin/x86_64_mereni_ethernet -d 172.16.100.1 27002

Aug 08 07:53:17 server systemd[1]: Starting /etc/rc.local Compatibility...
Aug 08 07:53:17 server rc.local[19847]: mereni_ethernet v. 1.0.11 (c) LIXIS s.r.o. 2006-2023 <jirka@lixis.cz>.  All rights reserved.
Aug 08 07:53:17 server rc.local[19847]: Jiz bezim v jine instanci s PID 17239, tu jsem ukoncil.
Aug 08 07:53:17 server systemd[1]: Started /etc/rc.local Compatibility.

Vytvoření vlastní služby

Nastavení vlastní služby, která vytvoří nebo zruší několik VPN linek k zákazníkům. Je použit wireguard.

V textovém editoru vytvořím soubor /etc/systemd/system/wireguard.service

Vytvoření služby /etc/systemd/system/wireguard.service
[Unit]
Before=network.target
[Service]
Type=oneshot
# wireguard na kvm2.lixis.cz
ExecStart=/usr/bin/wg-quick up wg0 (1)
# wireguard na zakaznik 1
ExecStart=/usr/bin/wg-quick up wg3 (3)
# wireguard na zakaznik 2
ExecStart=/usr/bin/wg-quick up wg7
# wireguard na zakaznik 3
ExecStart=/usr/bin/wg-quick up wg9
# wireguard na zakaznik 4
ExecStart=/usr/bin/wg-quick up wg18
# wireguard na zakaznik 5
ExecStart=/usr/bin/wg-quick up wg16
# wireguard na zakaznik 6
ExecStart=/usr/bin/wg-quick up wg15

# kvm2.lixis.cz
ExecStop=/usr/bin/wg-quick down wg0 (2)
# zakaznik 1
ExecStop=/usr/bin/wg-quick down wg3 (4)
# zakaznik 2
ExecStop=/usr/bin/wg-quick down wg7
# zakaznik 3
ExecStop=/usr/bin/wg-quick down wg9
# zakaznik 4
ExecStop=/usr/bin/wg-quick down wg18
# zakaznik 5
ExecStop=/usr/bin/wg-quick down wg16
# zakaznik 6
ExecStop=/usr/bin/wg-quick down wg15

RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
1 Vytvoření a spuštění VPN linky na náš server kvm2.lixis.cz v datacentru. ExecStart
2 Shození VPN linky na náš server kvm2.lixis.cz v datacentru. ExecStop
3 Vytvoření a spuštění VPN linky k zákazníkovi č.1
4 Shození VPN linky zákazníkovi č. 1

A tak dále.

Nastavím, aby služba naběhla automaticky po startu systému
root@jirka-Precision-T3610:/etc/systemd/system# systemctl enable wireguard.service
Spustím službu wireguard.service
root@jirka-Precision-T3610:/etc/systemd/system# systemctl start wireguard.service
Přesvědčím se, v jakém stavu je služba
root@jirka-Precision-T3610:/etc/systemd/system# systemctl status wireguard.service
● wireguard.service
     Loaded: loaded (/etc/systemd/system/wireguard.service; enabled; vendor preset: enabled)
     Active: active (exited) since Tue 2023-08-08 10:21:49 CEST; 1min 0s ago
    Process: 10877 ExecStart=/usr/bin/wg-quick up wg0 (code=exited, status=0/SUCCESS)
    Process: 10930 ExecStart=/usr/bin/wg-quick up wg3 (code=exited, status=0/SUCCESS)
    Process: 10997 ExecStart=/usr/bin/wg-quick up wg7 (code=exited, status=0/SUCCESS)
    Process: 11054 ExecStart=/usr/bin/wg-quick up wg9 (code=exited, status=0/SUCCESS)
    Process: 11132 ExecStart=/usr/bin/wg-quick up wg18 (code=exited, status=0/SUCCESS)
    Process: 11193 ExecStart=/usr/bin/wg-quick up wg16 (code=exited, status=0/SUCCESS)
    Process: 11249 ExecStart=/usr/bin/wg-quick up wg15 (code=exited, status=0/SUCCESS)
   Main PID: 11249 (code=exited, status=0/SUCCESS)

srp 08 10:21:49 jirka-Precision-T3610 wg-quick[11193]: [#] ip -4 route add 192.168.4.0/24 dev wg16
srp 08 10:21:49 jirka-Precision-T3610 wg-quick[11249]: [#] ip link add wg15 type wireguard
srp 08 10:21:49 jirka-Precision-T3610 wg-quick[11249]: [#] wg setconf wg15 /dev/fd/63
srp 08 10:21:49 jirka-Precision-T3610 wg-quick[11249]: [#] ip -4 address add 10.11.20.2/32 dev wg15
srp 08 10:21:49 jirka-Precision-T3610 wg-quick[11249]: [#] ip link set mtu 1420 up dev wg15
srp 08 10:21:49 jirka-Precision-T3610 wg-quick[11249]: [#] ip -4 route add 10.11.20.1/32 dev wg15
srp 08 10:21:49 jirka-Precision-T3610 wg-quick[11249]: [#] ip -4 route add 192.168.3.0/24 dev wg15
srp 08 10:21:49 jirka-Precision-T3610 wg-quick[11249]: [#] ip -4 route add 192.168.114.0/24 dev wg15
srp 08 10:21:49 jirka-Precision-T3610 wg-quick[11249]: [#] ip -4 route add 192.168.111.0/24 dev wg15
srp 08 10:21:49 jirka-Precision-T3610 systemd[1]: Finished wireguard.service.

Je vidět, že naběhla správně.

Mohu se o tom přesvědčit i příkazem wg
root@jirka-Precision-T3610:/etc/systemd/system# wg
interface: wg0
  public key: hSOPr8FVK1iUxIBzn/MYvt9HifTo7/iR+rrkXvp+1BM=
  private key: (hidden)
  listening port: 59608

peer: ObeiDk0dVMf/JYvSTUj8fnWpMw7OmdE8NUq+fsNtbkw=
  endpoint: [2a0e:5340:1:8000::68]:28412
  allowed ips: 192.168.224.1/32, 192.168.224.0/24
  latest handshake: 11 seconds ago
  transfer: 184 B received, 520 B sent
  persistent keepalive: every 25 seconds

interface: wg3
  public key: ctVMDbjwxEKtRVLEPKdzXmzRz4D2SKpAzI/B1WhJv2Y=
  private key: (hidden)
  listening port: 36391

peer: KeYxiuT83sgn68arRGSeTgIksz8AXyrB+wJm8o16yTo=
  endpoint: 99.25.208.13:37421
  allowed ips: 192.168.1.0/24, 192.168.101.0/24, 10.0.0.0/24
  latest handshake: 11 seconds ago
  transfer: 184 B received, 520 B sent
  persistent keepalive: every 25 seconds

interface: wg7
  public key: vq/AvCDVXjS0mU1IArI8dIDSo/ir2uOP1hDEAsvVnTA=
  private key: (hidden)
  listening port: 43412

peer: TiF9HBmCm3lGCrWE2uH+BUl6yPqVtPf7lwQgfJGXfn4=
  endpoint: 48.231.71.141:13858
  allowed ips: 192.168.110.0/24
  latest handshake: 11 seconds ago
  transfer: 184 B received, 520 B sent
  persistent keepalive: every 25 seconds

interface: wg9
  public key: EkRGku53KgoEip2MMHQYk7CFDN8BpRuUHe6wwJKGxWU=
  private key: (hidden)
  listening port: 48848

peer: SAbicG0LTin6Jwui9Ktjd42kzk5RhBxRAdXcy+MFLGg=
  endpoint: 88.109.68.81:25364
  allowed ips: 10.12.23.1/32, 192.168.2.0/24, 192.168.22.0/24, 192.168.112.0/24
  latest handshake: 11 seconds ago
  transfer: 248 B received, 520 B sent
  persistent keepalive: every 25 seconds

interface: wg18
  public key: p+gR2VssWt6aw/9n5NUL7h1O3ke8aKtRkK6Q8j4YAXE=
  private key: (hidden)
  listening port: 32400

peer: Jeye51HCZGKyoGGc4poTWpo5nvyGQix0JdSAlDfktRo=
  endpoint: 181.123.211.89:28344
  allowed ips: 10.92.16.1/32, 10.10.1.0/24, 10.14.1.0/24
  latest handshake: 20 seconds ago
  transfer: 248 B received, 776 B sent
  persistent keepalive: every 10 seconds

interface: wg16
  public key: 0ot+kVo93MR4Xd3y16qp/NEJ2yUO/RgWUWTOPTyZV30=
  private key: (hidden)
  listening port: 46434

peer: BEmkW4hNRbHg2kHIj2vBs4kuGvnA2DeaQKCPjt+a/XM=
  endpoint: 92.231.218.121:34730
  allowed ips: 10.11.18.1/32, 192.168.4.0/24
  latest handshake: 11 seconds ago
  transfer: 248 B received, 520 B sent
  persistent keepalive: every 25 seconds

interface: wg15
  public key: 6jRW+mlUd3QfmfjWwvYgfHYZQd7f0TMDnk/HTeqN5j0=
  private key: (hidden)
  listening port: 34177

peer: 5sdSLZnbifvc5VqcgA5r9/VNawH8/BWfI+0RvrVlXQg=
  endpoint: 92.231.218.122:34731
  allowed ips: 10.11.20.1/32, 192.168.3.0/24, 192.168.111.0/24, 192.168.114.0/24
  latest handshake: 9 seconds ago
  transfer: 248 B received, 520 B sent
  persistent keepalive: every 25 seconds
root@jirka-Precision-T3610:/etc/systemd/system#
Zastavím službu wireguard.service a přesvědčím se o stavu
root@jirka-Precision-T3610:/etc/systemd/system# systemctl stop wireguard.service
root@jirka-Precision-T3610:/etc/systemd/system# systemctl status wireguard.service
● wireguard.service
     Loaded: loaded (/etc/systemd/system/wireguard.service; enabled; vendor preset: enabled)
     Active: inactive (dead) since Tue 2023-08-08 10:25:58 CEST; 37s ago
    Process: 10877 ExecStart=/usr/bin/wg-quick up wg0 (code=exited, status=0/SUCCESS)
    Process: 10930 ExecStart=/usr/bin/wg-quick up wg3 (code=exited, status=0/SUCCESS)
    Process: 10997 ExecStart=/usr/bin/wg-quick up wg7 (code=exited, status=0/SUCCESS)
    Process: 11054 ExecStart=/usr/bin/wg-quick up wg9 (code=exited, status=0/SUCCESS)
    Process: 11132 ExecStart=/usr/bin/wg-quick up wg18 (code=exited, status=0/SUCCESS)
    Process: 11193 ExecStart=/usr/bin/wg-quick up wg16 (code=exited, status=0/SUCCESS)
    Process: 11249 ExecStart=/usr/bin/wg-quick up wg15 (code=exited, status=0/SUCCESS)
    Process: 13115 ExecStop=/usr/bin/wg-quick down wg0 (code=exited, status=0/SUCCESS)
    Process: 13154 ExecStop=/usr/bin/wg-quick down wg3 (code=exited, status=0/SUCCESS)
    Process: 13176 ExecStop=/usr/bin/wg-quick down wg7 (code=exited, status=0/SUCCESS)
    Process: 13198 ExecStop=/usr/bin/wg-quick down wg9 (code=exited, status=0/SUCCESS)
    Process: 13220 ExecStop=/usr/bin/wg-quick down wg18 (code=exited, status=0/SUCCESS)
    Process: 13250 ExecStop=/usr/bin/wg-quick down wg16 (code=exited, status=0/SUCCESS)
    Process: 13272 ExecStop=/usr/bin/wg-quick down wg15 (code=exited, status=0/SUCCESS)
   Main PID: 11249 (code=exited, status=0/SUCCESS)

srp 08 10:25:56 jirka-Precision-T3610 systemd[1]: Stopping wireguard.service...
srp 08 10:25:56 jirka-Precision-T3610 wg-quick[13115]: [#] ip link delete dev wg0
srp 08 10:25:56 jirka-Precision-T3610 wg-quick[13154]: [#] ip link delete dev wg3
srp 08 10:25:56 jirka-Precision-T3610 wg-quick[13176]: [#] ip link delete dev wg7
srp 08 10:25:57 jirka-Precision-T3610 wg-quick[13198]: [#] ip link delete dev wg9
srp 08 10:25:57 jirka-Precision-T3610 wg-quick[13220]: [#] ip link delete dev wg18
srp 08 10:25:57 jirka-Precision-T3610 wg-quick[13250]: [#] ip link delete dev wg16
srp 08 10:25:57 jirka-Precision-T3610 wg-quick[13272]: [#] ip link delete dev wg15
srp 08 10:25:58 jirka-Precision-T3610 systemd[1]: wireguard.service: Succeeded.
srp 08 10:25:58 jirka-Precision-T3610 systemd[1]: Stopped wireguard.service.
Wireguard, všechna zařízení wgX zmizela, VPN jsou zrušené
root@jirka-Precision-T3610:/etc/systemd/system# wg
root@jirka-Precision-T3610:/etc/systemd/system#

Pokud bych chtěl odhalit vzniklé chyby při startu služby, tak mohu použít příkaz journalctl -xeu wireguard.service, což mi zobrazí log.

Poznámka na konec

Pokud pracuji jako administrátor, tak pracuji jako root, nemám rád sudo, protože vím, co dělám. Jste-li normální uživatel, budete muset před všechny příkazy psát sudo.

Většina návodů na internetu je právě se sudo <příkaz_který_může_dělat_jenom_root>

sudo a bez sudo

jirka@jirka-Precision-T3610:~/vyuka_sspvc$ sudo systemctl status wireguard.service (1)
[sudo] heslo pro jirka:
● wireguard.service
     Loaded: loaded (/etc/systemd/system/wireguard.service; enabled; vendor preset: enabled)
     Active: active (exited) since Tue 2023-08-08 10:29:00 CEST; 18min ago
    Process: 13337 ExecStart=/usr/bin/wg-quick up wg0 (code=exited, status=0/SUCCESS)
    Process: 13391 ExecStart=/usr/bin/wg-quick up wg3 (code=exited, status=0/SUCCESS)
    Process: 13463 ExecStart=/usr/bin/wg-quick up wg7 (code=exited, status=0/SUCCESS)
    Process: 13518 ExecStart=/usr/bin/wg-quick up wg9 (code=exited, status=0/SUCCESS)
    Process: 13593 ExecStart=/usr/bin/wg-quick up wg18 (code=exited, status=0/SUCCESS)
    Process: 13653 ExecStart=/usr/bin/wg-quick up wg16 (code=exited, status=0/SUCCESS)
    Process: 13714 ExecStart=/usr/bin/wg-quick up wg15 (code=exited, status=0/SUCCESS)
   Main PID: 13714 (code=exited, status=0/SUCCESS)

srp 08 10:29:00 jirka-Precision-T3610 wg-quick[13653]: [#] ip -4 route add 192.168.4.0/24 dev wg16
srp 08 10:29:00 jirka-Precision-T3610 wg-quick[13714]: [#] ip link add wg15 type wireguard
srp 08 10:29:00 jirka-Precision-T3610 wg-quick[13714]: [#] wg setconf wg15 /dev/fd/63
srp 08 10:29:00 jirka-Precision-T3610 wg-quick[13714]: [#] ip -4 address add 10.11.20.2/32 dev wg15
srp 08 10:29:00 jirka-Precision-T3610 wg-quick[13714]: [#] ip link set mtu 1420 up dev wg15
srp 08 10:29:00 jirka-Precision-T3610 wg-quick[13714]: [#] ip -4 route add 10.11.20.1/32 dev wg15
srp 08 10:29:00 jirka-Precision-T3610 wg-quick[13714]: [#] ip -4 route add 192.168.3.0/24 dev wg15
srp 08 10:29:00 jirka-Precision-T3610 wg-quick[13714]: [#] ip -4 route add 192.168.114.0/24 dev wg15
srp 08 10:29:00 jirka-Precision-T3610 wg-quick[13714]: [#] ip -4 route add 192.168.111.0/24 dev wg15
srp 08 10:29:00 jirka-Precision-T3610 systemd[1]: Finished wireguard.service.
jirka@jirka-Precision-T3610:~/vyuka_sspvc$ sudo su (2)
root@jirka-Precision-T3610:/home/jirka/vyuka_sspvc# systemctl start wireguard.service
root@jirka-Precision-T3610:/home/jirka/vyuka_sspvc# systemctl status wireguard.service
● wireguard.service
     Loaded: loaded (/etc/systemd/system/wireguard.service; enabled; vendor preset: enabled)
     Active: active (exited) since Tue 2023-08-08 10:29:00 CEST; 18min ago
    Process: 13337 ExecStart=/usr/bin/wg-quick up wg0 (code=exited, status=0/SUCCESS)
    Process: 13391 ExecStart=/usr/bin/wg-quick up wg3 (code=exited, status=0/SUCCESS)
    Process: 13463 ExecStart=/usr/bin/wg-quick up wg7 (code=exited, status=0/SUCCESS)
    Process: 13518 ExecStart=/usr/bin/wg-quick up wg9 (code=exited, status=0/SUCCESS)
    Process: 13593 ExecStart=/usr/bin/wg-quick up wg18 (code=exited, status=0/SUCCESS)
    Process: 13653 ExecStart=/usr/bin/wg-quick up wg16 (code=exited, status=0/SUCCESS)
    Process: 13714 ExecStart=/usr/bin/wg-quick up wg15 (code=exited, status=0/SUCCESS)
   Main PID: 13714 (code=exited, status=0/SUCCESS)

srp 08 10:29:00 jirka-Precision-T3610 wg-quick[13653]: [#] ip -4 route add 192.168.4.0/24 dev wg16
srp 08 10:29:00 jirka-Precision-T3610 wg-quick[13714]: [#] ip link add wg15 type wireguard
srp 08 10:29:00 jirka-Precision-T3610 wg-quick[13714]: [#] wg setconf wg15 /dev/fd/63
srp 08 10:29:00 jirka-Precision-T3610 wg-quick[13714]: [#] ip -4 address add 10.11.20.2/32 dev wg15
srp 08 10:29:00 jirka-Precision-T3610 wg-quick[13714]: [#] ip link set mtu 1420 up dev wg15
srp 08 10:29:00 jirka-Precision-T3610 wg-quick[13714]: [#] ip -4 route add 10.11.20.1/32 dev wg15
srp 08 10:29:00 jirka-Precision-T3610 wg-quick[13714]: [#] ip -4 route add 192.168.3.0/24 dev wg15
srp 08 10:29:00 jirka-Precision-T3610 wg-quick[13714]: [#] ip -4 route add 192.168.114.0/24 dev wg15
srp 08 10:29:00 jirka-Precision-T3610 wg-quick[13714]: [#] ip -4 route add 192.168.111.0/24 dev wg15
srp 08 10:29:00 jirka-Precision-T3610 systemd[1]: Finished wireguard.service.
root@jirka-Precision-T3610:/home/jirka/vyuka_sspvc#
root@jirka-Precision-T3610:/home/jirka/vyuka_sspvc# exit (3)
jirka@jirka-Precision-T3610:~/vyuka_sspvc$
jirka@jirka-Precision-T3610:~/vyuka_sspvc$ ./prac.sh (4)
sending incremental file list
index.html
operacni_systemy/index.html
operacni_systemy/navody/
operacni_systemy/navody/systemd-vlastni-sluzba.adoc
operacni_systemy/navody/systemd-vlastni-sluzba.html

sent 50,641 bytes  received 1,516 bytes  104,314.00 bytes/sec
total size is 1,048,181,345  speedup is 20,096.66
jirka@jirka-Precision-T3610:~/vyuka_sspvc$
1 Tady jsem obyčejný uživatel, musím psát sudo.
2 Tady budu rootem a sudo už psát nebudu. Vím, co dělám. sudo su mi to zajistí.
3 Odteď jsem zase obyčejným uživatelem.
4 Takto překládám a posílám tento článek na webserver.

Zdroje a odkazy


1. /sbin/init je uživatelský program, který spouští jádro linuxu jako první.