snmp pass调用时,shell脚本未捕获的命令输出

时间:2017-01-31 20:41:16

标签: bash shell selinux snmpd

问题

SNMPD正确地将SNMP轮询请求委派给另一个程序,但该程序的响应无效。手动运行具有相同参数的程序正确响应。

详细信息

我已在服务器上安装了正确的LSI raid驱动程序,并且想要配置SNMP。根据说明,我已将以下内容添加到/etc/snmp/snmpd.conf,以将具有给定OID前缀的SNMP轮询请求重定向到程序:

pass .1.3.6.1.4.1.3582 /usr/sbin/lsi_mrdsnmpmain

对于SNMP轮询请求,它无法正常工作:

snmpget -v1 -c public localhost .1.3.6.1.4.1.3582.5.1.4.2.1.2.1.32.1

我收到以下回复:

Error in packet
Reason: (noSuchName) There is no such variable name in this MIB.
Failed object: SNMPv2-SMI::enterprises.3582.5.1.4.2.1.2.1.32.1

我尝试了什么

SNMPD传递两个参数-g<oid>,并期望三行响应<oid><data-type><data-value>

如果我手动运行以下内容:

/usr/sbin/lsi_mrdsnmpmain -g .1.3.6.1.4.1.3582.5.1.4.2.1.2.1.32.0

我正确地得到了正确的三行响应:

.1.3.6.1.4.1.3582.5.1.4.2.1.2.1.32.0
integer
30

这意味着pass命令工作正常且/usr/sbin/lsi_mrdsnmpmain程序正常工作在此示例中

我尝试用bash脚本替换/usr/sbin/lsi_mrdsnmpmain。 bash脚本委托调用并记录提供的参数和委托调用的输出:

#!/bin/bash
echo "In: '$@" > /var/log/snmp-pass-test
RETURN=$(/usr/sbin/lsi_mrdsnmpmain $@)
echo "$RETURN"
echo "Out: '$RETURN'" >> /var/log/snmp-pass-test

并修改了pass命令以重定向到bash脚本。如果我手动运行bash脚本/usr/sbin/snmp-pass-test -g .1.3.6.1.4.1.3582.5.1.4.2.1.2.1.32.0,我会得到正确的三行响应,就像我手动运行/usr/sbin/lsi_mrdsnmpmain时一样,我得到以下记录:

In: '-g .1.3.6.1.4.1.3582.5.1.4.2.1.2.1.32.0
Out: '.1.3.6.1.4.1.3582.5.1.4.2.1.2.1.32.0
integer
30'

当我重新运行snmpget测试时,我得到相同的Error in packet...错误,并且bash脚本的日志记录显示捕获的委托调用输出为空:

In: '-g .1.3.6.1.4.1.3582.5.1.4.2.1.2.1.32.0
Out: ''

如果我修改bash脚本只回显空行,我也会得到相同的Error in packet...消息。

我还尝试确保手动调用/usr/sbin/lsi_mrdsnmpmain时出现的环境变量对于bash脚本是相同的,但我得到相同的空输出。

最后,我的问题

  1. 为什么bash脚本在这两种情况下的表现会有所不同?
  2. bash脚本中存在的问题是否与最初注意到的相同(手动运行的程序与SNMPD运行程序有不同的输出)?
  3. 更新

    eewanco的建议

      

    每个场景中用户正在运行什么程序?

    我在bash脚本中添加了echo "$(whoami)" > /var/log/snmp-pass-test,并在日志中添加了root

      

    也许尝试在cron中执行它

    将以下内容添加到root的crontab中并记录正确的三行响应:

    * * * * * /usr/sbin/lsi_mrdsnmpmain -g .1.3.6.1.4.1.3582.5.1.4.2.1.2.1.32.1 >> /var/log/snmp-test-cron 2>&1
    

    Grisha Levit的建议

      

    尝试记录stderr

    没有记录任何错误

    检查/ var / log / messages

    当我通过SNMPD运行时,我会记录MegaRAID SNMP AGENT: Error in getting Shared Memory(lsi_mrdsnmpmain)。当我直接运行它时,我不会。我已经完成了一些谷歌搜索和I may need lm_sensors installed;我试试这个。

    我安装了lm_sensors&amp; compat-libstdc ++ - 33.i686(后者因为它说它是指令的先决条件而我错过了它),卸载并重新安装了LSI驱动程序并遇到了同样的问题。

    SELinux的

    我意外地偶然发现a page about extending snmpd with scripts并且它说要检查脚本是否具有正确的SELinux上下文。我在运行grep AVC /var/log/audit/audit.log | grep snmp之前和之后运行了snmpget,并添加了以下条目作为运行snmpget的直接结果:

    type=AVC msg=audit(1485967641.075:271): avc:  denied  { unix_read unix_write } for  pid=5552 comm="lsi_mrdsnmpmain" key=558265  scontext=system_u:system_r:snmpd_t:s0 tcontext=system_u:system_r:initrc_t:s0 tclass=shm
    

    我现在假设 SELinux导致呼叫失败;我会进一步挖掘......请参阅解决方案。

    strace(eewanco的建议)

      

    尝试使用带有和不带snmp的strace,看看是否可以捕获系统调用失败或其他一些提示

    为了完整起见,我想知道strace是否会暗示SELinux否认了。我不得不使用semodule -r <policy-package-name>删除策略包以重新引入问题,然后执行以下操作:

    strace snmpget -v1 -c public localhost .1.3.6.1.4.1.3582.5.1.4.2.1.2.1.32.1 >> strace.log 2>&1
    

    strace.log的结尾如下,除非我遗漏某些内容,否则它似乎无法提供任何提示:

    ...
    sendmsg(3, {msg_name(16)={sa_family=AF_INET, sin_port=htons(161),     sin_addr=inet_addr("127.0.0.1")}, msg_iov(1)=    [{"0;\2\1\0\4\20public\240$\2\4I\264-m\2"..., 61}], msg_controllen=32,     {cmsg_len=28, cmsg_level=SOL_IP, cmsg_type=, ...}, msg_flags=0},     MSG_DONTWAIT|MSG_NOSIGNAL) = 61
    select(4, [3], NULL, NULL, {0, 999997}) = 1 (in [3], left {0, 998475})
    brk(0xab9000)                           = 0xab9000
    recvmsg(3, {msg_name(16)={sa_family=AF_INET, sin_port=htons(161),     sin_addr=inet_addr("127.0.0.1")}, msg_iov(1)=    [{"0;\2\1\0\4\20public\242$\2\4I\264-m\2"..., 65536}],     msg_controllen=0, msg_flags=0}, MSG_DONTWAIT) = 61
    write(2, "Error in packet\nReason: (noSuchN"..., 81Error in packet
    Reason: (noSuchName) There is no such variable name in this MIB.
    ) = 81
    write(2, "Failed object: ", 15Failed object: )         = 15
    write(2, "SNMPv2-SMI::enterprises.3582.5.1"..., 48SNMPv2-        SMI::enterprises.3582.5.1.4.2.1.2.1.32.1
    ) = 48
    write(2, "\n", 1
    )                       = 1
    brk(0xaa9000)                           = 0xaa9000
    close(3)                                = 0
    exit_group(2)                           = ?
    +++ exited with 2 +++
    

1 个答案:

答案 0 :(得分:3)

SELinux拒绝了snmpd对/ usr / sbin / lsi_mrdsnmpmain(可能超出)的委托调用。

为了识别它,我运行了grep AVC /var/log/audit/audit.log,对于每个条目,我运行了以下内容:

echo "<grepped-output>" | audit2allow -a -M <filename>

这将创建一个SELinux策略包,该策略包应该允许委派的调用。然后使用以下方法加载包:

semodule -i <filename>.pp

我必须这样做5次,因为有不同的拒绝原因(unix_read unix_write,associate,read write)。我希望将模块合并为一个。

现在,当我运行snmpget时,我得到了正确的委托输出:

SNMPv2-SMI::enterprises.3582.5.1.4.2.1.2.1.32.1 = INTEGER: 34