В первую очередь, я предлагаю занять место
for fname in `find . -type f`; do
с
find . -type f | while read -r fname; do
Затем, относительно sha1sum, это должно быть "фактически" уникально, означая, что вероятность, чтобы иметь в различные файлы с той же контрольной суммой, если значительно низкий, так, чтобы можно было безопасно принять это, уникальна.
[
и 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
(иначе [
) не проверяет коды ошибок команд, это имеет специальный синтаксис, чтобы сделать тесты и затем выходит с кодом ошибки 0, если тест был успешен, или 1 иначе. Это if
тот, который проверяет код ошибки команды, которую Вы передаете ему, и выполняет ее тело на основе его.
Посмотрите man test
(или help test
, если Вы используете bash
), и help if
(так же).
В этом случае, wc -l
произведет число. Мы используем test
опция -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
Команды test
и [ … ]
точно синонимичны. Единственной разницей является их имя и факт это [
требует закрытия ]
как его последний аргумент. Как всегда, используйте двойные кавычки вокруг замены команды, иначе вывод find
команда будет повреждена в слова, и здесь Вы получите синтаксическую ошибку, если будет больше чем один файл соответствия (и когда нет никаких аргументов, [ -n ]
верно, тогда как Вы хотите [ -n "" ]
который является ложью).
В ksh, ударе и zsh, но не в пепле, можно также использовать [[ … ]]
который имеет различные правила парсинга: [
обычная команда, тогда как [[ … ]]
другая конструкция парсинга. Вам не нужны двойные кавычки внутри [[ … ]]
(хотя они не причиняют боль). Вам все еще нужно ;
после команды.
if [[ -n $(find /var/log/crashes -name app-\*\.log -mmin -5) ]]; then
Это может потенциально быть неэффективно: если существует много файлов в /var/log/crashes
, находка исследует их всех. Необходимо сделать, находят остановку, как только она находит соответствие, или вскоре после. С GNU находят (не встроил Linux, Cygwin), используйте -quit
основной.
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
Вы можете сделать это, поместив вывод find в переменную, а затем используя тест bash для обработки различных интересующих вас случаев. Простой случай — есть ли какие-либо результаты или нет:
mycrashedapp=$(find /var/log/crashes/ -name myapp-\*\.log -mmin -5)
# if no crash then the variable is empty
if [[ -z "${mycrashedapp}" ]];then
echo "myapp is behaving."
else
service myapp restart
fi
На этом этапе вы можете при необходимости выполнить дальнейшую обработку, используя манипуляции с переменными в bash:
substr="/var/log/crashes"
parse=${mycrashedapp//"$substr"}
myappcrashedcount="$(((${#mycrashedapp} - ${#parse}) / ${#substr}))"
echo "myapp has crashed ${myappcrashedcount} times in total."
Вы можете выполнить дальнейшую обработку с помощью встроенного в bash сопоставления шаблонов регулярных выражений:
if [[ "${mycrashedapp}" =~ myapp-([0-9\-]*).log ]]; then
echo "The dates and times that myapp has crashed:"
echo ${BASH_REMATCH[1]}
fi
echo
может перестать работать: попробоватьecho 'oops' > /dev/full
. – derobert 29.08.2012, 01:52