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

У меня есть каталог с журналами сбоев, и я бы хотел использовать условный оператор в bash-скрипте на основе команды find.

Файлы журнала хранятся в этом формате:

/var/log/crashes/app-2012-08-28.log /var/log/crashes/otherapp-2012-08-28.log 

Я хочу, чтобы оператор if возвращал true, если есть журнал сбоев для определенного приложения, которое было изменено за последние 5 минут. Команда find которую я буду использовать:

 find /var/log/crashes -name app-\*\.log -mmin -5 

Я не уверен, как правильно включить это в if . Я думаю, это может сработать:

 if [ test `find /var/log/crashes -name app-\*\.log -mmin -5` ] then service myapp restart fi 

Есть несколько областей, где я неясен:

  • Я посмотрел флаги if, но я не уверен, какой из них, если таковой имеется, я должен использовать.
  • Мне нужна директива test или я должен просто обработать результаты команды find напрямую или, возможно, использовать find... | wc -l find... | wc -l чтобы получить счетчик строк?
  • Не 100% необходимо для ответа на этот вопрос, но test для тестирования против возвратных кодов, возвращающих команды? И они вроде невидимы – вне stdout / stderr ? Я прочитал man страницу, но мне все еще неясно, когда использовать test и как его отлаживать.

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

[ и test – синонимы (кроме [ требуется ] ), поэтому вы не хотите использовать [ test :

 [ -x /bin/cat ] && echo 'cat is executable' test -x /bin/cat && echo 'cat is executable' 

test возвращает нулевой статус выхода, если условие истинно, в противном случае отличное от нуля. Это может быть фактически заменено любой программой, чтобы проверить ее статус выхода, где 0 указывает на успех, а ненулевое указывает на отказ:

 # echoes "command succeeded" because echo rarely fails if /bin/echo hi; then echo 'command succeeded'; else echo 'command failed'; fi # echoes "command failed" because rmdir requires an argument if /bin/rmdir; then echo 'command succeeded'; else echo 'command failed'; fi 

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

Для find вам нужно будет проверить, был ли произведен какой-либо вывод. -n тестов для непустой строки:

 if [[ -n $(find /var/log/crashes -name "app-*.log" -mmin -5) ]] then service myapp restart fi 

Полный список тестовых аргументов доступен, вызывая help test в командной строке bash .

Если вы используете bash (а не sh ), вы можете использовать [[ condition ]] , что ведет себя более предсказуемо, когда в вашем состоянии есть пробелы или другие особые случаи. В противном случае это, как правило, совпадает с использованием [ condition ] . Я использовал [[ condition ]] в этом примере, как и когда угодно.

Я также изменил `command` на $(command) , которая также ведет себя аналогично, но лучше с вложенными командами.

find будет успешно завершен, если ошибок не было, поэтому вы не можете рассчитывать на его статус выхода, чтобы узнать, нашел ли он какой-либо файл. Но, как вы сказали, вы можете подсчитать количество найденных файлов и проверить это число.

Это было бы примерно так:

 if [ $(find /var/log/crashes -name 'app-*.log' -mmin -5 | wc -l) -gt 0 ]; then ... fi 

test (aka [ ) не проверяет коды ошибок команд, он имеет специальный синтаксис для выполнения тестов, а затем выходит с кодом ошибки 0, если тест прошел успешно, или 1 в противном случае. Это тот, который проверяет код ошибки команды, которую вы передаете ему, и выполняет его тело на основе этого.

См. man test (или help test , если вы используете bash ), и help if (то же самое).

В этом случае wc -l выведет число. Мы используем опцию -gt для тестирования, если это число больше 0 . Если это так, test (или [ ) вернется с кодом выхода 0 . if интерпретировать этот код выхода как успех, и он будет запускать код внутри своего тела.

Это было бы

 if [ -n "$(find /var/log/crashes -name app-\*\.log -mmin -5)" ]; then 

или

 if test -n "$(find /var/log/crashes -name app-\*\.log -mmin -5)"; then 

Тест команд и [ … ] являются синонимами. Единственное различие – это их имя и тот факт, что [ требуется закрытие ] качестве последнего аргумента. Как всегда, используйте двойные кавычки вокруг подстановки команды, иначе вывод команды find будет разбит на слова, и здесь вы получите синтаксическую ошибку, если имеется более одного соответствующего файла (и когда аргументов нет, [ -n ] истинно, тогда как вы хотите [ -n "" ] который является ложным).

В ksh, bash и zsh, но не в золе, вы также можете использовать [[ … ]] который имеет разные правила синтаксического анализа: [ является обычной командой, тогда как [[ … ]] является другой конструкцией разбора. Вам не нужны двойные кавычки внутри [[ … ]] (хотя они не болят). Вам все еще нужно ; после команды.

 if [[ -n $(find /var/log/crashes -name app-\*\.log -mmin -5) ]]; then 

Это потенциально может быть неэффективным: если в /var/log/crashes много файлов, find обнаружит их все. Вы должны сделать остановку поиска, как только найдет совпадение, или вскоре после этого. С помощью GNU find (не встроенный Linux, Cygwin) используйте -quit primary.

 if [ -n "$(find /var/log/crashes -name app-\*\.log -mmin -5 -print -quit)" ]; then 

В других системах труба find в head по крайней мере, уходить сразу после первого матча (найти будет умирать от разбитой трубы).

 if [ -n "$(find /var/log/crashes -name app-\*\.log -mmin -5 -print | head -n 1)" ]; then 

(Вы можете использовать head -c 1 если ваша head команда поддерживает его.)


Альтернативно, используйте zsh.

 crash_files=(/var/log/crashes/**/app-*.log(mm-5[1])) if (($#crash_files)); then 

Это должно работать

 if find /var/log/crashes -name 'app-\*\.log' -mmin -5 | read then service myapp restart fi 
  • Как сделать вывод для grep неудачным?
  • Bash - ожидаемое целочисленное выражение
  • Поймать неожиданный ввод одиночного символа в bash
  • Правильное литье типов в сценарии оболочки для использования с циклом while и модулем
  • shell scripting - несколько тестов равенства в одном выражении if
  • Использование -n и -z в тестировании встроено - Bash
  • Модернизирован, чтобы проверить ветвь по ошибке в debian ... как я могу вернуться к стабильной?
  • Невозможно сравнить результат lsb_release с строкой в ​​Bash
  • Некоторые ошибки возникли, когда я установил lucene, модуль perl!
  • Interesting Posts

    Порт для вывода / ограничения трафика ebtables

    Почему это не работает, когда средняя загрузка превышает 1?

    заменить путь unix внутри файла

    Как узнать, когда пакет был обновлен в репозитории

    Как я могу следить за питанием веб-камер в Linux

    Deepin OS не обнаруживает внешний монитор, подключенный через HDMI

    По умолчанию tmux config

    Симметричная разностная труба?

    2 Аутентификация фактора в SSH с использованием открытого ключа и юбикея

    Как я могу открыть thunar, чтобы он выбирал конкретный файл?

    Передача вывода средства просмотра VNC на устройство / dev

    Команда для поиска длин файлов / путей, которые слишком велики для записи на DVD?

    Как узнать, сколько времени требуется для выполнения ежедневной работы updatedb?

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

    Как сбросить право собственности на / usr / bin / sudo на centOS?

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