Query systemd for unit file paths on install/uninstall. (#19346)
* Query systemd for unit file paths on install/uninstall. This makes our installation code more portable and more concise, and should make the uninstallation code significantly more robust. Also includes a number of other improvements to systemd handling and updater handling in the uninstaller that should make it much more thorough and reliable. * Fix issues brought up in code review, and better support old systemd versions. * Replace sed with AWK for readability. * Fix uninstaller loop. * Fix unit file detection in updater code.
Austin S. Hemmelgarn committed
Jan 16, 2025 at 07:58 UTC
8649e9daea8ae96a90e470263e8b5db2e2c7573a
4 files changed
+91
-39
packaging/installer/functions.sh
+15
-6
@@ -636,13 +636,22 @@ issystemd() {
636
}
637
638
get_systemd_service_dir() {
639
- if [ -w "/lib/systemd/system" ]; then
640
- echo "/lib/systemd/system"
641
- elif [ -w "/usr/lib/systemd/system" ]; then
642
- echo "/usr/lib/systemd/system"
643
- elif [ -w "/etc/systemd/system" ]; then
644
- echo "/etc/systemd/system"
639
+ unit_paths="$(systemctl show -p UnitPath | cut -f 2- -d '=' | tr ' ' '\n')"
640
+
641
+ if [ -n "${unit_paths}" ]; then
642
+ lib_paths="$(echo "${unit_paths}" | grep -vE '^/(run|etc)' | awk '{line[NR] = $0} END {for (i = NR; i > 0; i--) print line[i]}')"
643
+ etc_paths="$(echo "${unit_paths}" | grep -E '^/etc' | grep -vE '(attached|control)$')"
644
+ else
645
+ lib_paths="/usr/lib/systemd/system /lib/systemd/system /usr/local/lib/systemd/system"
646
+ etc_paths="/etc/systemd/system"
647
fi
648
+
649
+ for path in ${lib_paths} ${etc_paths}; do
650
+ if [ -d "${path}" ] && [ -w "${path}" ]; then
651
+ echo "${path}"
652
+ return 0
653
+ fi
654
+ done
655
}
656
657
run_install_service_script() {
packaging/installer/netdata-uninstaller.sh
+35
-18
@@ -731,27 +731,45 @@ if [ "$(uname -s)" = "Darwin" ]; then
731
fi
732
733
#### REMOVE NETDATA FILES
734
+
735
+# Handle updater files first so that it doesn’t try to run while we
736
+# are uninstalling things.
737
+if [ -x "${NETDATA_PREFIX}/usr/libexec/netdata-updater.sh" ]; then
738
+ "${NETDATA_PREFIX}/usr/libexec/netdata-updater.sh" --disable-auto-updates
739
+else
740
+ rm_file /etc/periodic/daily/netdata-updater
741
+ rm_file /etc/cron.daily/netdata-updater
742
+ rm_file /etc/cron.d/netdata-updater
743
+ rm_file /etc/cron.d/netdata-updater-daily
744
+fi
745
+
746
+if issystemd; then
747
+ for unit in netdata.service netdata-updater.timer; do
748
+ systemctl disable "${unit}"
749
+ systemctl stop "${unit}"
750
+ done
751
+
752
+ for unit in netdata.service netdata-updater.service netdata-updater.timer; do
753
+ unit_path="$(systemctl show -p FragmentPath "${unit}" | cut -f 2- -d '=')"
754
+ override_paths="$(systemctl show -p DropInPaths "${unit}" | cut -f 2- -d '=')"
755
+ for path in "${unit_path}" ${override_paths} ; do
756
+ rm_file "${path}"
757
+ done
758
+ done
759
+
760
+ rm_file /usr/lib/systemd/journald@netdata.conf.d/netdata.conf
761
+ rm_file /lib/systemd/journald@netdata.conf.d/netdata.conf
762
+ rm_dir /usr/lib/systemd/journald@netdata.conf.d/
763
+ rm_file /usr/lib/systemd/system-preset/50-netdata.preset
764
+ rm_file /lib/systemd/system-preset/50-netdata.preset
765
+
766
+ systemctl daemon-reload
767
+fi
768
+
769
rm_file /etc/logrotate.d/netdata
735
-rm_file /usr/lib/systemd/journald@netdata.conf.d/netdata.conf
736
-rm_file /etc/systemd/system/netdata.service
737
-rm_file /lib/systemd/system/netdata.service
738
-rm_file /usr/lib/systemd/system/netdata.service
739
-rm_file /etc/systemd/system/netdata-updater.service
740
-rm_file /lib/systemd/system/netdata-updater.service
741
-rm_file /usr/lib/systemd/system/netdata-updater.service
742
-rm_file /etc/systemd/system/netdata-updater.timer
743
-rm_file /lib/systemd/system/netdata-updater.timer
744
-rm_file /usr/lib/systemd/system/netdata-updater.timer
745
-rm_file /usr/lib/systemd/system-preset/50-netdata.preset
746
-rm_file /lib/systemd/system-preset/50-netdata.preset
770
rm_file /etc/init.d/netdata
748
-rm_file /etc/periodic/daily/netdata-updater
749
-rm_file /etc/cron.daily/netdata-updater
750
-rm_file /etc/cron.d/netdata-updater
751
-rm_file /etc/cron.d/netdata-updater-daily
771
rm_file /Library/LaunchDaemons/com.github.netdata.plist
772
754
-
773
if [ -n "${NETDATA_PREFIX}" ] && [ -d "${NETDATA_PREFIX}" ] && [ "netdata" = "$(basename "$NETDATA_PREFIX")" ] ; then
774
rm_dir "${NETDATA_PREFIX}"
775
else
@@ -768,7 +786,6 @@ else
786
rm_dir "${NETDATA_PREFIX}/var/cache/netdata"
787
rm_dir "${NETDATA_PREFIX}/var/log/netdata"
788
rm_dir "${NETDATA_PREFIX}/etc/netdata"
771
- rm_dir /usr/lib/systemd/journald@netdata.conf.d/
789
fi
790
791
if [ -n "${tmpdir}" ]; then
packaging/installer/netdata-updater.sh
+22
-7
@@ -172,6 +172,14 @@ issystemd() {
172
return 1
173
}
174
175
+systemd_unit_exists() {
176
+ if systemctl list-unit-files "${1}" 2>&1 | tail -n 1 | grep -qv '^0 '; then
177
+ return 0
178
+ else
179
+ return 1
180
+ fi
181
+}
182
+
183
# shellcheck disable=SC2009
184
running_under_anacron() {
185
pid="${1:-$$}"
@@ -307,11 +315,17 @@ enable_netdata_updater() {
315
case "${updater_type}" in
316
"systemd")
317
if issystemd; then
310
- systemctl enable netdata-updater.timer
311
-
312
- info "Auto-updating has been ENABLED using a systemd timer unit.\n"
313
- info "If the update process fails, the failure will be logged to the systemd journal just like a regular service failure."
314
- info "Successful updates should produce empty logs."
318
+ if systemd_unit_exists netdata-updater.timer; then
319
+ systemctl enable netdata-updater.timer
320
+ systemctl start netdata-updater.timer
321
+
322
+ info "Auto-updating has been ENABLED using a systemd timer unit.\n"
323
+ info "If the update process fails, the failure will be logged to the systemd journal just like a regular service failure."
324
+ info "Successful updates should produce empty logs."
325
+ else
326
+ error "Systemd-based auto-update scheduling requested, but the required timer unit does not exist. Auto-updates have NOT been enabled."
327
+ return 1
328
+ fi
329
else
330
error "Systemd-based auto-update scheduling requested, but this does not appear to be a systemd system. Auto-updates have NOT been enabled."
331
return 1
@@ -351,8 +365,9 @@ enable_netdata_updater() {
365
}
366
367
disable_netdata_updater() {
354
- if issystemd && ( systemctl list-units --full -all | grep -Fq "netdata-updater.timer" ) ; then
368
+ if issystemd && systemd_unit_exists "netdata-updater.timer" ; then
369
systemctl disable netdata-updater.timer
370
+ systemctl stop netdata-updater.timer
371
fi
372
373
if [ -d /etc/cron.daily ]; then
@@ -387,7 +402,7 @@ auto_update_status() {
402
enabled=""
403
404
if issystemd; then
390
- if systemctl list-units --full -all | grep -Fq "netdata-updater.timer"; then
405
+ if systemd_unit_exists "netdata-updater.timer"; then
406
if systemctl is-enabled netdata-updater.timer; then
407
info "Auto-updates using a systemd timer unit are ENABLED"
408
enabled="systemd"
system/install-service.sh.in
+19
-8
@@ -229,16 +229,27 @@ check_systemd() {
229
}
230
231
get_systemd_service_dir() {
232
- if [ -w "/lib/systemd/system" ]; then
233
- echo "/lib/systemd/system"
234
- elif [ -w "/usr/lib/systemd/system" ]; then
235
- echo "/usr/lib/systemd/system"
236
- elif [ -w "/etc/systemd/system" ]; then
237
- echo "/etc/systemd/system"
232
+ set +e
233
+ unit_paths="$(systemctl show -p UnitPath | cut -f 2- -d '=' | tr ' ' '\n')"
234
+ set -e
235
+
236
+ if [ -n "${unit_paths}" ]; then
237
+ lib_paths="$(echo "${unit_paths}" | grep -vE '^/(run|etc)' | awk '{line[NR] = $0} END {for (i = NR; i > 0; i--) print line[i]}')"
238
+ etc_paths="$(echo "${unit_paths}" | grep -E '^/etc' | grep -vE '(attached|control)$')"
239
else
239
- error "Unable to detect systemd service directory."
240
- exit 4
240
+ lib_paths="/usr/lib/systemd/system /lib/systemd/system /usr/local/lib/systemd/system"
241
+ etc_paths="/etc/systemd/system"
242
fi
243
+
244
+ for path in ${lib_paths} ${etc_paths}; do
245
+ if [ -d "${path}" ] && [ -w "${path}" ]; then
246
+ echo "${path}"
247
+ return 0
248
+ fi
249
+ done
250
+
251
+ error "Unable to detect usable systemd service directory."
252
+ exit 4
253
}
254
255
install_systemd_service() {