정렬: 쓰기 실패 |

정렬: 쓰기 실패 |

좋은 저녁이에요,

다음은 내 스크립트에서 사용하는 코드입니다. SSH 세션에서 시작하면 제대로 작동하지만 cron을 통해 실행하면 화면에 파이프 파손 오류가 표시됩니다.

SSH를 통해 재현할 수 없습니다.

암호:

IP=$(sort --random-sort /root/ips.csv | head -n 1); nc -zv -w 2 $IP 443 2>&1 | grep succeeded >> outfile

화면 오류:

sort: write failed: standard output; Broken pipe
sort: write error

어떤 팁이나 조언이 있나요?

감사합니다!

답변1

첫 번째 줄 처리가 끝나면 head파이프의 다른 쪽 끝을 닫고 종료됩니다. sort계속해서 더 쓰려는 시도가 있을 수 있으며 닫힌 파이프나 소켓에 쓰면 EPIPE 오류가 반환됩니다. 그러나 SIGPIPE 신호도 발생시켜 신호를 무시하거나 처리하지 않는 한 프로세스를 종료합니다. 신호를 무시하면 sort오류가 표시되고 불평하고 종료됩니다. 이 신호를 무시하지 않으면 sort당신은 죽게 됩니다.

우리는 사용할 수 있습니다trap내장쉘의 신호가 무시되고 오류가 발생합니다.

$ trap "" PIPE
$ sort bigfile | head -1 > /dev/null 
sort: write failed: standard output: Broken pipe
sort: write error

하지만 안타깝게도 우리는할 수 없다trap신호를 무시하지 않고 다음과 같은 원하는 동작을 얻는 데 사용됩니다 .POSIX 요구 사항이 작업은 비대화형 셸(스크립트)에서는 허용되지 않습니다. 대화형 쉘을 허용하지만 Bash는 trap이 경우에도 그렇게 하지 않습니다.

테스트하려면:

sh$ trap '' PIPE                     # ignore the signal    
sh$ PS1='another$ ' bash             # run another shell
another$ trap - PIPE                 # try to reset the signal
                                     # it doesn't work
another$ sort bigfile |head -1 > /dev/null
sort: write failed: 'standard output': Broken pipe
sort: write error

대신 Perl one-liner와 같은 외부 도구를 사용하여 스크립트나 명령을 실행할 수 있으며 신호는 무시되지 않습니다( sort여기에서는 자동으로 종료됩니다).

another$ perl -e '$SIG{PIPE}="DEFAULT"; exec "@ARGV"' \
         'sort bigfile |head -1' > /dev/null 
another$ 

귀하의 크론 상황은 그 이유가 체계화되어 있을 수 있습니다.분명히 SIGPIPE는 기본적으로 무시됩니다., 언급됨:

[SIGPIPE]는 일반 데몬에는 그다지 유용하지 않으며, 데몬에 유용하고 좋은 실행 환경을 제공하려고 할 때는 이 기능을 해제합니다. 물론 쉘이나 다른 것이 다시 열어야 합니다.

물론 이것도 언급됐지만문서(systemd.exec)에서:

IgnoreSIGPIPE=
부울 매개변수를 사용합니다. true인 경우 실행 프로세스에서 SIGPIPE가 무시됩니다. SIGPIPE는 일반적으로 쉘 파이프에서만 유용하므로 기본값은 true입니다.

내 데비안 시스템에서는/lib/systemd/system/cron.service 명시적 설정IgnoreSIGPIPE=false, cron에 대한 시스템 기본값을 실행 취소합니다. 이것이 귀하의 경우에 도움이되는지 확인하고 싶을 수도 있습니다.

답변2

어쨌든 GNU 확장 이므로 동일한 GNU 유틸리티 컬렉션(GNU ) 의 GNU를 --random-sort사용할 수도 있습니다 .shufcoreutils

ip=$(shuf -n 1 ips.tsv)

SIGPIPE 문제를 피하는 것 외에도 GNU 처럼 전체 파일을 섞을 필요가 없기 때문에 더 효율적입니다 sort --random-sort.shuf저수지 샘플링연산그러기 위해서는 많은 투자가 필요합니다.)

답변3

일반적인 솔루션으로 이 Bash 기능을 사용하면 파이프 파손 오류가 발생하지 않고 다른 가능한 오류 메시지를 숨기지 않고 파이프라인을 실행할 수 있습니다.

entire_pipe() {
    ( set -m; (
        trap 'exit 0' INT
        echo $BASHPID
        $1
    ) & wait $! ) |
    (
        trap 'trap - EXIT; kill -s INT -- -$pid 2>/dev/null || :' EXIT
        read -r pid
        $2
    )
}

$BASHPID휴대성을 높이 려면 $(exec sh -c 'echo "$PPID"').

이 문제가 발생했을 때 해당 기능을 사용하려면 교체가 필요합니다.

sort --random-sort /root/ips.csv | head -n 1

통과

entire_pipe 'sort --random-sort /root/ips.csv' 'head -n 1'

이는 파이프의 왼쪽에서 하위 프로세스가 시작되는 경우에도 작동하며 모두 중단됩니다.

관련 정보