Назад | Перейти на главную страницу

Как заставить SCP в Linux выводить «успешно» на stdout вместо stderr?

У нас есть задание 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.