Shell 为什么systemctl没有';在NRPE检查中是否不返回值?

Shell 为什么systemctl没有';在NRPE检查中是否不返回值?,shell,systemctl,nrpe,thruk,Shell,Systemctl,Nrpe,Thruk,我写的NRPE支票有问题 它是一个简单的shell脚本,运行“systemctl是活动的[service_name]”,并将值返回给我们的Thruk 当我直接使用用户nrpe运行脚本时,它可以工作: -bash-4.2$ /usr/lib64/nagios/plugins/check_service_active.sh --service dynflowd dynflowd Service dynflowd démarré 但当我在本地使用NRPE运行它时,它告诉我服务已停止: -bash-4

我写的NRPE支票有问题

它是一个简单的shell脚本,运行“systemctl是活动的[service_name]”,并将值返回给我们的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有些问题,但我找不到什么? 我在谷歌上找不到任何关于它的信息

我来了

提前感谢您的回复,如果我不能理解,请原谅

这是我的剧本:

#!/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 "$1"; do
        case "$1" in
                --service)
                        SERV=$2
                        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(服务器)在与您的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启动实例中到底发生了什么

希望它会说一些简单的东西,比如
找不到systemctl
(表示路径问题),但是,不管它给了你什么,它都应该有助于准确地找出问题所在


更新1:根据您的评论,尝试运行
systemctl
会导致:

systemctl: command not found
这几乎可以肯定,因为这条路是错的。您可以通过在我发布的调试代码中添加以下行来检查路径:

echo "PATH is [$PATH]"
若要修复此问题,请修改脚本中的路径以包含
/usr/bin
(假设该路径位于
systemctl
所在的位置),或者只运行绝对路径(在调试和原始区域中):


更新2:根据您的评论,使用绝对路径后,您现在可以获得:

/usr/lib64/nagios/plugins/check_service_active.sh: line 32:
    /usr/bin/systemctl: Permission denied
这可能是以低权限级别运行的NRPE,或者是以不同的用户身份运行的NRPE,以提供免受攻击的安全性。考虑到中央系统对系统运行的重要性,允许不受限制地访问它是不明智的

因此,与上一次更新类似,将以下内容添加到调试区域:

/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}"
也许还有其他方法(也许更好),但如果这确实是个问题的话,那应该是一个好的开始


请注意,对于具有shebang行的shell脚本(如
#!/usr/bin/env bash
),我认为
setuid
被忽略,因此您可能需要解决这个问题,可能需要构建一个真正的可执行文件来完成这项工作

如果您确实需要为它构建一个真正的可执行文件,那么可以从以下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;
}
#包括
#包括
#包括
int main(int argc,字符**argv){
//检查提供的服务名称。
如果(argc<2){
认沽权(“已提供”);
返回1;
}
//检查允许的服务名称。
静态字符*允许[]={“dynflowd”,NULL};
允许int=0;
for(char**service=&(允许[0]);*service!=NULL;service++){
if(strcmp(*服务,argv[1])==0){
i允许=1;
打破
}
}
如果(!不允许){
puts(“InvalidServiceName”);
返回1;
}
//尝试为命令分配内存。
char*prefix=“/usr/bin/systemctl处于活动状态”;
char*cmdBuff=malloc(strlen(前缀)+strlen(argv[1])+1);
如果(cmdBuff==NULL){
出售(“失忆”);
返回1;
}
//执行命令,释放内存,然后返回。
sprintf(cmdBuff,“%s%s”,前缀,argv[1]);
系统(cmdBuff);
免费(cmdBuff);
返回0;
}

好的,与
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启动实例中到底发生了什么

希望它会说一些简单的东西,比如
找不到systemctl
(表示路径问题),但是,不管它给了你什么,它都应该有助于准确地找出问题所在


更新1:根据您的评论,尝试运行
systemctl
会导致:

systemctl: command not found
这几乎可以肯定,因为这条路是错的。您可以通过在我发布的调试代码中添加以下行来检查路径:

echo "PATH is [$PATH]"
若要修复此问题,请修改脚本中的路径以包含
/usr/bin
(假设该路径位于
systemctl
所在的位置),或者只运行绝对路径(在调试和原始区域中):


更新2:根据您的评论,使用绝对路径后,您现在可以获得:

/usr/lib64/nagios/plugins/check_service_active.sh: line 32:
    /usr/bin/systemctl: Permission denied
这可能是以低权限级别运行的NRPE,或者是以不同的用户身份运行的NRPE,以提供免受攻击的安全性。