У нас есть задание cron, которое отправляет данные в другую компанию с помощью SCP. Команда выглядит так:
10 0 * * * ssh USER@LOCAL-SERVER 'scp -q ~/some/dir/* REMOTE_SERVER:/other/dir/' >> ~/log/some.log
Это было настроено кем-то другим. Теперь моя проблема в том, что мой босс находится в списке рассылки cron, и, несмотря на то, что cron ">> ~ / log / some.log" по-прежнему отправляет электронное письмо каждый день, потому что даже если передача прошла успешно, он все равно выводит:
Connection to REMOTE_SERVER 12345 port [tcp/*] succeeded!
И мой босс не хочет получать это письмо, если только не произойдет ошибка.
Команда действительно находится внутри скрипта, который я пропустил, чтобы упростить вопрос. Он работает на сервере RHEL 6. Но поскольку это единственная линия, в которой мы разговариваем с REMOTE_SERVER, она должна исходить оттуда. И причина, по которой мы выполняем команду на LOCAL-SERVER (Ubuntu 10.04.4 LTS), заключается в том, что мы находимся на сервере БД, который не может пройти через брандмауэр, поэтому мы сначала копируем данные на другой локальный сервер и загружаем их оттуда.
При использовании без -q я также получаю следующий результат:
SSH Server supporting SFTP and SCP
Я не хочу перенаправлять весь вывод stderr, потому что я все равно хочу получать электронное письмо при возникновении ошибки.
Я не думаю, что ты можешь перенаправить STDERR
выводить выборочно без переписывания программы для записи этих конкретных сообщений в STDOUT
вместо того STDERR
. Однако вы можете написать сценарий оболочки, который отфильтровывает нежелательное сообщение, и запустить этот сценарий в cron
работа.
#!/bin/bash
(ssh USER@LOCAL-SERVER ... 3>&1 1>&2- 2>&3-) 2>> ~/log/some.log \
| grep -v "Connection .* succeeded" 1>&2
exit $?
Из любопытства, почему вы не запускаете cron
работа с scp
команда прямо на LOCAL-SERVER?
Редактировать: Вы хотите отфильтровать некоторые STDERR
вывод при перенаправлении всех STDOUT
вывод в файл, но труба может подключаться STDOUT
одного процесса STDIN
другого процесса. |&
или 2>&1 |
не сработает, потому что STDOUT
уже перенаправлен на ~/log/some.log
, поэтому в конвейер ничего не попадет, а в вашем файле журнала будет много нежелательного вывода.
Однако можно поменять местами дескрипторы, чтобы STDOUT
на самом деле идет в STDERR
и STDERR
на самом деле идет в STDOUT
. Затем вы можете перенаправить все STDERR
вывод в файл журнала и отфильтруйте STDOUT
вывод через grep
. Кто-то в переполнение стека опубликовал этот аккуратный трюк. В 1>&2
возвращает отфильтрованный вывод обратно в STDERR
.
Предполагая, что вы используете BASH:
Поменяйте местами stdout и stderr, сначала поместив дублирование:
2> & 1 >> ~ / log / some.log ssh ПОЛЬЗОВАТЕЛЬ @ ЛОКАЛЬНЫЙ-СЕРВЕР 'scp -q ~ / some / dir / * REMOTE_SERVER: / other / dir /'
Затем вы настраиваете канал для захвата всего, что собирается на stderr:
2> & 1 >> ~ / log / some.log ssh ПОЛЬЗОВАТЕЛЬ @ LOCAL-SERVER 'scp -q ~ / some / dir / * REMOTE_SERVER: / other / dir /' |
И grep только для неудачных сообщений:
2> & 1 >> ~ / log / some.log ssh ПОЛЬЗОВАТЕЛЬ @ LOCAL-SERVER 'scp -q ~ / some / dir / * REMOTE_SERVER: / other / dir /' | grep -E "сообщение об ошибке"
В результате будет получен результат, который cron получит и включит в свое сообщение MAIL. Все остальные выходные данные "stderr" исчезнут (будут потеряны). Если по какой-то причине вы хотите сохранить копию всего stderr, то сначала используйте команду tee:
2> & 1 >> ~ / log / some.log ssh ПОЛЬЗОВАТЕЛЬ @ LOCAL-SERVER 'scp -q ~ / some / dir / * REMOTE_SERVER: / other / dir /' | tee -a ~ / log / some_other.log | grep -E "сообщение об ошибке"
который поместит копию ВСЕГО stderr в новый файл журнала, а затем только сообщения об ошибках попадут в электронную почту CRON.