Как сделать так, чтобы SCP на Linux выводил "успех" на стандартный вывод вместо стандартного?

У нас есть работа cron, которая отправляет материал в другую компанию, используя SCP. Команда выглядит так:

 10 0 * * * ssh USER@LOCAL-SERVER 'scp -q ~/some/dir/* REMOTE_SERVER:/other/dir/' >> ~/log/some.log

Это было настроено кем-то другим. Теперь моя проблема в том, что мой босс находится в списке рассылки cron, и, несмотря на то, что ">> ~/log/some.log" cron по-прежнему отправляет электронное письмо каждый день, потому что даже если передача прошла успешно, он все равно выдает:

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, потому что я все еще хочу получить электронное письмо, когда есть ошибка.

2 ответа

Решение

Я не думаю, что вы можете перенаправить 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 команда прямо на ЛОКАЛЬНО-СЕРВЕРНОЙ?

Изменить: вы хотите отфильтровать некоторые из STDERR вывод при перенаправлении всех STDOUT вывод в файл, но канал может подключиться STDOUT одного процесса в STDIN другого процесса. |& или же 2>&1 | не будет работать, потому что STDOUT уже перенаправлен на ~/log/some.logТаким образом, в канал ничего не попадет, и в вашем файле журнала будет много нежелательных выходных данных.

Тем не менее, можно поменять дескрипторы так, чтобы STDOUT на самом деле идет в STDERR а также STDERR на самом деле идет в STDOUT, Тогда вы можете перенаправить все STDERR вывод в файл журнала и отфильтровать STDOUT вывод через grep, Кто-то из стека overoverflow опубликовал этот аккуратный трюк. 1>&2 возвращает отфильтрованный вывод обратно в STDERR,

Предполагая, что вы используете BASH:

Поменяйте местами stdout и stderr, поставив дублирование первым:

2> & 1 >> ~ / log / some.log ssh ПОЛЬЗОВАТЕЛЬ @LOCAL-SERVER '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 "сообщение об ошибке"

который поместит копию ALL stderr в новый файл журнала, а затем только сообщения об ошибках попадут в электронную почту CRON.

Другие вопросы по тегам