3つの並列ダウンロードを実行し、いつでもすべてのダウンロードをキャンセルします。

3つの並列ダウンロードを実行し、いつでもすべてのダウンロードをキャンセルします。

以下を実行するbashスクリプトが必要です。

  1. wgetを使用して3つのファイルを同時にダウンロードすると、同時に完了する必要はありません。
  2. 同時に3つのダウンロードをキャンセルできますCTRL+C(完了したダウンロードを除く)。

現在、私はwget -c URL各端末で3つの並列インスタンスを実行しています。ただし、Linuxの再起動後に続行できるように、ユーザー入力がキャンセルされるのを待つスクリプトが必要です。

私のシステムはCygwinがインストールされているWindowsです。

答え1

parallelこれを達成するためにGNUを使用できます。 URLを配列に入れて、次wgetを実行しますparallel

#!/bin/bash
urls=( "https://example.com" "https://example1.com" "https://example2.com")

parallel wget -c ::: "${urls[@]}"

Parallelはコマンドを並列に実行し、スクリプトを停止します(たとえば、Ctrl+を使用するとC並列処理が終了し、完了したインスタンスに影響を与えずに実行中の3つのwgetインスタンスがすべて終了します。

parallelオペレーティングシステムリポジトリに見つかる必要があります。


インストールしたくない場合やインストールできない場合は、parallelbashからローカルにインストールすることもできます。

#!/bin/bash

trap 'kill $(jobs -p)' EXIT

urls=( "https://example.com" "https://example1.com" "https://example2.com" )
for url in "${urls[@]}"; do
  wget -c "$url" &
done

wait

ここでの秘密は、trap組み込み関数(help trapbashを参照)を使用して次のことを行います。kill $(jobs -p)EXIT信号コマンド。jobs -p現在のシェルのすべての子プロセスのPIDが返されるため、この場合は実行中のwgetプロセスのPIDになります。これらはkill殺された場所に渡されます。したがって、スクリプトを終了するとサブスクリプトに渡されます。 +killスクリプトを使用してプロセスを終了waitできるように終了する前に、すべてのバックグラウンドジョブの実行が完了するまでスクリプトが待機していることを確認してください。wgetCtrlC

答え2

Bashスクリプトは次の場所にあります。この他の答えBashは別のプロセスグループでコマンド(非同期コマンドを含む)を実行するため、トラップが必要です。端末はフォアグラウンドプロセスグループについて知っており、Ctrlそのグループに+のSIGINTを送信しますc。 Bashスクリプトがwaitフォアグラウンドにある場合、それbash自体はフォアグラウンドプロセスグループに属しますが、wget自分が作成したプロセスグループには属しません。 SIGINT(存在する場合)はsのbash代わりに到着しますwget。そのため、上記の回答にトラップが必要です。

他のシェルは異なる動作をする可能性があります。私のKubuntuでは、posh新しいプロセスグループは作成されず、自分が属するプロセスグループのすべてを実行します。これにより、スクリプトを簡素化できます。

#!/usr/bin/posh

set -- 'https://example.com' 'https://example1.com' 'https://example2.com'
for url do
  wget -c "$url" &
done

wait

スクリプトがフォアグラウンドで実行中に+を押すと、Ctrl端末はSIGINTを直接送信します。cposh そしてwgetフォアグラウンドプロセスグループと同じプロセスグループにあるためです。

メモ:

  • posh配列はサポートされていないため、URLを位置パラメータとして保存します。そのset …行を削除してからスクリプトを呼び出すときにURL(たとえば)を指定できます./the_script 'https://example.com' 'https://example1.com' 'https://example2.com'。これにより、スクリプトをランダムなコンテンツを並列にダウンロードするためのツールに置き換えることができます。
  • トラップに使用される別の答えは、kill基本信号がSIGTERMであり、これはSIGINTと同じではありません(wget同じ方法で反応することができます)。killSIGINTまたは他の信号を送信することができ、オプションです(kill -s …)。私たちのスクリプトでは選択肢はありません。我々は信号を伝達せず、信号を生成しません。Ctrlまずc、端末でSIGINTをスクリプトを解釈するシェルだけでなくsにも送信するようにすべてを設定しましたwget

他の答えは良いです。 GNUがparallel正しいツールであり、Bashがtrap機能する必要があるため、ある意味では私の答えは必要ありません。私はまだCtrl+がどのようにc機能するのか、そしてさまざまなシェルがどのように機能するのかを知っていれば、あなたが望む動作を得るために別のシェルを選択できることを示したいと思います。

関連情報