为什么 systemctl 在 NRPE 检查中没有 return 值?
Why systemctl doesn't return a value in an NRPE check?
我写的 NRPE 检查有问题。
这是一个简单的 shell 脚本,运行 "systemctl is-active [service_name]" 和 return 对我们的 Thruk 的价值。
当我 运行 直接使用用户 nrpe 的脚本时,它有效:
-bash-4.2$ /usr/lib64/nagios/plugins/check_service_active.sh --service dynflowd
dynflowd
Service dynflowd démarré
但是当我在本地使用 NRPE 运行 它时,它告诉我服务已停止:
-bash-4.2$ ./check_nrpe -H 127.0.0.1 -c check_service_active -a 'dynflowd'
dynflowd
Service dynflowd arrêté
经过多次测试,我发现它与systemctl命令有关。
当我用 "echo" 等另一个命令替换 systemctl 时,它起作用了。
所以我认为 NRPE 和 systemctl 有一些东西,但我找不到什么?
我在 Google.
上找不到任何相关信息
所以我来了!
预先感谢您的回复,如果我的理解不够,请见谅。
这是我的脚本:
#!/bin/sh
#
# Script d'interrogation d'un service via systemctl
# Nagios return codes
STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
STATE_UNKNOWN=3
STATE_DEPENDENT=4
#Recuperation des parametres
while test -n ""; do
case "" in
--service)
SERV=
shift
;;
-u)
print_usage
exit $STATE_OK
;;
esac
shift
done
STAT=$(systemctl is-active $SERV)
if [[ $STAT == "active" ]]
then
echo "Service $SERV démarré"
exit $STATE_OK
else
echo "Service $SERV arrêté"
exit $STATE_CRITICAL
fi
好的,类似于 cron
工作,可能 是 NRPE(服务器)运行 与您的 [=78] 具有不同的环境=],并且那个独特的环境在某种程度上不正确 运行ning 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
脚本,该脚本将由(和因此 运行 as) 允许 运行 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
[[ "" = "${service}" ]] && result=""
done
# If it IS allowed, get actual status.
[[ -z "${result}" ]] && result="$(/usr/bin/systemctl is-active "")"
echo "${result}"
可能有 其他 方法(它们可能更好)但如果这确实是问题所在,那应该是一个好的开始。
请注意,我认为 setuid
对于具有 shebang 行(如 #!/usr/bin/env bash
)的 shell 脚本会被忽略,因此您可能需要解决这个问题,可能是通过构建一个真正的可执行文件来完成这项工作。
如果您必须为其构建一个真正的可执行文件,您可以从以下 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;
}
我终于找到问题了:NRPE版本!!!
在我的服务器上,NRPE 在 nrpe-3.2.1-6
.
我 运行 我的脚本通过另一台服务器上的 NRPE 运行并且有效。
这台服务器 运行s nrpe-3.2.1-8
.
所以解决方案是:更新 !
感谢您的宝贵时间和想法,尤其是 >> /tmp/paxdebug.dynflowd 2>&1
帮助我解决问题的想法。
我写的 NRPE 检查有问题。
这是一个简单的 shell 脚本,运行 "systemctl is-active [service_name]" 和 return 对我们的 Thruk 的价值。
当我 运行 直接使用用户 nrpe 的脚本时,它有效:
-bash-4.2$ /usr/lib64/nagios/plugins/check_service_active.sh --service dynflowd
dynflowd
Service dynflowd démarré
但是当我在本地使用 NRPE 运行 它时,它告诉我服务已停止:
-bash-4.2$ ./check_nrpe -H 127.0.0.1 -c check_service_active -a 'dynflowd'
dynflowd
Service dynflowd arrêté
经过多次测试,我发现它与systemctl命令有关。 当我用 "echo" 等另一个命令替换 systemctl 时,它起作用了。
所以我认为 NRPE 和 systemctl 有一些东西,但我找不到什么? 我在 Google.
上找不到任何相关信息所以我来了!
预先感谢您的回复,如果我的理解不够,请见谅。
这是我的脚本:
#!/bin/sh
#
# Script d'interrogation d'un service via systemctl
# Nagios return codes
STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
STATE_UNKNOWN=3
STATE_DEPENDENT=4
#Recuperation des parametres
while test -n ""; do
case "" in
--service)
SERV=
shift
;;
-u)
print_usage
exit $STATE_OK
;;
esac
shift
done
STAT=$(systemctl is-active $SERV)
if [[ $STAT == "active" ]]
then
echo "Service $SERV démarré"
exit $STATE_OK
else
echo "Service $SERV arrêté"
exit $STATE_CRITICAL
fi
好的,类似于 cron
工作,可能 是 NRPE(服务器)运行 与您的 [=78] 具有不同的环境=],并且那个独特的环境在某种程度上不正确 运行ning 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
脚本,该脚本将由(和因此 运行 as) 允许 运行 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
[[ "" = "${service}" ]] && result=""
done
# If it IS allowed, get actual status.
[[ -z "${result}" ]] && result="$(/usr/bin/systemctl is-active "")"
echo "${result}"
可能有 其他 方法(它们可能更好)但如果这确实是问题所在,那应该是一个好的开始。
请注意,我认为 setuid
对于具有 shebang 行(如 #!/usr/bin/env bash
)的 shell 脚本会被忽略,因此您可能需要解决这个问题,可能是通过构建一个真正的可执行文件来完成这项工作。
如果您必须为其构建一个真正的可执行文件,您可以从以下 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;
}
我终于找到问题了:NRPE版本!!!
在我的服务器上,NRPE 在 nrpe-3.2.1-6
.
我 运行 我的脚本通过另一台服务器上的 NRPE 运行并且有效。
这台服务器 运行s nrpe-3.2.1-8
.
所以解决方案是:更新 !
感谢您的宝贵时间和想法,尤其是 >> /tmp/paxdebug.dynflowd 2>&1
帮助我解决问题的想法。