나는 여러 웹페이지를 다운로드하려고 하는데, N줄의 html을 다운로드하고 나면 모든 것을 중단하고 싶습니다. 그러나 대신 파이프라인의 이전 단계가 계속됩니다. 문제를 확인하는 예:
for i in /accessories /aches-pains /allergy-hayfever /baby-child /beauty-skincare; do echo $i; sleep 2; done | \
while read -r line; do curl "https://www.medino.com$line"; done \
| head -n 2
이제 요청한 다음 중단하고 싶습니다.
그러나 실제로 일어나는 일은 다음과 같습니다.
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0<!DOCTYPE html>
<html lang="en" >
100 4412 0 4412 0 0 12788 0 --:--:-- --:--:-- --:--:-- 12751
curl: (23) Failed writing body (0 != 2358)
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 2358 0 2358 0 0 3772 0 --:--:-- --:--:-- --:--:-- 3766
curl: (23) Failed writing body (0 != 2358)
( ^ repeats 4 times)
스크립트가 즉시 중단되지 않고 계속 실행되는 이유는 무엇입니까? 저는 배관에 대한 전문가가 아니기 때문에 여기에 기본적인 것이 빠진 것 같습니다.
답변1
파이프라인의 두 번째 부분은 입니다 while read -r line; do curl ...$line; done
. 실행 시:
첫 번째 반복에서 쉘은 첫 번째 값을 라인으로 읽고 컬을 실행합니다. 컬(가져오기 및)은
head -n2
처음 두 라인을 추출하고 종료하여 두 번째와 세 번째 부분 사이의 간격을 닫습니다. 귀하의 예에서 컬은 이 출력을 최소한 두 개의 블록에 기록하므로 두 번째 쓰기에서 오류가 발생하고 실패합니다. 즉, 0이 아닌 상태로 종료됩니다.쉘은 명령이 실패할 때 대부분의 명령 시퀀스(복합 명령 포함)를 종료하지 않으며 쉘은 대화식으로 사용되는 경우가 많기 때문에 명령을 실행할 때마다 쉘이 죽어 다시 로그인해야 하는 경우 문제가 될 수 있습니다. 다시 시작하세요. 매우 불편합니다. 프로그램을 실행하는 동안 오류가 발생했습니다.
따라서 쉘은 두 번째 값을 라인으로 읽고 두 번째 컬을 실행합니다. 이는 파이프가 닫혀 있기 때문에 즉시 실패하지만 쉘은 다시 세 번째 라인을 읽고 세 번째 컬을 실행하는 방식으로 입력 End가
read
실패할 때까지 계속됩니다.read
이는 list-1 섹션에 있으며while
실패하면 루프가 종료됩니다.
다음을 사용하여 컬이 실패하고 종료되는지 명시적으로 테스트할 수 있습니다.
generate_values | while read -n line && curl ...$line; do :; done | head -n2
또는 쉘 옵션을 설정하여하다실패 시 종료:
generate_values | { set -e; while read -n line; do curl ...$line; done } | head -n2
두 가지 방법 모두 실행될 수 있습니다.하나컬은 쓰기 시에만 오류를 보고하기 때문에 종료됩니다.뒤쪽에파이프가 닫혀 있습니다. 즉, 마지막 블록 이후입니다. 컬 #2 출력의 마지막 블록 중에 출력 제한( head -n$n
)이 소진되면 해당 컬은 "성공적으로" 종료되고 쉘은 컬 #3을 시작합니다. 이는 쓰기 중 처음(또는 유일한) 실패가 됩니다. .