systemd

最後更新: 2023-10-04

目錄

 


Status

 

systemctl status httpd

...
 Main PID: 9376 (httpd)
   Status: "Total requests: 321; Current requests/sec: -2.44; Current traffic:   0 B/sec"
   CGroup: /system.slice/httpd.service
           ├─9376 /usr/sbin/httpd -DFOREGROUND
           ...
...

The "-DFOREGROUND" option does indeed mean that Apache won't fork,

    but that doesn't mean that it's attached to your shell!

The service is started by systemd when you run "systemctl start httpd"

It is systemd to which Apache is attached, and systemd is managing the process as one of its children.

This is done so that systemd can easily tell whether Apache has crashed,

    without having to poll a pid file or do other nasty hackery.

This also means that systemd is capable of automatically restarting Apache if it does crash.

Systemd is designed to run processes "in the foreground",

    that is, they don't have to specifically run themselves as daemons. 

The processes don't exactly run in the foreground,

    they run under systemd and it captures their input and output, but from the process's perspective,

   it is the same as running in the foreground.  That is systemd's preferred method of operation,

   but it does have compatibility with traditional daemons.

 


systemctl

 

Help

-h, --help

Version

--version

systemd 219
+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP
 +GCRYPT +GNUTLS +ACL +XZ -LZ4 -SECCOMP +BLKID +ELFUTILS +KMOD +IDN

Suport systemctl 的 Service 會有

/usr/lib/systemd/system/XXXX.service

Check status

systemctl status httpd

i.e. output

● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
   Active: active (running) since Thu 2018-04-12 18:09:26 HKT; 22h ago
     Docs: man:httpd(8)
           man:apachectl(8)
 Main PID: 24686 (httpd)
   Status: "Total requests: 216; Current requests/sec: 0; Current traffic:   0 B/sec"
   CGroup: /system.slice/httpd.service
           ├─24686 /usr/sbin/httpd -DFOREGROUND
           ├─24687 /usr/sbin/httpd -DFOREGROUND
...

Stop service:

systemctl stop httpd

Enable / Disable Service

systemctl disable httpd

systemctl enable httpd [--now]    # enable 同時 start

# check an service on / off

systemctl is-enabled httpd

# list running unit

# List known units. 相當於 "chkconfig –list"

systemctl list-units [PATTERN...]

 * list-units 是 systemctl 的 default command

( 所以當執行 systemctl 沒有加任何參數時, 就是這個 )

# to see inactive units too

systemctl --all

  UNIT                               LOAD      ACTIVE   SUB       DESCRIPTION
  ...
  dev-mqueue.mount                   loaded    active   mounted   POSIX Message Queue File System
  proc-sys-fs-binfmt_misc.mount      loaded    inactive dead      Arbitrary Executable File Formats File System

# '-t' subject to limitations specified with -t

# -t -type        # unit types: service and socket

systemctl [-t type]

Note:

"chkconfig --list" This output shows SysV services only and does not include native systemd services.

i.e.

systemctl -t service

mysqld.service       loaded active running   MySQL Server
vsftpd.service       loaded active running   Vsftpd ftp daemon
...

# list unit file ( 相當於 /usr/lib/systemd/system 內的檔案 )

# List installed unit files and their enablement state

# Usage: list-unit-files [PATTERN...]

systemctl list-unit-files

i.e. output

UNIT FILE                                   STATE
...
mysqld.service                              enabled
[email protected]                             disabled
...

找 enable 了的 Service

systemctl list-unit-files | grep enabled

 


修改 Unit File

 

跟 Package 來的 Default unit file 在 /usr/lib/systemd/system/????.service

一般而言, 建議修改過的 unit file 放在 "/etc/systemd/system/????.service.d/foo.conf"

which will be parsed after the file mariadb.service itself is parsed

i.e.

ls /usr/lib/systemd/system/mariadb.service

mkdir /etc/systemd/system/mariadb.service.d

/etc/systemd/system/mariadb.service.d/limits.conf

[Service]
LimitNOFILE=6144
LimitNPROC=6144

systemctl daemon-reload

systemctl restart mariadb

 


Unit File

 

系統的 Unit file 係存放在 /etc/systemd/system 下

它們會 soft link 到 /lib/systemd/system

i.e.

ls -l /etc/systemd/system

sshd.service -> /lib/systemd/system/ssh.service
inetd.service -> /dev/null

link 到 "/dev/null" 代表停(mask)用它

Setting

seafile.service

[Unit]
Description=Seafile
After=network.target mariadb.service

[Service]
Type=oneshot
ExecStart=/home/seafile/seafile-server-latest/seafile.sh start
ExecStop=/home/seafile/seafile-server-latest/seafile.sh stop
RemainAfterExit=yes
User=seafile
Group=seafile

[Install]
WantedBy=multi-user.target

Type

simple (default) – starts the service immediately.

It is expected that the main process of the service is defined in ExecStart.

notify - 與 systemd-notify 有關

systemd will automatically set up a communication socket back to systemd and

    will export its path to the service under $NOTIFY_SOCKET.

This indicates that the service will issue a notification when it has finished starting up.

The systemd process will wait for this to happen before proceeding to other units.

forking

forks a child process, exiting the parent process almost immediately.

This tells systemd that the process is still running even though the parent exited.

Environment Variable

ExecStart 及 ExecStop 的 Path 唔用得 variable

${FOOBAR} expands the variable into one word

$FOOBAR splits up the variable value at whitespace into multiple words

Environment="String"

space-separated list of variable assignments

The "$" character has no special meaning

i.e.

Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6"
#                OR
Environment="SECRET=a"
Environment="ANOTHER_SECRET=b"

EnvironmentFile=/Path/To/File

File

* lines without an "=" separator, or lines starting with ; or # will be ignored

* A line ending with a backslash will be concatenated with the following one

* If the empty string is assigned to this option, the list of file to read is reset

* later setting will override the earlier setting)

 * The "-" on the EnvironmentFile= line ensures that no error messages is generated
    if the environment file does not exist.

[Service]
EnvironmentFile=-/etc/environment

Usage

File

MY_VAR=123

Call

${MY_VAR}

# 修改完 unit file 後要 reload systemd daemon

# reload all unit files, and recreate the entire dependency tree.

# While the daemon is being reloaded, all sockets systemd listens on behalf of user configuration will stay accessible.

systemctl daemon-reload         # systemd to reload the configuration file of a unit

有 "@" 號的 Unit

mysqld.service

/usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid $MYSQLD_OPTS

[email protected]

ExecStart=/usr/sbin/mysqld --defaults-group-suffix=@%I --daemonize --pid-file=/var/run/mysqld/mysqld-%i.pid $MYSQLD_OPTS

--defaults-group-suffix=str

mysql opts

Read not only the usual option groups, but also groups with the usual names and a suffix of "str"

normally reads:

[mysql]

--defaults-group-suffix=_other

also reads the

[mysql_other]

Flow Control

 ("!"), the test is negated (unit is only started if the path does not exist)

("|"), triggering condition. unit will be executed if at least one of the triggering conditions apply

ConditionPathExists

# If any of the condition isn't satisfied, it doesn't start service.

ConditionPathExists=!/tmp/abc
ConditionPathExists=!/tmp/abe

# If any of these conditions is satisfied, it will run the service.

ConditionPathExists=|!/tmp/abc
ConditionPathExists=|!/tmp/abe

 


Auto Restart Service when fail

 

[Service]
Restart=always

Takes one of no, on-success, on-failure, on-abnormal, on-watchdog, on-abort, or always.

If set to no (the default), the service will not be restarted.

If set to on-success, it will be restarted only when the service process exits cleanly.

clean exit means any of the following:

  • exit code of 0
  • for types other than Type=oneshot, one of the signals SIGHUP, SIGINT, SIGTERM, or SIGPIPE
  • exit statuses and signals specified in SuccessExitStatus=

 


Log Settings

 

i.e.

/etc/systemd/system/shadowsocks.service             # shadowsocks.service

[Unit]
Description=Shadowsocks proxy server
After=network.target

[Service]
Type=simple
User=ss
Group=ss
ExecStart=/opt/shadowsocks/bin/ss-server -v \
          --no-delay --fast-open \
          -c /opt/shadowsocks/etc/ss/config.json
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=shadowsocks
Restart=always

[Install]
WantedBy=multi-user.target

Notes

SyslogIdentifier 最好長一點, 否則會 grep 到類似的字

StandardOutput & StandardError

# V >= 240

Takes one of

  • inherit,
  • null, tty, journal, kmsg, journal+console, kmsg+console,
  • file:path, append:path, truncate:path,
  • socket or fd:name

i.e.

StandardOutput=append:/var/log/ss/ss.log
StandardError=append:/var/log/ss/ss.log
SyslogIdentifier=shadowsocks

Notes

使用自定的 log 檔要自行處理 logrotate

 


Overriding some setting

 

[方法1]

Copy the unit file from /lib/systemd/system/ to /etc/systemd/system/

[方法2]

systemctl edit --full <service-name>

[方法3]

# This creates a directory "/etc/systemd/system/NamedOfUnit.d", and an "override.conf" file in that directory

systemctl edit foo

i.e.

在 console-getty.service 內有設定

[Service]
ExecStart=-/sbin/agetty --noclear --keep-baud console 115200,38400,9600 $TERM

想 Override "ExecStart"

systemctl edit console-getty

[Service]
# needs to first clear
ExecStart=
ExecStart=-/sbin/agetty --noclear console linux

systemctl daemon-reload

 


cgroup_systemd

 

https://datahunter.org/cgroup_systemd

 

 


systemd_nice

 

http://datahunter.org/nice#systemd_nice

 


systemd_oom_score_adj

 

http://datahunter.org/oom-killer#systemd-oom_score_adj

 

 


Disable systemd listening on port 111

 

Port 111 is rpcbind and it would be recommended to firewall it off if it's not being used.

CLI

# 會出 Warning
# 因為它被 "rpcbind.socket" 使用, 所以要 stop rpcbind.socket 先

systemctl disable rpcbind --now

systemctl disable rpcbind.socket --now

Checking

ss -ntl sport eq 111

 


Disable Service(mask)

 

如果此 Service 被其他 Service 所依賴, 那就不能 disable 它, 那時要用 mask

systemctl disable dev-hugepages.mount

說明

This will link these units to /dev/null, making it impossible to start them.

This is a stronger version of disable, since it prohibits all kinds of activation of the unit

systemctl mask dev-hugepages.mount

Created symlink /etc/systemd/system/dev-hugepages.mount → /dev/null

 


Disk automatically unmounts immediately after mounting

 

OS: CentOS 7.7

mount /mnt/rsync_disk2 時會被 auto umount

dmesg

[1983866.411072] XFS (sdb1): Mounting V5 Filesystem
[1983866.529664] XFS (sdb1): Ending clean mount
[1983866.539527] XFS (sdb1): Unmounting Filesystem

/var/log/messages

Nov 27 09:41:56 backup1 kernel: XFS (sdb1): Mounting V5 Filesystem
Nov 27 09:41:57 backup1 kernel: XFS (sdb1): Ending clean mount
Nov 27 09:41:57 backup1 systemd: Unit mnt-rsync_disk2.mount is bound to inactive unit
 dev-disk-by\x2duuid-182515f8\x2d72b2\x2d4552\x2dbf07\x2dba2074343af1.device. Stopping, too.
Nov 27 09:41:57 backup1 systemd: Unmounting /mnt/rsync_disk2...
Nov 27 09:41:57 backup1 kernel: XFS (sdb1): Unmounting Filesystem
Nov 27 09:41:57 backup1 systemd: Unmounted /mnt/rsync_disk2.

Reason

at boot time systemd-fstab-generator generates, in effect, a bunch of dynamic unit files for each mount.

Fix

systemctl daemon-reload

 


Toubleshoot

 

[1]

apt-get install -y rsync

initctl: Unable to connect to Upstart: Failed to connect to socket /com/ubuntu/upstart: Connection refused

原因

Ubuntu 16.04 now uses systemd rather than Upstart

runit package in an semi-installed state.

Package & File

upstart-sysv

  • /sbin/init
  • /sbin/reboot
  • /sbin/runlevel
  • /sbin/shutdown
  • /sbin/poweroff
  • /sbin/halt
  • /sbin/telinit

systemd-sysv

  • /sbin/init
  • /sbin/reboot
  • /sbin/runlevel
  • /sbin/shutdown
  • /sbin/poweroff
  • /sbin/halt
  • /sbin/telinit

判斷在使用 upstart-sysv 還是 systemd-sysv

dpkg -S /sbin/init

systemd-sysv: /sbin/init

 


依賴 unit

 

systemctl list-units | grep clamd

clamd@amavisd.service    loaded active running   clamd scanner (amavisd) daemon

/usr/lib/systemd/system/amavisd.service

[Unit]
...
Wants[email protected]

[Service]
...

systemctl list-unit-files | grep clamd

clamd@.service                                enabled

/usr/lib/systemd/system/[email protected]

[Unit]
Description = clamd scanner (%i) daemon
After = syslog.target nss-lookup.target network.target

[Service]
Type = forking
ExecStart = /usr/sbin/clamd -c /etc/clamd.d/%i.conf
Restart = on-failure
[Install]
WantedBy=multi-user.target

Wants=

A weaker version of "Requires=".

Units listed in this option will be started if the configuring unit is.

However, if the listed units fail to start or cannot be added to the transaction,

this has no impact on the validity of the transaction as a whole.

This is the recommended way to hook start-up of one unit to the start-up of another unit.

應用: Disable the service

systemctl disable [email protected]

 


KillMode

 

One of control-group(Default), mixed, process, none.

control-group

all remaining processes in the control group of this unit will be killed on unit stop

process (not recommended!)

only the main process itself is killed

none (not recommended!)

only the stop command will be executed on unit stop, but no process will be killed otherwise.

Processes remaining alive after stop are left in their control group and

the control group continues to exist after stop unless empty.

 

 


Debian add sysv systemd service

 

/etc/init.d/vpnserver

在 Debian 上必須有此 header, 否則 /lib/systemd/systemd-sysv-install 安裝唔到它

### BEGIN INIT INFO
# Provides: vpnserver
# Required-Start: $network $local_fs
# Required-Stop: $network $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: SoftEther VPN Server
### END INIT INFO

...

systemctl enable vpnserver

 


Fix /run/systemd/system Full

 

ls -1 /run/systemd/system

user-0.slice              # File
user-0.slice.d            # Folder
...

Fix

systemctl | awk '$4 == "abandoned" {print $1}' | xargs -r systemctl stop

 


RestrictAddressFamilies

 

"none", or a space-separated list of address family names to allow-list

  • "none": all address families will be denied
  • Prefixed with "~" # the listed address families will be applied as deny list, otherwise as allow list.
  • AF_UNIX             # UNIX Domain Sockets
  • AF_INET              # IPv4 (TCP, UDP)
  • AF_INET6            # IPv6
  • AF_NETLINK        # Communication between the kernel and user space processes
  • AF_PACKET         # for low-level packet interface (directly with the network device driver)
  • AF_BLUETOOTH    # for Bluetooth networking
  • AF_ALG              # kernel's cryptographic API
  • AF_VSOCK         # communication between virtual machines and the host kernel
  • ....

應用: rsyslog

 


journalctl

 

應用 1

  • -u, --unit=UNIT|PATTERN     # 查看某一 unit 的 log msg
  • -f, --follow                           # continuously print new entries as they are appended to the journal
  • -e                                       # jump to the end of the journal

journalctl -f -u rsyslog

 


Log File

 

Location: /var/log/journal

查看 log 的 usage

journalctl --disk-usage

Archived and active journals take up 1.1G in the file system.

清 log 指令

journalctl --vacuum-size=100M

journalctl --vacuum-time=7d

# Unit: "K", "M", "G"
# Unit: "s", "m", "h", "days", "months"

Removes the oldest archived journal files until the disk space they use falls below the specified size,
 or all archived journal files contain no data older than the specified timespan,
 or no more than the specified number of separate journal files remain.

--vacuum-size=, --vacuum-time= and --vacuum-files=
 may be combined in a single invocation to enforce any combination of a size,
 a time and a number of files limit on the archived journal files.
 Specifying any of these three parameters as zero is equivalent to not enforcing the specific limit

Log File Size 設定

/etc/systemd/journald.conf

SystemMaxFileSize=50M
SystemMaxFiles=5

service systemd-journald restart

Note

  • only archived files are deleted to reduce the number of files until this limit is reached;
  • active files will stay around.

 


cron run every 10s

 

1) Create a service unit file

[Unit]
Description=My Service

[Service]
Type=simple
ExecStart=/path/to/your/script.sh

2) Create a timer unit file

[Unit]
Description=Run My Service every 10 seconds

[Timer]
OnUnitActiveSec=10s
Unit=my-service.service

[Install]
WantedBy=timers.target

systemctl enable my-service.timer

systemctl start my-service.timer

To ensure that only one instance of a process runs at a time

#!/bin/bash

LOCK_FILE=/tmp/my_script.lock

# Check if lock file exists
if [ -e "$LOCK_FILE" ]; then
    echo "Script is already running. Exiting." && exit 1
fi

# Create lock file
touch $LOCK_FILE

...

# Close the lock
rm -f $LOCK_FILE

 


target

 

查看有什麼 target

systemctl | awk '$1 ~ /.target$/{print $1}'

以圖表查看次序

systemd-analyze plot > systemd.svg

multi-user 與 sysinit target

e.g.

...

[Install]
WantedBy=multi-user.target

sysinit.target

It is after the filesystems and swap are mounted and the basic system features are up,
 but before the various background services start.

multi-user.target

It is after the services are running and the login prompts are enabled.

 


Doc

 

man systemd-system.conf

 


More

 

進程管理工具

 

Creative Commons license icon Creative Commons license icon