当 snmp pass 调用时,shell 脚本未捕获命令输出
command output not captured by shell script when invoked by snmp pass
问题
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 脚本相同,但我得到相同的空输出。
最后,我的问题
- 为什么 bash 脚本在这两种情况下表现不同?
- bash 脚本存在的问题是否可能与最初注意到的问题相同(手动 运行ning 程序与 SNMPD 运行 程序有不同的输出)?
更新
eewanco 的建议
What user is running the program in each scenario?
我在 bash 脚本中添加了 echo "$(whoami)" > /var/log/snmp-pass-test
,在日志中添加了 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;[=22=]public0$I4-m"..., 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;[=22=]public2$I4-m"..., 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(可能超过)的委托调用。
为了识别它,我 运行 grep AVC /var/log/audit/audit.log
并且对于每个条目,我 运行 以下内容:
echo "<grepped-output>" | audit2allow -a -M <filename>
这将创建一个应该允许委托调用通过的 SELinux 策略包。然后使用以下内容加载包:
semodule -i <filename>.pp
我不得不这样做 5 次,因为有不同的拒绝原因(unix_read unix_write、关联、读写)。我会考虑将这些模块合并为一个。
现在当我 运行 snmpget
我得到正确的委托输出:
SNMPv2-SMI::enterprises.3582.5.1.4.2.1.2.1.32.1 = INTEGER: 34
问题
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 脚本相同,但我得到相同的空输出。
最后,我的问题
- 为什么 bash 脚本在这两种情况下表现不同?
- bash 脚本存在的问题是否可能与最初注意到的问题相同(手动 运行ning 程序与 SNMPD 运行 程序有不同的输出)?
更新
eewanco 的建议
What user is running the program in each scenario?
我在 bash 脚本中添加了 echo "$(whoami)" > /var/log/snmp-pass-test
,在日志中添加了 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;[=22=]public0$I4-m"..., 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;[=22=]public2$I4-m"..., 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(可能超过)的委托调用。
为了识别它,我 运行 grep AVC /var/log/audit/audit.log
并且对于每个条目,我 运行 以下内容:
echo "<grepped-output>" | audit2allow -a -M <filename>
这将创建一个应该允许委托调用通过的 SELinux 策略包。然后使用以下内容加载包:
semodule -i <filename>.pp
我不得不这样做 5 次,因为有不同的拒绝原因(unix_read unix_write、关联、读写)。我会考虑将这些模块合并为一个。
现在当我 运行 snmpget
我得到正确的委托输出:
SNMPv2-SMI::enterprises.3582.5.1.4.2.1.2.1.32.1 = INTEGER: 34