Zsh
頭部完成時中止 curl,xargs 管道中的先前步驟
我正在嘗試下載一堆網頁,一旦我下載了 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)
為什麼腳本沒有立即中止,而是繼續執行?我不是管道上的超級專家,所以感覺我在這裡缺少一些基本的東西。
管道的第二部分是
while read -r line; do curl ...$line; done
. 當它執行時:
- 在第一次迭代時,shell 將第一個值讀入 line,然後執行 curl;curl(獲取並)輸出網頁,其中
head -n2
提取前兩行並退出,關閉第二部分和第三部分之間的管道。它出現在您的範例 curl 將此輸出寫入至少兩個塊,因此它在第二次寫入時出錯並失敗,即以非零狀態退出。- 當一個命令失敗時,shell 不會終止大多數命令序列(包括複合命令),因為 shell 經常以互動方式使用,並且每次執行任何命令時讓 shell 當機迫使您重新登錄並重新開始都會非常不方便錯誤執行任何程序。
- 因此,shell 將第二個值讀入 line 並執行第二個 curl,由於管道關閉,它立即失敗,但 shell 再次繼續並讀取第三行並執行第三個 curl,依此類推,直到輸入結束導致
read
失敗;因為read
在 的 list-1 部分while
,它的失敗會導致循環終止。您可以使用以下命令顯式測試 curl 是否失敗(然後終止):
generate_values | while read -n line && curl ...$line; do :; done | head -n2
或者您可以設置一個 shell 選項,使其在失敗時終止:
generate_values | { set -e; while read -n line; do curl ...$line; done } | head -n2
請注意,這兩種方法都可能會執行一次,因為 curl 僅在管道關閉後(即在最後一個塊之後)寫入時報告錯誤。如果您的輸出限制 (
head -n$n
) 在 curl #2 的最後一個輸出塊期間用盡,則該 curl 將退出“成功”並且 shell 將啟動 curl #3,這將在其第一次(或唯一一次)寫入時失敗。