検索
連載

【 wait 】コマンド――プロセスやジョブの終了を待つLinux基本コマンドTips(317)

本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、プロセスやジョブの終了を待つ「wait」コマンドです。

Share
Tweet
LINE
Hatena
「Linux基本コマンドTips」のインデックス

Linux基本コマンドTips一覧

 本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。今回は、プロセスやジョブの終了を待つ「wait」コマンドです。

waitコマンドとは?

 「wait」はプロセスやジョブの終了を待つコマンドです。「バックグラウンドで複数のコマンドを実行し、全てが終了したら次の処理を行う」といった処理が可能です。シェルスクリプト中で使用することが多いでしょう。

 waitコマンドはbashのビルトインコマンド(シェルの組み込みコマンド)であるため、「man」コマンドではなく、「help」コマンドで詳細を表示します。



waitコマンドの書式

wait [ジョブ番号かプロセスID]

※[ ]は省略可能な引数を示しています。





waitの主なオプション

 bash バージョン4.3から、複数のジョブまたはプロセスを指定して、いずれかのプロセスの終了を待つ「-n」オプションが追加されました。CentOS 7のbash(4.2.46)では未対応ですが、Ubuntu 18.04 LTSのbash(4.4.19)は「-n」に対応しています。



プロセスの終了を待つ

 「wait %ジョブ番号」または「wait プロセスID」で、指定したジョブやプロセスの終了を待ちます。プロセスIDで指定できるのは、現在のシェルから実行されたプロセスのみです。

 引数を指定しなかった場合、現在のシェルが実行している全てのジョブが終了するのを待ちます。

コマンド実行例

wait %1

(ジョブ番号「1」の終了を待つ)

wait 1001

(プロセスID「1001」の終了を待つ。現在のシェルから実行されたプロセス以外は指定できない)

wait

(現在のシェルが実行している全てのジョブが終了するのを待つ)


 画面1、画面2では、waitコマンドの動作を確かめるために、Webブラウザ「Firefox」と「eogコマンド」(画像ファイルを表示するコマンド、ここでは単にバックグラウンドで実行するコマンドとして使用)を順に実行しています。

画面1
画面1 1つのジョブの終了を待つ実行例
画面2
画面2 全てのジョブの終了を待つ実行例


スクリプト中でwaitコマンドを使う

 waitコマンドを使うと、シェルスクリプトの中で「複数の処理を並行させて動かし、全て終了したら次の処理へ進む」という制御が可能になります。

 例えばスクリプト1では、command1、command2、command3という3つのコマンドを順番に実行しています(全て架空のコマンドです)。この場合、command1が終わったらcommand2、command2が終わったらcommand3の実行が始まります。

#! /bin/bash
command1
command2
command3
スクリプト1

 ここで、command1とcommand2に「&」を付けて実行すると、command1の終了を待たずにcommand2の実行が、command1とcommand2の終了を待たずにcommand3の実行が始まります(スクリプト2)。

#! /bin/bash
command1 &
command2 &
command3
スクリプト2

 もし、「command1とcommand2はそれぞれ並行して実行することができるので、command1の終了を待たずにcommand2を実行したい、ただし、command3はcommand1とcommand2の両方が終了するまでは実行したくない」、という場合は、スクリプト3のようにwaitコマンドを使います。

#! /bin/bash
command1 &
command2 &
wait
command3
スクリプト3


コマンドの終了コードを取得する

 ジョブ番号またはプロセスIDを指定してwaitコマンドを実行すると、「指定したジョブまたはプロセスの終了コード」がwaitコマンドの終了コードになります(※1)。

※1 ジョブ番号やプロセスIDを指定せず「wait」のみで実行すると、waitコマンドの終了コードは「0」になる。



 画面3では、「ちょっと時間がかかる処理」として「ping」コマンド(第143回)を使ってテストしています。画面3ではpingコマンドでわざとエラーが返るように「1.2.3.4」というIPアドレスを指定して実行しています。pingの結果を画面に表示しないよう、「> /dev/null」を指定し、「&」でバックグラウンド実行にしました。

 「-c 10」を指定しているため、10回ほど実行すると処理を終了します。全体としては20秒ほどかかる想定です。テストする場合はお使いの環境によって適宜回数を調整してください。

 画面3ではバックグラウンドで実行したジョブは1つだけですが、終了コードを取得することが目的なので「wait %1」のようにジョブ番号を指定しています。「wait 17951」あるいは「wait $!」のようにプロセスIDを指定しても同じように実行できます。

画面3
画面3 存在しないIPアドレスを指定して終了コードを取得しているところ

 画面3と比較するため、画面4では同じpingコマンドで「localhost」を指定しています。こちらは約10秒間で終了します。

画面4
画面4 必ず成功するコマンドを実行して終了コードを取得しているところ


コマンドごとの終了コードを取得する

 先ほどのスクリプト3で、command1とcommand2とcommand3それぞれの終了コードを表示したい場合は、次のように指定します。

#! /bin/bash
./command1 &
pid1=$!
./command2 &
pid2=$!
wait $pid1
exit1=$?
wait $pid2
exit2=$?
./command3
exit3=$?
echo "command1 exit:$exit1"
echo "command2 exit:$exit2"
echo "command3 exit:$exit3"
スクリプト4

 画面5では、command1、command2、command3という簡単なスクリプトを作成して、スクリプト4の動作をテストしています。

画面5
画面5 スクリプト中で各コマンドの終了コードを取得したところ


筆者紹介

西村 めぐみ(にしむら めぐみ)

元々はDOSユーザーで「DOS版UNIX-like tools」を愛用。ソフトハウスに勤務し生産管理のパッケージソフトウェアの開発およびサポート業務を担当、その後ライターになる。著書に『図解でわかるLinux』『らぶらぶLinuxシリーズ』『Accessではじめるデータベース超入門[改訂2版]』『macOSコマンド入門』など。地方自治体の在宅就業支援事業にてMicrosoft Officeの教材作成およびeラーニング指導を担当。会社などの"PCヘルパー"やピンポイント研修なども行っている。


Copyright © ITmedia, Inc. All Rights Reserved.

ページトップに戻る