Существует ли команда Linux, которая удаляет только первый символ каждого файла?

Когда 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 )
0
14.11.2021, 21:55
2 ответа
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/.//' \{} +
0
19.11.2021, 23:14

Вы можете начать с awk-цикла в папке с вашими файлами, а затем через секунду перенаправить строку вывода в исходный файл. Команда awk, которую вы можете использовать для удаления первых n символов, выглядит примерно так:

awk '{print substr($1,2) > "/output/file" }' /path/to/file

Имейте в виду, что запись в тот же файл, который вы читаете, не является лучшей практикой, но она работает.

0
16.11.2021, 09:02

Теги

Похожие вопросы