Как я могу определить в сценарии оболочки, вызывается ли он systemd или нет?

Недавно я нашел решение своей проблемы.

Поскольку убийца OOM в Linux не может выполнять свою работу должным образом, я начал использовать убийцу OOM в пользовательском пространстве:Earlyoom . Он написан на C, достаточно настраиваемый и работает как шарм для меня.

Я также слышал о некоторых альтернативах, таких как OOMD Facebook , разработанных для работы на их серверах, но я не пробовал эту

24
04.12.2020, 16:15
4 ответа

Из Лукаса Веркмайстера информативного ответа о сбое сервера:

  • В systemd версии 231 и более поздних есть переменная JOURNAL _STREAM, которая устанавливается для служб, stdout или stderr которых подключен к журналу.
  • В systemd версии 232 и более поздних установлена ​​переменная INVOCATION _ID.

Если вы не хотите полагаться на эти переменные или для версий systemd до 231, вы можете проверить, равен ли родительский PID 1:

if [[ $PPID -ne 1 ]]
then
  echo "Don't call me directly; instead, call 'systemctl start/stop service-name'"
  exit 1
fi >&2
25
18.03.2021, 22:45

Мне нравится ответ Джеффа Шаллера, возможно, это The Right Thing™.Другой подход может заключаться в использовании двух сценариев. Переместите фактическую оболочку из /path/to/wrapperв другое имя файла и используйте это имя в файле модуля systemd. А затем создайте еще один сценарий с исходным именем, который ничего не делает, кроме отображения полезного сообщения об ошибке.

5
18.03.2021, 22:45

Краткий ответ

if ! grep -qEe '[.]service$' /proc/self/cgroup; then
    echo "This script should be started with systemctl" >&2
    exit 1
fi

...или, если вы знаете конкретное имя службы, от которой вы должны работать, и хотите быть устойчивым к неправильным конфигурациям, препятствующим созданию сеанса пользователя:

if ! grep -qEe '/myservice[.]service$' /proc/self/cgroup; then
    echo "This service should be started with systemctl start myservice" >&2
    exit 1
fi

Почему это работает

Одним из способов определения того, какая служба --, если таковая вообще --запустила текущий процесс, является проверка /proc/self/cgroup. Для запущенной службыsystemd-это будет содержать имя службы; например:

12:pids:/system.slice/dhcpcd.service
11:rdma:/
10:memory:/system.slice/dhcpcd.service
9:blkio:/system.slice/dhcpcd.service
8:devices:/system.slice/dhcpcd.service
7:hugetlb:/
6:cpuset:/
5:freezer:/
4:cpu,cpuacct:/system.slice/dhcpcd.service
3:net_cls,net_prio:/
2:perf_event:/
1:name=systemd:/system.slice/dhcpcd.service
0::/system.slice/dhcpcd.service

...тогда как для процесса, связанного с сеансом пользователя, контрольная группа будет больше похожа на /user.slice/user-1000.slice/session-337.scope(, предполагая, что это пользователь с UID 1000, 337-й сеанс в системе с момента его последней перезагрузки ).


Более изящная реализация

Если кто-то хочет определить конкретную службу, запущенную как, это тоже можно извлечь из /proc/self/cgroup. Рассмотрим, например:

cgroup_full=$(awk -F: '$1 == 0 { print $3 }' /proc/self/cgroup)
cgroup_short=${cgroup_full##*/}
case $cgroup_full in
  /system.slice/*.service) echo "Run from system service ${cgroup_short%.*}";;
  /user.slice/*.service)   echo "Run from user service ${cgroup_short%.*}";;
  *.service)               echo "Service ${cgroup_short%.*} type unknown";;
  *)                       echo "Not run from a systemd service; in $cgroup_full";;
esac
13
18.03.2021, 22:45

Другим очевидным решением, которое приходит на ум, является добавление чего-то вроде

Environment=FROM_SYSTEMD=1

в служебный файл и протестируйте этот envvar.

7
18.03.2021, 22:45

Теги

Похожие вопросы