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

标签 bash shell selinux snmpd

问题

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

详情

我已经在服务器上安装了正确的 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程序在本例中

正常工作

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

#!/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 脚本的日志记录显示捕获的委托(delegate)调用输出为空:

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 运行程序有不同的输出)?

更新

eewanco的建议

What user is running the program in each scenario?

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

Maybe try executing it in 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 的建议

Try logging the stderr

没有任何错误记录

检查/var/log/messages

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

我安装了 lm_sensors & 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 的建议)

Try using strace with and without snmp and see if you can catch a system call failure or some additional hints

为了完整起见,我想看看 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 +++

最佳答案

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

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

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

这会创建一个应该允许委托(delegate)调用通过的 SELinux 策略包。然后使用以下方法加载包:

semodule -i <filename>.pp

我不得不这样做 5 次,因为有不同的拒绝原因(unix_read unix_write、associate、read write)。我会考虑将这些模块合并为一个。

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

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

关于bash - 由 snmp pass 调用时,shell 脚本未捕获命令输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41967095/

相关文章:

bash - 如何在 awk 脚本中的搜索模式中使用变量

Bash:如何从输出中删除 xargs 产生的错误消息?

shell - 关于 KornShell 中的 'for' 循环

Linux shell 脚本没有完全作为桌面快捷方式执行

linux - Varnish 4.0.1 无法在 CentOS 7 上启动 - selinux 问题

java - svn PRE-COMMIT Hook 扫描java类内容

bash - 检查文件所有者权限

bash - 我怎么知道我是否在子 shell 中

启用了 selinux 的 Docker - 不允许在/usr 中重新标记内容

Redis 转储.rdb |不是默认目录