私は複数のWebページをダウンロードしようとしていますが、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
パイプラインの2番目の部分はですwhile read -r line; do curl ...$line; done
。実行時:
最初の反復では、シェルは最初の値を行として読み込み、カールを実行します。カール(インポートと)は
head -n2
最初の2行を抽出して終了し、2番目と3番目の部分の間の間隔を閉じます。あなたの例では、カールはこの出力を少なくとも2つのブロックに書き込むので、2番目の書き込みでエラーが発生して失敗します。つまり、ゼロ以外の状態で終了します。シェルはコマンドが失敗したときにほとんどのコマンドシーケンス(複合コマンドを含む)を終了せず、シェルは対話的に使用されることが多いため、コマンドを実行するたびにシェルが死んで再ログインする必要がある場合に問題が発生する可能性があります。再起動してください。とても不便です。プログラムの実行中にエラーが発生しました。
したがって、シェルは2番目の値を行として読み取り、2番目のカールを実行します。これはパイプが閉じているためすぐに失敗しますが、シェルは再び3行目を読み、3番目のカールを実行するように入力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を起動します。これは書き込み中の最初(または唯一の)失敗になります。 。