Как сделать так, чтобы 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.