Вопрос или проблема
Ладно, это РЕШЕННАЯ проблема, но остаются несколько вопросов…
У меня есть некоторые “скрипты”, которые автоматически монтируют файловые системы, а затем делятся различными частями через NFS и Samba.
Я запускал версии этих скриптов в течение многих месяцев на системе с фиксированными (болтами закрепленными) дисками и использовал службу systemd, работало нормально.
Моя текущая система имеет диск, подключенный через USB (плюс фиксированный NVME), поэтому я использовал udev. Конечно, я столкнулся с проблемой “вы не можете выполнить mount(1) внутри правила udev (отдельное пространство имен для монтирования), поэтому я сделал ‘обычное’ (запуск службы):
graeme@argon:~$ cat /etc/udev/rules.d/99-QPImount.rules
ACTION=="add|change|online|bind", ENV{ID_FS_USAGE}=="filesystem", ENV{ID_FS_LABEL_ENC}=="rest?", TAG+="systemd" ENV{SYSTEMD_WANTS}+="QPImount.service"
Это работало нормально, когда я тестировал его (udevadm trigger -a add /dev/sda4) и на практике, когда отключал и снова включал питание.
Однако сегодня я включил систему без подключенного USB-диска, а затем позже подключил его. Мой скрипт не запустился. Проводя шаги вручную, все выглядело нормально, пока я не попробовал запустить службу вручную:
#systemctl start QPImount
Это зависает.
graeme@argon:~$ cat /etc/systemd/system/QPImount.service
[Unit]
Description=Сделать все файловые системы QPIhomebrew доступными (NFS & SAMBA)
After=remote-fs.target
Before=minidlna.service samba.service
[Service]
Type=oneshot
ExecStart=/bin/bash -c 'QPImount' && echo 'QPImount completed'
[Install]
#WantedBy=multi-user.target minidlna.service samba.service
#WantedBy=multi-user.target
Вы можете видеть, я хочу дождаться remote-fs.target (экспорт NFS не удается до этого момента)
К вашему сведению, в скрипте есть отладка, поэтому я вижу, что ОН НЕ НАЧАЛСЯ.
Если я перечислю цели…
# systemctl list-units --type target
UNIT LOAD ACTIVE SUB JOB DESCRIPTION
basic.target загружен активно активно Основная система
bluetooth.target загружен активно активно Поддержка Bluetooth
cryptsetup.target загружен активно активно Локальные шифрованные тома
getty.target загружен активно активно Запросы на вход
graphical.target загружен неактивно неактивный начать Графический интерфейс
integritysetup.target загружен активно активно Локальные тома с защитой целостности
local-fs-pre.target загружен активно активно Подготовка для локальных файловых систем
local-fs.target загружен активно активно Локальные файловые системы
multi-user.target загружен неактивно неактивный начать Много-пользовательская система
network-online.target загружен активно активно Сеть в сети
network.target загружен активно активно Сеть
nfs-client.target загружен активно активно Службы клиента NFS
nss-lookup.target загружен активно активно Поиск имен хостов и сетей
nss-user-lookup.target загружен активно активно Поиск имен пользователей и групп
paths.target загружен активно активно Путь Units
remote-fs-pre.target загружен активно активно Подготовка к удаленным файловым системам
remote-fs.target загружен активно активно Удаленные файловые системы
rpc_pipefs.target загружен активно активно rpc_pipefs.target
rpcbind.target загружен активно активно Отображение портов RPC
slices.target загружен активно активно Единицы Slice
sockets.target загружен активно активно Единицы Socket
sound.target загружен активно активно Звуковая карта
swap.target загружен активно активно Свопы
sysinit.target загружен активно активно Инициализация системы
time-set.target загружен активно активно Установка времени системы
timers.target загружен активно активно Единицы таймера
veritysetup.target загружен активно активно Локальные защищенные тома Verity
Я вижу, что remote-fs.target активен.
Итак, мой вопрос:
Я считаю, что systemd “ждет чего-то”, чтобы запустить QPImount.service. Есть ли команда, которая скажет мне, чего он ждет, прежде чем он запустит QPImount.
…статус показывает статус первого использования службы QPImount (для монтирования файловых систем NVME)… ничего по этому (потому что он не запущен?)
root@argon:/home/graeme# systemctl status QPImount
QPImount.service - Сделать все файловые системы QPIhomebrew доступными (NFS & SAMBA)
Загружено: загружено (/etc/systemd/system/QPImount.service; статично)
Активно: активируется (старт) с Пн 2025-03-03 09:02:01 GMT; 43мин назад
Основной PID: 1005 (QPImount)
Задачи: 2 (лимит: 9569)
ЦП: 134мс
ГруппаC: /system.slice/QPImount.service
005 /bin/bash /usr/local/bin/QPImount
1492 systemctl restart minidlna.service
Мар 03 09:02:01 argon systemd[1]: Starting QPImount.service - Сделать все файловые системы QPIhomebrew доступными (NFS & SAMBA)...
Мар 03 09:02:01 argon bash[1005]: QPImount вызван с
Мар 03 09:02:01 argon bash[1029]: rmdir: не удалось удалить '/QPI/mounts/rest2/Multimedia': Нет такого файла или каталога
Мар 03 09:02:01 argon bash[1029]: rmdir: не удалось удалить '/Multimedia': Нет такого файла или каталога
Мар 03 09:02:01 argon bash[1033]: rmdir: не удалось удалить '/QPI/mounts/rest2/USBUploads': Нет такого файла или каталога
Мар 03 09:02:01 argon bash[1033]: rmdir: не удалось удалить '/USBUploads': Нет такого файла или каталога
Мар 03 09:02:01 argon bash[1047]: rmdir: не удалось удалить '/QPI/mounts/rest2/Recordings': Нет такого файла или каталога
Мар 03 09:02:01 argon bash[1047]: rmdir: не удалось удалить '/Recordings': Нет такого файла или каталога
Мар 03 09:02:01 argon bash[1048]: rmdir: не удалось удалить '/QPI/mounts/rest2': Нет такого файла или каталога
Мар 03 09:02:02 argon bash[1005]: Для QPI rest3 добавление Public svn git Web InternalAdmin Download home
…ниже есть “решение”, но вопрос о том, как это обнаружить, все еще открыт
Кажется, люди не любят, когда я даю частичный ответ в оригинале… поэтому выделен здесь
————– Решение ————–
При написании этого сообщения, я нашел свою проблему (https://wiki.c2.com/?CardboardProgrammer также известный как картонный супермен)
В службе я указываю “Before=minidlna.service samba.service”, но в моем скрипте я делаю:
systemctl restart smb.service # Поделиться тем, что можем через SAMBA
systemctl restart minidlna.service # Поделиться через DLNA протокол
…так что “смертельное объятие”, я должен запустить ПЕРЕД smb.service, НО прежде чем закончить, я должен перезапустить smb.service (думаю, я мог бы сделать это в фоновом режиме?) Я считаю, что делать это тоже “нельзя”… но вы видите мою проблему? Как только появляется новая файловая система, различные службы нужно перезапустить, чтобы с этим справиться.
Кстати, я заметил, что runlevel(1) возвращает “неизвестно” в то время, как сейчас возвращает “5”… намек/подпись на блокировку.
Но исходный вопрос остается: “есть ли команда, которую я могу ввести в systemd, чтобы спросить ‘чего вы ждете, чтобы запустить эту службу’?
…так что НЕ “от чего он зависит”, а скорее “вы его не запустили? …почему?” предположительно, у systemd есть некоторое внутреннее состояние, которое говорит “ожидание X”
(2-й вопрос, как лучше достичь того, что я хочу [перезапуск])
Ответ или решение
Причины зависания сервиса systemd могут быть разнообразными и связаны с множеством факторов. Давайте разберемся, какие проблемы могут вызывать зависание сервиса, а затем перейдём к возможным решениям и рекомендациям для предотвращения таких ситуаций в дальнейшем.
Теория
1. Взаимная блокировка (Deadlock):
Ваша проблема, судя по всему, связана с взаимной блокировкой. Это состояние, при котором два или более процесса ожидают, пока другой сделает что-то для завершения, при этом ни один из них не может продолжить работу.
2. Некорректная конфигурация зависимостей:
В systemd очень важно корректно настроить зависимости между сервисами. Неправильная конфигурация может привести к зависаниям или недоступным сервисам.
3. Непредвиденные изменения в аппаратуре или окружении системы:
Подключение или отключение устройств может нарушить работу сервисов, если конфигурация не была подготовлена к такого рода изменениям. Это особенно актуально для систем с внешними накопителями.
4. Ошибки в скриптах или программах:
Могут быть в виде бесконечных циклов, преждевременных выходов и блокировок ресурсов, которые необходимы другим процессам.
Пример
В вашем случае проблема была вызвана зависимостями между сервисами. Вы указали, что ваш сервис должен выполняться до minidlna.service
и smb.service
. Однако внутри вашего скрипта вы пытались перезапустить эти сервисы, что привело к появлению взаимной блокировки — сервис не может завершиться до тех пор, пока не завершит перезапуск smb.service
, но задан в качестве необходимости выполнения до него.
Приложение
Решение проблемы
-
Избегайте вызова команд systemctl в сервисах, которые требуют конкретного порядка запуска.
Используйте возможность фоново запускать команды или подумайте о реструктуризации скрипта таким образом, чтобы сократить зависимости и избежать взаимных блокировок. -
Измените конфигурационные файлы systemd:
Вы можете попробовать следующие подходы:- Определите более простой порядок зависимостей, разделяя задачи так, чтобы избежать необходимости взывать systemd команды внутри ваших скриптов.
- Используйте более продвинутые механизмы, такие как
ExecStartPre
иExecStartPost
, для выполнения необходимых операций до и после основной команды.
-
Изучение возможных состояний зависимостей в systemd:
В вашем случае, возможно, полезно будет использоватьsystemctl list-dependencies --reverse
, чтобы увидеть, какие сервисы могут ожидать ваш сервис для завершения запуска. Однако, нужно помнить, что systemd не предоставляет прямой команды для выведения конкретного ожидания. -
Перемещение временных зависимостей в отдельные задачи/таймеры:
Подумайте об использовании механизма таймеров systemd, который позволит выполнять задачи без жесткой привязки к состоянию других сервисов, тем самым снижая риск взаимной блокировки. -
Логирование и отладка:
Усиление уровней логирования для более подробной информации о действиях и состояниях позволит оперативнее выявлять места потенциальных зависаний. Использованиеjournalctl -xe
может дать более глубокую информацию о состоянии системных журналов и текущих проблемах.
Используя приведенные методики и подходы, вы можете более эффективно управлять сервисами в вашей системе, минимизировать риск зависания, а также повысить стабильность её работы в условиях изменяющегося окружения и оборудования. Обязательно следуйте лучшим практикам и постоянно тестируйте изменения в изолированной среде перед их внедрением в рабочую систему.