Какие различия между «Убийство -Pipe $$» против «Выход 1»?

Возможным решением является использование grep с perl-regex. Флаг для этого -P

Например, это должно выглядеть так:

#!/bin/bash

regex="[^-_0-9A-Za-z\. ]+"

while IFS=  read -r -d $'\0'; do
    filepath=${REPLY%/*}
    filename=${REPLY##*/}

    #use grep with perl-regex -P and 
    #-q for quiet to prevent output to stdin

    echo "$filename" | grep -qP "$regex" 
    #now we compare the return code from grep
    if  [[ "$?" -eq 0 ]]
    then
        echo "match: $filename"
    else
        echo "nomatch: $filename"

    fi


done < <(find /symlnks -type f -print0)
5
29.10.2018, 11:26
1 ответ

exit 1 выходит из текущей среды подоболочки с кодом выхода 1, поэтому, например, в:

sh -c '(echo 1; exit 1; echo 2); echo 3'

Это exit 1выходит из подоболочки, выполняющей код на стороне (...), так что 2не выводится, а родительский процесс оболочки возобновляет эхо 3.

kill -s PIPE "$$"¹ отправляет сигнал SIGPIPE процессу, который выполнил интерпретатор оболочки, интерпретирующий в данный момент сценарий. Сигнал SIGPIPE по умолчанию вызывает завершение процессов, и тот факт, что этот процесс был уничтожен SIGPIPE, отражается в его статусе завершения.

Так в:

sh -c '(echo 1; kill -s PIPE "$$"; echo 2); echo 3'

Сигнал SIGPIPE отправляется процессом подоболочки своему родительскому процессу (, который выполнилsh). Этот родительский процесс умрет и не выведет 3, в то время как процесс подоболочки продолжит работу в фоновом режиме и выведет 2.

Если вы запустили эту команду в оболочке bashили zsh(и некоторых других оболочках Bourne -, подобных оболочкам ), эти оболочки установят параметр $?(в их внутреннем представлении. статуса выхода последней команды )на что-то вроде 141, что на большинстве систем равно 128 + SIGPIPE (13 ).

Теперь SIGPIPE — это сигнал, отправляемый системой процессам, пытающимся выполнить запись в канал или сокет, который не имеет конца для чтения (сломанный канал/сокет ), поэтому отправка его здесь немного вводит в заблуждение. Сигналом, зарезервированным для административного завершения процесса, является SIGTERM, который является сигналом kill, отправляемым по умолчанию.

Одна из причин, по которой вы можете захотеть использовать SIGPIPE вместо SIGTERM, заключается в том, что существуют оболочки, такие как bash, которые выводят сообщение, когда одно из их заданий завершается сигналом, в то время как они обычно не делают этого для SIGPIPE (, так как процессы обычно завершаются SIGPIPE и не обязательно означают наличие проблемы, как в cmd | head -n 1), поэтому использование SIGPIPE позволяет избежать таких сообщений.

bash-4.4$ /bin/kill 0
Terminated
bash-4.4$ /bin/kill -s PIPE 0
bash-4.4$

даже если не -интерактивный:

$ bash -c 'sh -c "kill \$\$"; exit'
bash: line 1:  6665 Terminated              sh -c "kill \$\$"
$ bash -c 'sh -c "kill -s PIPE \$\$"; exit'
$

1 Здесь добавление отсутствующих кавычек вокруг$$для надежности и использование стандартного (не -необязательного синтаксиса POSIX)kill -s PIPEдля переносимости (, хотя kill -PIPEтакже должен работать на большинстве систем ).

10
27.01.2020, 20:34

Теги

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