У меня есть каталог с журналами сбоев, и я хотел бы использовать условный оператор в скрипте 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
вместо этого счетчик строк? - Не на 100% необходимо ответить на этот вопрос, но
test
для проверки на коды возврата возвращаются команды? И они вроде невидимы - внеstdout
/stderr
? Я прочиталman
страницу, но мне все еще неясно, когда использоватьtest
и как ее отладить.
find ... -exec
. Также см. Пример команд в разделе « Почему циклическая обработка вывода find является плохой практикой»?... -exec command ';' -quit
, но я не верю, что есть какое-то решение для второго, кроме анализа результата. Кроме того, в любом случае основная проблема с синтаксическим анализом результатаfind
(т. Е. Невозможность отличить разделители от символов в именах файлов) не применима, так как в этих случаях вам не нужно находить разделители.Ответы:
[
иtest
являются синонимами ( за исключением[
требует]
), так что вы не хотите использовать[ test
:test
возвращает нулевое состояние выхода, если условие истинно, иначе ненулевое. Это может быть фактически заменено любой программой, чтобы проверить ее состояние выхода, где 0 указывает на успех, а ненулевое указывает на сбой:Однако все вышеприведенные примеры только проверяют состояние завершения программы и игнорируют вывод программы.
Для
find
, вам нужно будет проверить, был ли сгенерирован какой-либо вывод.-n
тестирует непустую строку:Полный список тестовых аргументов доступен при вызове
help test
вbash
командной строке.Если вы используете
bash
(а неsh
), вы можете использовать[[ condition ]]
, что ведет себя более предсказуемо, когда в вашем состоянии есть пробелы или другие особые случаи. В противном случае это обычно то же самое, что и использование[ condition ]
. Я использовал[[ condition ]]
в этом примере, как я делаю, когда это возможно.Я также изменился
`command`
на$(command)
, который также обычно ведет себя аналогично, но лучше с вложенными командами.источник
echo
может потерпеть неудачу: попробуйтеecho 'oops' > /dev/full
.find
выйдет успешно, если не было никаких ошибок, поэтому вы не можете рассчитывать на его состояние выхода, чтобы узнать, нашел ли он какой-либо файл. Но, как вы сказали, вы можете посчитать, сколько файлов он нашел и проверить это число.Это было бы что-то вроде этого:
test
(aka[
) не проверяет коды ошибок команд, у него есть специальный синтаксис для выполнения тестов, а затем завершается с кодом ошибки 0, если тест прошел успешно, или 1 в противном случае. Этоif
тот, который проверяет код ошибки команды, которую вы передаете ему, и выполняет ее тело на основе этого.Смотрите
man test
(илиhelp test
, если вы используетеbash
), иhelp if
(так же).В этом случае
wc -l
будет выводиться число. Мы используемtest
опцию,-gt
чтобы проверить, больше ли это число, чем0
. Если это так,test
(или[
) вернется с кодом выхода0
.if
будет интерпретировать этот код выхода как успешный, и он выполнит код внутри своего тела.источник
Это было бы
или
Команды
test
и[ … ]
являются точно синонимами. Разница лишь в их имени и в том, что последний аргумент[
требует закрытия]
. Как всегда, используйте двойные кавычки вокруг подстановки команд, в противном случае выходные данныеfind
команды будут разбиты на слова, и здесь вы получите синтаксическую ошибку, если существует более одного совпадающего файла (и если аргументов нет, значение[ -n ]
true в то время как вы хотите,[ -n "" ]
который является ложным).В ksh, bash и zsh, но не в ash, вы также можете использовать
[[ … ]]
различные правила синтаксического анализа:[
это обычная команда, а[[ … ]]
другая конструкция синтаксического анализа. Вам не нужны двойные кавычки внутри[[ … ]]
(хотя они не больно). Вам все еще нужно;
после команды.Это может быть неэффективно: если в файле много файлов
/var/log/crashes
, команда find изучит их все. Вы должны сделать find stop, как только он найдет совпадение или вскоре после этого. С GNU find (не встроенный Linux, Cygwin) используйте-quit
основной.С другими системами, труба
find
в,head
по крайней мере, выходит вскоре после первого матча (find умрет от сломанной трубы).(Вы можете использовать,
head -c 1
если вашаhead
команда поддерживает это.)Или используйте zsh.
источник
Это должно работать
источник
это подходящее решение здесь.
-exec service myapp restart ';'
вызываетfind
команду, которую вы хотите запустить напрямую, вместо того, чтобы интерпретировать что-либо.-quit
вызываетfind
выход после обработки команды, предотвращая, таким образом, повторное выполнение команды, если окажется, что несколько файлов соответствуют критериям.источник