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

Как я могу переписать эту команду только по электронной почте, если есть выход из mailq | grep mailq | grep ?

 mailq | egrep 'rejected|refused' -A 5 -B 5 | mail -s 'dd' email@email 

Возможно ли это на одной линии?

См. Раздел Проверка наличия пустого канала и запуск команды на данные, если это не для более общего случая, чем отправка электронной почты.

8 Solutions collect form web for “Как перенести вывод из одного процесса в другой, но только выполнить, если первый имеет выход?”

Я думаю, вам придется использовать временный файл для этой операции, чтобы вы могли использовать оператор && только для запуска команды mail, если grep вернул статус выхода, в котором говорится, что он имеет такие совпадения:

 TMPFILE=`mktemp /tmp/mailqgrep.XXXXXX`; mailq | egrep 'rejected|refused' -A5 -B5 > "$TMPFILE" && mail -s 'dd' email@email < "$TMPFILE"; rm "$TMPFILE" 

Если вы не возражаете, что временный файл где-то торчит и может использовать статическое имя для него, вы можете пропустить специальные материалы для именования и удаления:

  mailq | egrep 'rejected|refused' -A5 -B5 > /tmp/mailqgrep && mail -s 'dd' email@email < /tmp/mailqgrep 

Edit: После просмотра ответа Гленна я сыграл с этим еще несколько и, видимо, назначил переменную, используя синтаксис $() возвращает код выхода команды, поэтому вы можете пропустить тест, который он использовал для длины строки, и использовать это вместо этого. Здесь все в одной команде:

 data=$(mailq | egrep 'rejected|refused' -A 5 -B 5) && mail -s 'dd' email@email <<< "$data" 

Редактировать 2: После просмотра ответа Саймона я проверил свою mail программу. Он не ведет себя так, как он описывает по умолчанию, но имеет для этого вариант. На странице руководства:

-E Если исходящее сообщение не содержит текста в его первой или единственной части сообщения, не отправляйте его, а отбрасывайте его молча, эффективно устанавливая переменную skipemptybody при запуске программы. Это полезно для отправки сообщений из скриптов, запущенных cron (8).

Сделав это возможным:

 mailq | egrep 'rejected|refused' -A 5 -B 5 | mail -E -s 'dd' email@email 

Вы можете сохранить вывод в переменной, а затем вызвать команду mail, если длина строки отлична от нуля.

 data=$(mailq | egrep 'rejected|refused' -A 5 -B 5) [[ -n "$data" ]] && mail -s 'dd' email@email <<< "$data" 

Для одной строки присоедините две команды с помощью двоеточия.

Программа утилиты ifne существует для этой цели: для запуска команды, если стандартный ввод не пуст.

 mailq | egrep 'rejected|refused' -A 5 -B 5 | ifne mail -s 'dd' email@email 

Команда ifne является частью пакета moreutils , объявленного как «растущая коллекция инструментов Unix, которую никто не думал писать давно, когда Unix был молод».

Используйте mail с параметром -E . На моем Mac MAIL (1) говорит, что флаг -E не отправляет электронное письмо с пустым телом.

-E Не отправлять сообщения с пустым телом. Это полезно для ошибок трубопровода из скриптов cron (8).

На моем Mac я проверил следующий тест. Обратите внимание, что файл file_does_exist существует, но файл file_does__not_exist не существует.

Это отправляет мне электронное письмо:

 $ ls file_does_exist | egrep 'file' -A5 -B5 | mailx -E -s 'test' stefan@example.org 

Это не так. Обратите внимание, что команда ls file_does_not_exist | egrep ... ls file_does_not_exist | egrep ... не производит никакого вывода.

 $ ls file_does_not_exist | egrep 'file' -A5 -B5 | mailx -E -s 'test' stefan@example.org ls: file_does_not_exist: No such file or directory 

В этом конкретном случае, если ваша mail поддерживает параметр -E , просто используйте его. В общем случае вы можете попробовать прочитать один символ; если он есть, запустите команду постобработки и подайте этот символ из остальной части файла.

 pipe_if_not_empty () { a=$(dd bs=1 count=1 2>/dev/null; echo .) # read at most one character if [ "$a" != "." ]; then # if there were two characters, { printf %s "${a%.}"; # then output the first character cat; } | # and the rest of the input "$@" # into the specified program fi } mailq | egrep 'rejected|refused' -A 5 -B 5 | pipe_if_not_empty mail -s 'dd' email@email 

Обратите внимание на полезное использование cat . Добавление echo . заставляет эту функцию работать, даже если первый символ на входе является символом новой строки (помните, что конструкция $(…) расшифровывает терминалы newlines).

С большинством оболочек (ничего, кроме zsh, насколько я знаю), если файл начинается с нулевого символа, этот код будет считать, что он пуст. Исправление, которое остается для упражнения читателем. (Подсказка: используйте od в первой подоболочке и printf для печати первого байта.) (Решение: как проверить, является ли канал пустым ). Вы можете столкнуться с той же проблемой, если файл начинается с байта, который не является допустимым символом в текущий язык; это легче исправить, запустив этот код с помощью LC_ALL=C

IIRC mail команда BSD прерывается, если задано пустое сообщение.

Вы можете переписать свою команду с помощью test -s /dev/stdin чтобы проверить, есть ли какой-либо вывод из mailq | grep mailq | grep часть.

 - mailq | egrep 'rejected|refused' -A 5 -B 5 | mail -s 'dd' email@email + mailq | egrep 'rejected|refused' -A 5 -B 5 | (test -s /dev/stdin && cat) | mail -s 'dd' email@email 

Недавно я узнал о имени команды ifne которое является частью пакета moreutils . Где вы можете использовать его для решения этой конкретной проблемы.

ifne – команда запуска, если стандартный ввод не пуст

пример из справочной страницы,

 EXAMPLE find . -name core | ifne mail -s "Core files found" root 
  • Статус выхода apt-get update
  • Правильное текстовое название для <<
  • Я в замешательстве, почему «| true "в make-файле имеет тот же эффект, что и" || правда"
  • Печать stderr только в том случае, если в stdout ничего не записано, иначе распечатайте только stdout, отбрасывая stderr
  • начать процесс из ssh и иметь возможность закрыть соединение
  • Могу ли я использовать modulecmd с раковиной?
  • Команды соединения в unix
  • Fish Shell: как установить несколько переменных среды из файла с помощью экспорта
  • Diff stdin после прокладки его через команду
  • pipe stdout-to-file с wc
  • Как передать результат предыдущей команды узлу в качестве переменной?
  • Interesting Posts

    Какие настройки вы сделали в своем профиле оболочки, чтобы повысить производительность?

    количество сеансов ssh, разрешенных с сервера

    Как включить режим восстановления зоны памяти на ядре Linux?

    почему моя конфигурация портативного компьютера игнорируется?

    Передача аргументов из файла в сценарий bash

    Различия между Debian и Ubuntu для ноутбуков практичны

    Как определить, видно ли окно рабочего стола в Xfce?

    перенаправить вывод для команды, которая принимает несколько аргументов

    Файл открывается автоматически в вкладках

    Захват нового результата после удаления выходного файла

    crontab каждые 12 часов – когда он отправит электронное письмо?

    Являются ли данные дешифрованы и повторно зашифрованы сервером OpenVPN при отправке между клиентами?

    Как определить фальшивый почтовый источник?

    Сервер OpenVPN на кластере Kubernetes / DNS и разрешении обслуживания

    «Cut» зависает при использовании «tail -f» в сочетании с «tr»,

    Linux и Unix - лучшая ОС в мире.