вывод команды не захватывается сценарием оболочки при вызове через snmp pass

Проблема

SNMPD правильно делегирует запросы опроса SNMP другой программе, но ответ от этой программы недействителен. Ручной запуск программы с теми же аргументами работает корректно.

Деталь

Я установил на сервер правильные драйверы рейда LSI и хочу настроить SNMP. В соответствии с инструкциями я добавил следующее в /etc/snmp/snmpd.conf для перенаправления запросов опроса SNMP с заданным префиксом OID в программу:

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 делегирует вызов и регистрирует предоставленные аргументы и выходные данные делегированного вызова:

#!/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)?

Обновления

предложения eewanco

Какой пользователь запускает программу в каждом сценарии?

Я добавил echo "$(whoami)" > /var/log/snmp-pass-test в скрипт bash, а root добавил в логи

Может попробовать запустить в cron

Добавление следующего в crontab root и правильный трехстрочный ответ был зарегистрирован:

* * * * * /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

Предложение Гриши Левита

Попробуйте зарегистрировать stderr

Ошибок не зарегистрировано

Проверка /var/log/messages

Когда я запускаю его через SNMPD, я получаю MegaRAID SNMP AGENT: Error in getting Shared Memory(lsi_mrdsnmpmain) в журнале. Когда я запускаю его напрямую, я этого не делаю. Я немного погуглил и может потребоваться установка lm_sensors; Я попробую это.

Я установил lm_sensors & compat-libstdc++-33.i686 (последний, потому что он сказал, что это обязательное условие из инструкций, и я его пропустил), удалил и переустановил драйверы LSI и столкнулся с той же проблемой.

SELinux

Я случайно наткнулся на страницу о расширении snmpd скриптами и он говорит проверить, что сценарий имеет правильный контекст 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)

Попробуйте использовать strace с snmp и без него и посмотрите, сможете ли вы поймать ошибку системного вызова или какие-то дополнительные подсказки.

Для полноты картины я хотел посмотреть, намекает ли 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 +++

person PhilJ    schedule 31.01.2017    source источник
comment
Какой пользователь запускает программу в каждом сценарии? Что произойдет, если вы используете su для запуска команды, используя пользователя, который запускает программу в snmpd, если это другой пользователь? Возможно, попробуйте выполнить его в cron или at, чтобы увидеть, есть ли у вас похожая проблема, связана ли она со средой выполнения.   -  person eewanco    schedule 01.02.2017
comment
Это root в обоих сценариях. Я заметил, что вывод «env» был разным для обоих, поэтому я удостоверился, что у меня есть «экспорт» для каждого из них в сценарии bash в качестве теста, прежде чем сценарий bash делегировал вызов. Я получил тот же ответ «Ошибка в упаковщике» с присутствующими переменными среды   -  person PhilJ    schedule 01.02.2017
comment
Попробуйте также зарегистрировать stderr, например RETURN=$(/usr/sbin/lsi_mrdsnmpmain $@ 2>&1)   -  person Grisha Levit    schedule 01.02.2017
comment
Попробуйте использовать strace с snmp и без него и посмотрите, сможете ли вы поймать ошибку системного вызова или какие-то дополнительные подсказки. Вам придется перенаправить stderr с помощью 2>&1 или чего-то подобного. Тупой вопрос: Вы используете джейл chroot? Я не думаю, что вы, но если это так и /proc и /sys не смонтированы в нем, у вас могут быть проблемы.   -  person eewanco    schedule 01.02.2017


Ответы (1)


Именно 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
person PhilJ    schedule 01.02.2017
comment
Ура! Это довольно неясно. Слава тому, что разобрался! - person eewanco; 01.02.2017
comment
Спасибо. SELinux — одна из моих слепых зон, о которой у меня не было причин узнавать раньше; Думаю, сейчас самое время! - person PhilJ; 02.02.2017