Недавно я нашел решение своей проблемы.
Поскольку убийца OOM в Linux не может выполнять свою работу должным образом, я начал использовать убийцу OOM в пользовательском пространстве:Earlyoom . Он написан на C, достаточно настраиваемый и работает как шарм для меня.
Я также слышал о некоторых альтернативах, таких как OOMD Facebook , разработанных для работы на их серверах, но я не пробовал эту
Из Лукаса Веркмайстера информативного ответа о сбое сервера:
Если вы не хотите полагаться на эти переменные или для версий 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
Мне нравится ответ Джеффа Шаллера, возможно, это The Right Thing™.Другой подход может заключаться в использовании двух сценариев. Переместите фактическую оболочку из /path/to/wrapper
в другое имя файла и используйте это имя в файле модуля systemd. А затем создайте еще один сценарий с исходным именем, который ничего не делает, кроме отображения полезного сообщения об ошибке.
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
Другим очевидным решением, которое приходит на ум, является добавление чего-то вроде
Environment=FROM_SYSTEMD=1
в служебный файл и протестируйте этот envvar.