Когда GNU grep
попытается записать свой результат, он завершится ошибкой с не -нулевым статусом выхода, потому что ему некуда записать вывод, потому что SSH-соединение потеряно.
Это означает, что оператор if
всегда использует ветвь else
.
Чтобы проиллюстрировать это, (это не точно то, что происходит в вашем случае, но оно показывает, что произойдет, если GNU grep
не сможет записать свой вывод):
$ echo 'hello' | grep hello >&- 2>&-
$ echo $?
2
Здесь мы grep
для строки, которую производит echo
, но мы закрываем оба потока вывода для grep
, чтобы она не могла никуда писать. Как видите, статус выхода GNU grep
равен 2, а не 0.
Это характерно для GNU grep
, grep
в системах BSD не будет вести себя одинаково:
$ echo 'hello' | grep hello >&- 2>&- # using BSD grep here
$ echo $?
0
Чтобы исправить это, убедитесь, что сценарий не генерирует выходные данные. Вы можете сделать это с помощью exec >/dev/null 2>&1
. Кроме того, мы должны использовать grep
с его опцией -q
, так как мы совсем не заинтересованы в просмотре вывода из него (это, как правило, также ускорит grep
, поскольку он не нужно анализировать весь файл, но в этом случае это очень мало влияет на скорость, так как файл очень маленький ).
Короче:
#!/bin/sh
# redirect all output not redirected elsewhere to /dev/null by default:
exec >/dev/null 2>&1
while true; do
date >sdown.txt
ping -c 1 -W 1 myserver.net >pingop.txt
if ! grep -q "64 bytes" pingop.txt; then
mutt -s "Server Down!" myemail@address.com <sdown.txt
break
fi
sleep 10
done
Вы также можете использовать тест ping
напрямую, устраняя необходимость в одном из промежуточных файлов (, а также избавляясь от другого промежуточного файла, который на самом деле всегда содержит только отметку даты):
#!/bin/sh
exec >/dev/null 2>&1
while true; do
if ! ping -q -c 1 -W 1 myserver.net; then
date | mutt -s "Server Down!" myemail@address.com
break
fi
sleep 10
done
В обоих вариантах вышеприведенного сценария я выбираю выход из цикла при невозможности связаться с хостом, просто чтобы свести к минимуму количество отправленных электронных писем.Вместо этого вы можете заменить break
, например, на. sleep 10m
или что-то в этом роде, если вы ожидаете, что сервер снова заработает.
Я также немного изменил параметры, используемые с ping
, так как -i 1
не имеет особого смысла с -c 1
.
Короче (, если вы не хотите, чтобы он продолжал отправлять электронные письма, когда хост недоступен):
#!/bin/sh
exec >/dev/null 2>&1
while ping -q -c 1 -W 1 myserver.net; do
sleep 10
done
date | mutt -s "Server Down!" myemail@address.com
Поскольку задание cron выполняется каждую минуту, (будет продолжать отправлять электронные письма каждую минуту, если сервер по-прежнему не работает):
* * * * * ping -q -c 1 -W 1 >/dev/null 2>&1 || ( date | mail -s "Server down" myemail@address.com )
find PATH -type f -printf "%p\n" | xargs -i -- /bin/sh -c '
/bin/sed "1s/.//" "$1" > "_$1" && mv "_$1" "$1"
' x {}
Или если у вас GNU sed
еще проще:
find PATH -type f -exec sed -s -i '1s/.//' \{} +
Вы можете начать с awk-цикла в папке с вашими файлами, а затем через секунду перенаправить строку вывода в исходный файл. Команда awk, которую вы можете использовать для удаления первых n символов, выглядит примерно так:
awk '{print substr($1,2) > "/output/file" }' /path/to/file
Имейте в виду, что запись в тот же файл, который вы читаете, не является лучшей практикой, но она работает.