好的,类似于cron
作业,可能是 NRPE(服务器)在与您的 shell 不同的环境中运行,并且该不同的环境在某种程度上无法正常运行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
这很可能是 NRPE 以低权限级别运行,或者作为不同的用户提供安全性免受攻击。考虑到 systemd 对系统运行的重要性,允许不受限制地访问它是不明智的。
因此,与之前的更新类似,将以下内容添加到调试区域:
/bin/ls -al /usr/bin/systemctl # Check "ls" is in this directory first.
/usr/bin/id # Ditto for "id".
第一行将为您获取权限,第二行将为您获取用户详细信息。到那时,它就变成了一个练习,弄清楚如何在systemctl
不违反安全性的情况下运行。
如果事实证明这是一个权限或用户问题,一种可能性是提供一个安全可靠的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 行(如 )的 shell 脚本会被忽略,#!/usr/bin/env bash
因此您可能必须解决这个问题,可能通过构建一个真正的可执行文件来完成这项工作。
如果你必须为它构建一个真正的可执行文件,你可以从下面的 C 代码开始,它是上面 shell 脚本的改编:
#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;
}