Хорошо, аналогично cron
заданиям, может быть тем, что NRPE (сервер) работает с другой средой для вашей оболочки, и эта отдельная среда почему-то не работает systemctl
должным образом.
Простой способ убедиться в этом - временно изменить строку:
STAT=$(systemctl is-active $SERV)
, чтобы вы могли видеть, что происходит. Измените сценарий так, чтобы строка теперь стала:
(
echo ==== $(date) ==== ${SERV}
systemctl is-active $SERV
) >> /tmp/paxdebug.dynflowd 2>&1
STAT=$(systemctl is-active $SERV)
Это, наряду с запуском сценария для получения статуса, запишет некоторую полезную информацию в файл /tmp/paxdebug.dynflowd
, который затем можно просмотреть, чтобы увидеть именно то, что происходит в запущенном NRPE экземпляре сценария.
Надеюсь, он скажет что-то простое, например Cannot find systemctl
(с указанием проблем с путями), но, что бы он вам ни давал, он должен помочь точно определить в чем проблема.
Обновление 1: на основе ваших комментариев попытка запустить systemctl
привела к:
systemctl: command not found
Это почти наверняка, потому что путь неправильный. Вы можете проверить путь, добавив следующую строку в тот код отладки, который я опубликовал:
echo "PATH is [$PATH]"
Чтобы исправить его, либо измените свой путь в сценарии, включив в него /usr/bin
(при условии, что там находится systemctl
) или просто запустите абсолютный путь (как в области отладки, так и в исходной области):
/usr/bin/systemctl is-active ${SERV}
STAT=$(/usr/bin/systemctl is-active ${SERV})
Обновление 2: на основе ваших комментариев, что с использованием абсолютного пути вы теперь получаете:
/usr/lib64/nagios/plugins/check_service_active.sh: line 32:
/usr/bin/systemctl: Permission denied
Вероятно, 1037 * будет NRPE, работающим с низким уровнем привилегий, или как другой пользователь для обеспечения защиты от атак. Учитывая то, как systemd является центральным для работы системы, было бы неразумно разрешать беспрепятственный доступ к ней.
Итак, подобно предыдущему обновлению, добавьте следующее в область отладки:
/bin/ls -al /usr/bin/systemctl # Check "ls" is in this directory first.
/usr/bin/id # Ditto for "id".
В первой строке вы получите разрешения, во второй - ваши данные пользователя. В этот момент это становится упражнением в выяснении того, как запустить systemctl
без нарушения безопасности.
Если окажется, что это разрешение или проблема пользователя, one вероятность будет предоставить хорошо защищенный скрипт setuid
, который будет принадлежать (и, следовательно, запускаться от имени) пользователю, которому разрешено запускать systemctl
. Но я действительно имею в виду хорошо защищенный, так как вы не хотите открывать дыру:
# SysCtlIsActive.sh: only allows certain services to be queried.
# Limit to these ones (white-space separated).
allowed="dynflowd"
# If not allowed, reject with special status.
result="GoAway"
for service in ${allowed} ; do
[[ "$1" = "${service}" ]] && result=""
done
# If it IS allowed, get actual status.
[[ -z "${result}" ]] && result="$(/usr/bin/systemctl is-active "$1")"
echo "${result}"
Могут быть другие методы (и они могут будет лучше) но, надеюсь, это будет хорошим началом, если это действительно проблема.
Просто знайте, что я думаю, что setuid
игнорируется для сценариев оболочки, имеющих строку shebang (например, * 1061) *) поэтому вам, возможно, придется обойти это, возможно, создав настоящий исполняемый файл, чтобы выполнить эту работу.
Если вам do нужно создать для него настоящий исполняемый файл, вы можете запустить со следующим C кодом, который является адаптацией сценария оболочки выше:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv) {
// Check service name provided.
if (argc < 2) {
puts("NoServiceProvided");
return 1;
}
// Check service name allowed.
static char *allowed[] = { "dynflowd", NULL };
int isAllowed = 0;
for (char **service = &(allowed[0]); *service != NULL; service++) {
if (strcmp(*service, argv[1]) == 0) {
isAllowed = 1;
break;
}
}
if (! isAllowed) {
puts("InvalidServiceName");
return 1;
}
// Try to allocate memory for command.
char *prefix = "/usr/bin/systemctl is-active ";
char *cmdBuff = malloc(strlen(prefix) + strlen(argv[1]) + 1);
if (cmdBuff == NULL) {
puts("OutOfMemory");
return 1;
}
// Execute command, free memory, and return.
sprintf(cmdBuff, "%s%s", prefix, argv[1]);
system(cmdBuff);
free(cmdBuff);
return 0;
}