]> git.ipfire.org Git - thirdparty/systemd.git/blame - test/units/testsuite-26.sh
shell-completion: add systemctl list-paths
[thirdparty/systemd.git] / test / units / testsuite-26.sh
CommitLineData
ff12a795 1#!/usr/bin/env bash
7b3cec95 2# SPDX-License-Identifier: LGPL-2.1-or-later
209d355c 3# shellcheck disable=SC2016
084575ff 4set -eux
79411bbc
LP
5set -o pipefail
6
5f882cc3
YW
7# shellcheck source=test/units/assert.sh
8. "$(dirname "$0")"/assert.sh
9
10: >/failed
11
d16684fe
FS
12at_exit() {
13 if [[ -v UNIT_NAME && -e "/usr/lib/systemd/system/$UNIT_NAME" ]]; then
209d355c 14 rm -fvr "/usr/lib/systemd/system/$UNIT_NAME" "/etc/systemd/system/$UNIT_NAME.d" "+4"
d16684fe 15 fi
5f882cc3
YW
16
17 rm -f /etc/init.d/issue-24990
18 return 0
d16684fe
FS
19}
20
9aaa333f
MY
21# shellcheck source=test/units/assert.sh
22. "$(dirname "$0")"/assert.sh
23
d16684fe
FS
24trap at_exit EXIT
25
26# Create a simple unit file for testing
27# Note: the service file is created under /usr on purpose to test
28# the 'revert' verb as well
209d355c 29export UNIT_NAME="systemctl-test-$RANDOM.service"
d16684fe
FS
30cat >"/usr/lib/systemd/system/$UNIT_NAME" <<\EOF
31[Unit]
32Description=systemctl test
33
34[Service]
35ExecStart=sleep infinity
36ExecReload=true
37
38# For systemctl clean
39CacheDirectory=%n
40ConfigurationDirectory=%n
41LogsDirectory=%n
42RuntimeDirectory=%n
43StateDirectory=%n
44
45[Install]
46WantedBy=multi-user.target
47EOF
48
49# Configure the preset setting for the unit file
50mkdir /run/systemd/system-preset/
51echo "disable $UNIT_NAME" >/run/systemd/system-preset/99-systemd-test.preset
52
209d355c 53EDITOR='true' script -ec 'systemctl edit "$UNIT_NAME"' /dev/null
54[ ! -e "/etc/systemd/system/$UNIT_NAME.d/override.conf" ]
55
7a17e41d 56printf '%s\n' '[Service]' 'ExecStart=' 'ExecStart=sleep 10d' >"+4"
209d355c 57EDITOR='mv' script -ec 'systemctl edit "$UNIT_NAME"' /dev/null
58printf '%s\n' '[Service]' 'ExecStart=' 'ExecStart=sleep 10d' | cmp - "/etc/systemd/system/$UNIT_NAME.d/override.conf"
59
7a17e41d 60printf '%b' '[Service]\n' 'ExecStart=\n' 'ExecStart=sleep 10d' >"+4"
209d355c 61EDITOR='mv' script -ec 'systemctl edit "$UNIT_NAME"' /dev/null
62printf '%s\n' '[Service]' 'ExecStart=' 'ExecStart=sleep 10d' | cmp - "/etc/systemd/system/$UNIT_NAME.d/override.conf"
d16684fe
FS
63
64# Argument help
65systemctl --state help
66systemctl --signal help
67systemctl --type help
68
69# list-dependencies
70systemctl list-dependencies systemd-journald
71systemctl list-dependencies --after systemd-journald
72systemctl list-dependencies --before systemd-journald
73systemctl list-dependencies --after --reverse systemd-journald
74systemctl list-dependencies --before --reverse systemd-journald
75systemctl list-dependencies --plain systemd-journald
76
77# list-* verbs
78systemctl list-units
79systemctl list-units --recursive
80systemctl list-units --type=socket
81systemctl list-units --type=service,timer
23f3a6f5
FS
82# Compat: --type= allows load states for compatibility reasons
83systemctl list-units --type=loaded
84systemctl list-units --type=loaded,socket
d16684fe
FS
85systemctl list-units --legend=yes -a "systemd-*"
86systemctl list-units --state=active
87systemctl list-units --with-dependencies systemd-journald.service
88systemctl list-units --with-dependencies --after systemd-journald.service
89systemctl list-units --with-dependencies --before --reverse systemd-journald.service
90systemctl list-sockets
91systemctl list-sockets --legend=no -a "*journal*"
92systemctl list-sockets --show-types
93systemctl list-sockets --state=listening
94systemctl list-timers -a -l
95systemctl list-unit-files
96systemctl list-unit-files "*journal*"
97systemctl list-jobs
98systemctl list-jobs --after
99systemctl list-jobs --before
100systemctl list-jobs --after --before
101systemctl list-jobs "*"
37299769
MY
102systemctl list-dependencies sysinit.target --type=socket,mount
103systemctl list-dependencies multi-user.target --state=active
104systemctl list-dependencies sysinit.target --state=mounted --all
d16684fe 105
9aaa333f
MY
106# is-* verbs
107# Should return 4 for a missing unit file
108assert_rc 4 systemctl --quiet is-active not-found.service
109assert_rc 4 systemctl --quiet is-failed not-found.service
110assert_rc 4 systemctl --quiet is-enabled not-found.service
111# is-active: return 3 when the unit exists but inactive
112assert_rc 3 systemctl --quiet is-active "$UNIT_NAME"
113# is-enabled: return 1 when the unit exists but disabled
114assert_rc 1 systemctl --quiet is-enabled "$UNIT_NAME"
115
d16684fe
FS
116# Basic service management
117systemctl start --show-transaction "$UNIT_NAME"
118systemctl status -n 5 "$UNIT_NAME"
119systemctl is-active "$UNIT_NAME"
120systemctl reload -T "$UNIT_NAME"
121systemctl restart -T "$UNIT_NAME"
122systemctl try-restart --show-transaction "$UNIT_NAME"
123systemctl try-reload-or-restart --show-transaction "$UNIT_NAME"
124systemctl kill "$UNIT_NAME"
125(! systemctl is-active "$UNIT_NAME")
126systemctl restart "$UNIT_NAME"
127systemctl is-active "$UNIT_NAME"
128systemctl restart "$UNIT_NAME"
129systemctl stop "$UNIT_NAME"
130(! systemctl is-active "$UNIT_NAME")
131
132# enable/disable/preset
133(! systemctl is-enabled "$UNIT_NAME")
134systemctl enable "$UNIT_NAME"
135systemctl is-enabled -l "$UNIT_NAME"
136# We created a preset file for this unit above with a "disable" policy
137systemctl preset "$UNIT_NAME"
138(! systemctl is-enabled "$UNIT_NAME")
139systemctl reenable "$UNIT_NAME"
140systemctl is-enabled "$UNIT_NAME"
141systemctl preset --preset-mode=enable-only "$UNIT_NAME"
142systemctl is-enabled "$UNIT_NAME"
143systemctl preset --preset-mode=disable-only "$UNIT_NAME"
144(! systemctl is-enabled "$UNIT_NAME")
145systemctl enable --runtime "$UNIT_NAME"
146[[ -e "/run/systemd/system/multi-user.target.wants/$UNIT_NAME" ]]
147systemctl is-enabled "$UNIT_NAME"
148systemctl disable "$UNIT_NAME"
149# The unit should be still enabled, as we didn't use the --runtime switch
150systemctl is-enabled "$UNIT_NAME"
151systemctl disable --runtime "$UNIT_NAME"
152(! systemctl is-enabled "$UNIT_NAME")
153
154# mask/unmask/revert
155systemctl disable "$UNIT_NAME"
156[[ "$(systemctl is-enabled "$UNIT_NAME")" == disabled ]]
157systemctl mask "$UNIT_NAME"
158[[ "$(systemctl is-enabled "$UNIT_NAME")" == masked ]]
159systemctl unmask "$UNIT_NAME"
160[[ "$(systemctl is-enabled "$UNIT_NAME")" == disabled ]]
161systemctl mask "$UNIT_NAME"
162[[ "$(systemctl is-enabled "$UNIT_NAME")" == masked ]]
163systemctl revert "$UNIT_NAME"
164[[ "$(systemctl is-enabled "$UNIT_NAME")" == disabled ]]
165systemctl mask --runtime "$UNIT_NAME"
166[[ "$(systemctl is-enabled "$UNIT_NAME")" == masked-runtime ]]
167# This should be a no-op without the --runtime switch
168systemctl unmask "$UNIT_NAME"
169[[ "$(systemctl is-enabled "$UNIT_NAME")" == masked-runtime ]]
170systemctl unmask --runtime "$UNIT_NAME"
171[[ "$(systemctl is-enabled "$UNIT_NAME")" == disabled ]]
172
173# add-wants/add-requires
174(! systemctl show -P Wants "$UNIT_NAME" | grep "systemd-journald.service")
175systemctl add-wants "$UNIT_NAME" "systemd-journald.service"
176systemctl show -P Wants "$UNIT_NAME" | grep "systemd-journald.service"
177(! systemctl show -P Requires "$UNIT_NAME" | grep "systemd-journald.service")
178systemctl add-requires "$UNIT_NAME" "systemd-journald.service"
179systemctl show -P Requires "$UNIT_NAME" | grep "systemd-journald.service"
180
181# set-property
182systemctl set-property "$UNIT_NAME" IPAccounting=yes MemoryMax=1234567
183systemctl cat "$UNIT_NAME"
184# These properties should be saved to a persistent storage
185grep -r "IPAccounting=yes" "/etc/systemd/system.control/${UNIT_NAME}.d/"
186grep -r "MemoryMax=1234567" "/etc/systemd/system.control/${UNIT_NAME}.d"
187systemctl revert "$UNIT_NAME"
188(! grep -r "IPAccounting=" "/etc/systemd/system.control/${UNIT_NAME}.d/")
189(! grep -r "MemoryMax=" "/etc/systemd/system.control/${UNIT_NAME}.d/")
190# Same stuff, but with --runtime, which should use /run
191systemctl set-property --runtime "$UNIT_NAME" CPUAccounting=no CPUQuota=10%
192systemctl cat "$UNIT_NAME"
193grep -r "CPUAccounting=no" "/run/systemd/system.control/${UNIT_NAME}.d/"
194grep -r "CPUQuota=10%" "/run/systemd/system.control/${UNIT_NAME}.d/"
195systemctl revert "$UNIT_NAME"
196(! grep -r "CPUAccounting=" "/run/systemd/system.control/${UNIT_NAME}.d/")
197(! grep -r "CPUQuota=" "/run/systemd/system.control/${UNIT_NAME}.d/")
198
199# Failed-unit related tests
23f3a6f5 200(! systemd-run --wait --unit "failed.service" /bin/false)
d16684fe
FS
201systemctl is-failed failed.service
202systemctl --state=failed | grep failed.service
203systemctl --failed | grep failed.service
204systemctl reset-failed "fail*.service"
205(! systemctl is-failed failed.service)
206
207# clean
208systemctl restart "$UNIT_NAME"
209systemctl stop "$UNIT_NAME"
210# Check if the directories from *Directory= directives exist
211# (except RuntimeDirectory= in /run, which is removed when the unit is stopped)
212for path in /var/lib /var/cache /var/log /etc; do
213 [[ -e "$path/$UNIT_NAME" ]]
214done
215# Run the cleanup
216for what in "" configuration state cache logs runtime all; do
217 systemctl clean ${what:+--what="$what"} "$UNIT_NAME"
218done
219# All respective directories should be removed
220for path in /run /var/lib /var/cache /var/log /etc; do
221 [[ ! -e "$path/$UNIT_NAME" ]]
222done
223
224# --timestamp
225for value in pretty us µs utc us+utc µs+utc; do
226 systemctl show -P KernelTimestamp --timestamp="$value"
227done
228
23f3a6f5
FS
229# set-default/get-default
230target="$(systemctl get-default)"
231systemctl set-default emergency.target
232[[ "$(systemctl get-default)" == emergency.target ]]
233systemctl set-default "$target"
234[[ "$(systemctl get-default)" == "$target" ]]
235
236# show/status
237systemctl show --property ""
238# Pick a heavily sandboxed unit for the best effect on coverage
239systemctl show systemd-logind.service
240systemctl status
241# Ignore the exit code in this case, as it might try to load non-existing units
242systemctl status -a >/dev/null || :
243systemctl status -a --state active,running,plugged >/dev/null
244systemctl status "systemd-*.timer"
245systemctl status "systemd-journald*.socket"
246systemctl status "sys-devices-*-ttyS0.device"
247systemctl status -- -.mount
e0e7bc82 248systemctl status 1
23f3a6f5
FS
249
250# --marked
251systemctl restart "$UNIT_NAME"
252systemctl set-property "$UNIT_NAME" Markers=needs-restart
253systemctl show -P Markers "$UNIT_NAME" | grep needs-restart
254systemctl reload-or-restart --marked
255(! systemctl show -P Markers "$UNIT_NAME" | grep needs-restart)
256
257# --dry-run with destructive verbs
258# kexec is skipped intentionally, as it requires a bit more involved setup
259VERBS=(
260 default
261 emergency
262 exit
263 halt
264 hibernate
265 hybrid-sleep
266 poweroff
267 reboot
268 rescue
269 suspend
270 suspend-then-hibernate
271)
272
273for verb in "${VERBS[@]}"; do
274 systemctl --dry-run "$verb"
275
276 if [[ "$verb" =~ (halt|poweroff|reboot) ]]; then
277 systemctl --dry-run --message "Hello world" "$verb"
278 systemctl --dry-run --no-wall "$verb"
279 systemctl --dry-run -f "$verb"
280 systemctl --dry-run -ff "$verb"
281 fi
282done
283
d16684fe
FS
284# Aux verbs & assorted checks
285systemctl is-active "*-journald.service"
286systemctl cat "*journal*"
287systemctl cat "$UNIT_NAME"
288systemctl help "$UNIT_NAME"
23f3a6f5
FS
289systemctl service-watchdogs
290systemctl service-watchdogs "$(systemctl service-watchdogs)"
d16684fe
FS
291
292# show/set-environment
79411bbc
LP
293# Make sure PATH is set
294systemctl show-environment | grep -q '^PATH='
79411bbc
LP
295# Let's add an entry and override a built-in one
296systemctl set-environment PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/testaddition FOO=BAR
79411bbc
LP
297# Check that both are set
298systemctl show-environment | grep -q '^PATH=.*testaddition$'
299systemctl show-environment | grep -q '^FOO=BAR$'
79411bbc 300systemctl daemon-reload
79411bbc
LP
301# Check again after the reload
302systemctl show-environment | grep -q '^PATH=.*testaddition$'
303systemctl show-environment | grep -q '^FOO=BAR$'
5ef599b3
JH
304# Check that JSON output is supported
305systemctl show-environment --output=json | grep -q '^{.*"FOO":"BAR".*}$'
79411bbc
LP
306# Drop both
307systemctl unset-environment FOO PATH
79411bbc 308# Check that one is gone and the other reverted to the built-in
4e20fe27
ZJS
309systemctl show-environment | grep '^FOO=$' && exit 1
310systemctl show-environment | grep '^PATH=.*testaddition$' && exit 1
79411bbc 311systemctl show-environment | grep -q '^PATH='
d16684fe
FS
312# Check import-environment
313export IMPORT_THIS=hello
314export IMPORT_THIS_TOO=world
315systemctl import-environment IMPORT_THIS IMPORT_THIS_TOO
316systemctl show-environment | grep "^IMPORT_THIS=$IMPORT_THIS"
317systemctl show-environment | grep "^IMPORT_THIS_TOO=$IMPORT_THIS_TOO"
318systemctl unset-environment IMPORT_THIS IMPORT_THIS_TOO
319(! systemctl show-environment | grep "^IMPORT_THIS=")
320(! systemctl show-environment | grep "^IMPORT_THIS_TOO=")
79411bbc 321
5f882cc3
YW
322# test for sysv-generator (issue #24990)
323if [[ -x /usr/lib/systemd/system-generators/systemd-sysv-generator ]]; then
fc2a0bc0
FS
324 # This is configurable via -Dsysvinit-path=, but we can't get the value
325 # at runtime, so let's just support the two most common paths for now.
326 [[ -d /etc/rc.d/init.d ]] && SYSVINIT_PATH="/etc/rc.d/init.d" || SYSVINIT_PATH="/etc/init.d"
327
5f882cc3 328 # invalid dependency
fc2a0bc0 329 cat >"${SYSVINIT_PATH:?}/issue-24990" <<\EOF
5f882cc3
YW
330#!/bin/bash
331
332### BEGIN INIT INFO
333# Provides:test1 test2
334# Required-Start:test1 $remote_fs $network
335# Required-Stop:test1 $remote_fs $network
336# Description:Test
337# Short-Description: Test
338### END INIT INFO
339
340case "$1" in
341 start)
342 echo "Starting issue-24990.service"
343 sleep 1000 &
344 ;;
345 stop)
346 echo "Stopping issue-24990.service"
347 sleep 10 &
348 ;;
349 *)
350 echo "Usage: service test {start|stop|restart|status}"
351 ;;
352esac
353EOF
354
fc2a0bc0 355 chmod +x "$SYSVINIT_PATH/issue-24990"
5f882cc3
YW
356 systemctl daemon-reload
357 [[ -L /run/systemd/generator.late/test1.service ]]
358 [[ -L /run/systemd/generator.late/test2.service ]]
359 assert_eq "$(readlink -f /run/systemd/generator.late/test1.service)" "/run/systemd/generator.late/issue-24990.service"
360 assert_eq "$(readlink -f /run/systemd/generator.late/test2.service)" "/run/systemd/generator.late/issue-24990.service"
361 output=$(systemctl cat issue-24990)
fc2a0bc0 362 assert_in "SourcePath=$SYSVINIT_PATH/issue-24990" "$output"
5f882cc3
YW
363 assert_in "Description=LSB: Test" "$output"
364 assert_in "After=test1.service" "$output"
365 assert_in "After=remote-fs.target" "$output"
366 assert_in "After=network-online.target" "$output"
367 assert_in "Wants=network-online.target" "$output"
fc2a0bc0
FS
368 assert_in "ExecStart=$SYSVINIT_PATH/issue-24990 start" "$output"
369 assert_in "ExecStop=$SYSVINIT_PATH/issue-24990 stop" "$output"
5f882cc3
YW
370 systemctl status issue-24990 || :
371 systemctl show issue-24990
372 assert_not_in "issue-24990.service" "$(systemctl show --property=After --value)"
373 assert_not_in "issue-24990.service" "$(systemctl show --property=Before --value)"
374
375 if ! systemctl is-active network-online.target; then
376 systemctl start network-online.target
377 fi
378
379 systemctl restart issue-24990
380 systemctl stop issue-24990
381
382 # valid dependency
fc2a0bc0 383 cat >"$SYSVINIT_PATH/issue-24990" <<\EOF
5f882cc3
YW
384#!/bin/bash
385
386### BEGIN INIT INFO
387# Provides:test1 test2
388# Required-Start:$remote_fs
389# Required-Stop:$remote_fs
390# Description:Test
391# Short-Description: Test
392### END INIT INFO
393
394case "$1" in
395 start)
396 echo "Starting issue-24990.service"
397 sleep 1000 &
398 ;;
399 stop)
400 echo "Stopping issue-24990.service"
401 sleep 10 &
402 ;;
403 *)
404 echo "Usage: service test {start|stop|restart|status}"
405 ;;
406esac
407EOF
79411bbc 408
fc2a0bc0 409 chmod +x "$SYSVINIT_PATH/issue-24990"
5f882cc3
YW
410 systemctl daemon-reload
411 [[ -L /run/systemd/generator.late/test1.service ]]
412 [[ -L /run/systemd/generator.late/test2.service ]]
413 assert_eq "$(readlink -f /run/systemd/generator.late/test1.service)" "/run/systemd/generator.late/issue-24990.service"
414 assert_eq "$(readlink -f /run/systemd/generator.late/test2.service)" "/run/systemd/generator.late/issue-24990.service"
415 output=$(systemctl cat issue-24990)
fc2a0bc0 416 assert_in "SourcePath=$SYSVINIT_PATH/issue-24990" "$output"
5f882cc3
YW
417 assert_in "Description=LSB: Test" "$output"
418 assert_in "After=remote-fs.target" "$output"
fc2a0bc0
FS
419 assert_in "ExecStart=$SYSVINIT_PATH/issue-24990 start" "$output"
420 assert_in "ExecStop=$SYSVINIT_PATH/issue-24990 stop" "$output"
5f882cc3
YW
421 systemctl status issue-24990 || :
422 systemctl show issue-24990
423 assert_not_in "issue-24990.service" "$(systemctl show --property=After --value)"
424 assert_not_in "issue-24990.service" "$(systemctl show --property=Before --value)"
425
426 systemctl restart issue-24990
427 systemctl stop issue-24990
428fi
79411bbc 429
5f882cc3
YW
430touch /testok
431rm /failed