timeout コマンド入門 - 実行時間を制限してハングを防ぐ
この記事でできるようになること
- コマンドの実行時間に上限を付けて、固まったまま放置される事故を防げる
- 終了ステータス `124` を見てタイムアウトかどうかを判定できる
- `-k` で SIGTERM を無視するプロセスを確実に止められる
前提知識(先に読むと理解しやすい記事)
この記事で学べること
timeoutで コマンドの実行時間に制限 をかけられるようになる- 「固まって戻ってこない」コマンドを 自動で打ち切る 方法が分かる
- タイムアウトしたかどうかを 終了ステータス
124で判定できる - SIGTERM を無視するしぶといプロセスを
-kで強制終了 できる
結論(先に覚えるべき型)
- 時間を区切って実行 →
timeout 10 コマンド(10 秒で打ち切り) - 単位を付けてもよい →
timeout 30s/timeout 5m/timeout 1h - 打ち切られたかの判定 → 終了ステータスが
124ならタイムアウト - それでも止まらないとき →
timeout -k 5 10 コマンド(5 秒後に強制終了)
先に覚える「固まったように見えるとき」の抜け方
コマンドが戻ってこないと、画面が壊れたように感じる。しかし、たいていは次の順で抜けられる。
| 見えている状態 | 抜け方 |
|---|---|
| コマンドが終わらずプロンプトコマンドの入力を待っている状態を示す記号(例 $ や #)。が出ない | Ctrl+C を押して中止する |
Ctrl+C でも止まらない |
Ctrl+Z で一時停止し、jobs で番号を見て kill %1 |
| 毎回この状態になるのを避けたい | 最初から timeout 10 コマンド のように上限を付けて実行する |
timeout は「そもそも固まったまま放置しない」ための予防策。だから毎回 Ctrl+C を押す必要がなくなる。
1. timeout コマンドとは何か?
結論:
timeoutは「指定した時間を超えたらコマンドを自動で終了させる」コマンド。ハング対策の定番。
Ctrl+C で止めるしかないんですか?timeout だよ。「このコマンドは最大 N 秒だけ動かす。それを超えたら自動で止める」 という時間制限をかけられるんだ。Ctrl+C を押さなくても、勝手に止めてくれるんですか?timeout はその保険なんですね。ハング(hang)とは
ハングは「コマンドが終わらないまま止まって見える状態」のこと。「フリーズ」「固まる」「応答がない」も、ほぼ同じ意味で使われる。プログラムがこわれているとはかぎらない。相手の返事をずっと待っているだけのこともある。
timeout の基本イメージ
timeout 10 コマンド
↑ ↑
| 実行したいコマンド
制限時間(秒)「10 秒以内に終われば普通に終了、超えたら強制的に打ち切り」。
2. なぜ timeout が必要なのか?
結論: ネットワーク待ちや無限ループで固まるコマンドを放置すると、スクリプト全体が止まる。timeout がそれを防ぐ。
ping、書き方を間違えた無限ループ。こういうのは 永遠に戻ってこない ことがある。Ctrl+C で止められる。でも cron や自動化スクリプトには 見ている人がいない。timeout で上限を決めておけば、最悪でも「N 秒で諦めて次へ進む」ようにできるんだ。固まったコマンドを放置すると、メモリやプロセス枠を食いつぶす。cron の多重起動を招くこともある。「いつ終わるか分からない処理には時間の上限を付ける」 のが安全な運用。
3. 基本の使い方(時間の指定)
結論:
timeout 時間 コマンドの形。数字だけなら秒、s/m/h/dで単位も付けられる。
いちばん基本の形は次の通り。
$ timeout 10 sleep 30
sleep 30 は本来 30 秒待つコマンド。だが timeout 10 を付けると 10 秒で打ち切られる。
sleep 30 なのに 10 秒で終わった! 約束の 30 秒より早く止まりましたね。時間には単位(サフィックス)を付けられる。
$ timeout 30s コマンド # 30秒 $ timeout 5m コマンド # 5分 $ timeout 1h コマンド # 1時間 $ timeout 2d コマンド # 2日
時間の単位(サフィックス)
| 書き方 | 意味 |
|---|---|
10 |
10秒(単位なし=秒) |
30s |
30秒 |
5m |
5分 |
1h |
1時間 |
2d |
2日 |
0.5 のような小数も使える(timeout 0.5 コマンド で0.5秒)。
4. 終了ステータス 124 でタイムアウトを判定する
結論: timeout で打ち切られたときの終了ステータスは
124。echo $?が124ならタイムアウトと判断できる。
終了ステータス(exit status)とは
終了ステータスは、コマンドが終わるときに残す番号のこと。「終了コード」「リターンコード」「exit code」も同じものを指す呼び方だよ。0 は成功。0 以外は「何か普通ではないことが起きた」という意味になる。直前のコマンドの値は $? で見られる。
timeout が時間切れでコマンドを止めたとき、終了ステータスは 124 になる。これを見れば、タイムアウトしたかどうかを自動で見分けられる。
$ timeout 1 sleep 10 $ echo $?
124
124 という数字が出ました。これがタイムアウトの目印なんですね。0 だね。124 かどうかを見れば「途中で打ち切られたのか、ちゃんと終わったのか」が分かる。時間内に終わった場合は、コマンド本来のステータスが返る。
$ timeout 10 sleep 1 $ echo $?
0
覚えておきたい終了ステータス
| 値 | 意味 |
|---|---|
124 |
タイムアウトで打ち切られた |
125 |
timeout コマンド自体の失敗 |
126 |
コマンドは見つかったが実行できない |
127 |
コマンドが見つからない |
137 |
KILL シグナル(-k)で強制終了された(128 + 9) |
まずは 「124 = タイムアウト」 だけ覚えれば十分。
まれに、コマンド自身が 124 を返すこともある。そこまで区別したいときは --preserve-status を使う。
5. -k でしぶといプロセスを強制終了する
結論: timeout はデフォルトで SIGTERM を送る。無視されるときは
-k 時間で猶予後に SIGKILL を送って確実に止める。
プロセス(process)とは
プロセスは「今このコンピュータの中で動いている、プログラム 1 つ 1 つ」のこと。あなたが打ったコマンドも、動き始めるとプロセスになる。
シグナル(signal)とは
シグナルは、プロセスに送る短い合図のこと。「終わってください」「今すぐ止まれ」といった内容を番号と名前で送る。よく使うのは 3 つだけ。
- SIGTERM: 終了のお願い。プログラム側はあとしまつをしてから終われる
- SIGINT:
Ctrl+Cを押したときに送られる合図 - SIGKILL: 強制終了。プログラム側は拒否できない
timeout で止めたはずなのに、たまにコマンドが止まらないと聞きました。どうしてですか?timeout は時間が来ると、まず SIGTERM(終了のお願い) を送る。でも、このお願いを 無視するプログラム もあるんだ。-k(kill-after)を使う。「最初のお願いから N 秒待っても止まらないなら、今度は強制終了する」という二段構えにできるんだ。$ timeout -k 5 10 コマンド
これは次の意味になる。
- まず 10 秒 でコマンドに SIGTERM(終了のお願い)を送る
- それでも さらに 5 秒 止まらなければ SIGKILL(強制終了)を送る
-k(kill-after)の動き
timeout -k 5 10 コマンド
↑ ↑
| 本来の制限時間(10秒)→ SIGTERM
追加の猶予(5秒)→ それでも残れば SIGKILLSIGKILL はプログラム側が拒否できない。どうしても止めたいときの、いちばん最後の手だて。
SIGKILL(強制終了)は あとしまつをする間を与えずに プロセスを止める。書きかけのファイルが壊れる可能性もある。まずは普通の timeout(SIGTERM)で試そう。止まらないときの保険として -k を使うのがよい。
6. シグナルを指定する(-s)
結論:
-sで送るシグナルを変えられる。終了時にコマンド自身のステータスを返したいなら--preserve-status。
デフォルトでは SIGTERM が送られる。-s(--signal)を使えば、別のシグナルを指定できる。
$ timeout -s SIGINT 10 コマンド
これは Ctrl+C と同じ SIGINT を送る。コマンドによっては、SIGTERM より行儀よく終われることがある。
timeout でよく使うのは 3 つ。お願い系の SIGTERM(デフォルト)と SIGINT(Ctrl+C 相当)、いちばん最後の手だてになる SIGKILL だね。タイムアウトしたときに 124 へ書き換えず、コマンドが最期に返した値をそのまま受け取りたい ときは --preserve-status を使う。
$ timeout --preserve-status 10 コマンド
--preserve-status を付けると、SIGTERM で止められた場合は 143(128 + 15)が返る。「コマンドが正常に終わったときの値」が返るわけではない。「シグナルで止められた」という事実まで含めて知りたい場面で使う。通常は付けない。124 で判定する方がシンプル。
7. よくある初心者のつまずき
結論: 時間とコマンドの順番、
124の意味、-kの引数の並びを取り違えやすい。
7-1. 時間とコマンドの順番を逆にする
# NG: コマンドが先になっている $ timeout sleep 30 10 # OK: 時間 → コマンドの順 $ timeout 10 sleep 30
timeout のすぐあとは かならず時間。その後に実行したいコマンドを書く。順番を逆にすると timeout がエラーになる。
7-2. 124 を「エラー」と勘違いする
124 を返しました。私、コマンドを壊しちゃったんでしょうか...?124 は 「timeout が時間どおり仕事をした」証拠 なんだ。124 を見たら「上限に達した」と読めばいいんですね。安心しました。7-3. パイプ全体にかけたつもりで一部しか制限されない
# これは「timeout 10 で grep」だけにかかる書き方ではない $ timeout 10 grep pattern file | sort
パイプ(|。左のコマンドの結果を、右のコマンドへ渡す書き方)でつないでも、制限がかかるのは timeout 10 grep pattern file の部分だけ。| sort は別扱いになる。
パイプ全体を一括で囲みたいときは、bash -c 'コマンド列'(まとめてひとつのコマンドとして扱わせる書き方)を使う。
$ timeout 10 bash -c 'grep pattern file | sort'
8. ミニ課題:実際にやってみよう
結論: 打ち切り・終了ステータス確認・強制終了の 3 問で timeout を手で確かめる。
sleep にしてある。消えて困る中身が無いので、失敗しても何も壊れない。課題 1: sleep 30 を 3 秒で打ち切る
やること: 本来 30 秒かかるコマンドを、3 秒で終わらせよう。
ヒント1(方向づけ)を見る
制限時間を先に書き、そのあとに実行したいコマンドを書く。数字だけを書いた場合の単位は何になるか思い出そう。
ヒント2(コマンド名)を見る
使うのは timeout。形は timeout 時間 コマンド。数字だけなら秒の意味になる。
答えを見る
$ timeout 3 sleep 30
3 秒でプロンプトが戻る。sleep の 30 秒を待たされない。
課題 2: タイムアウトしたか確かめる
やること: 課題 1 のすぐあとに終了ステータスを表示して、124 になることを確かめよう。
ヒント1(方向づけ)を見る
直前のコマンドの結果は、特別な変数に入っている。それを表示するコマンドを使おう。
ヒント2(コマンド名)を見る
直前の結果は $? に入っている。表示は echo $?。
答えを見る
$ timeout 3 sleep 30 $ echo $?
124 が表示されればタイムアウト成功。
課題 3: 止まらないときに強制終了する
やること: sleep 30 を「5 秒で SIGTERM、さらに 2 秒待っても止まらなければ SIGKILL」で止める指定を書こう。
ヒント1(方向づけ)を見る
二段構えにするオプションがある。猶予の秒数と、本来の制限時間の 2 つを並べて書く。
ヒント2(コマンド名)を見る
使うのは -k。並び順は -k 猶予秒 制限秒 コマンド。
答えを見る
$ timeout -k 2 5 sleep 30
sleep は SIGTERM で素直に止まる。だから 5 秒で終わり、SIGKILL までは進まない。
124 を見る。この 2 つが軸ですね。-k を足すだけ。この 3 つで、固まったまま放置される事故はほぼ防げるよ。9. コピペ用テンプレート
結論: 基本・単位付き・判定・強制終了・パイプのよく使う型をまとめて手元に置いておく。
よく使う型をまとめておく
# 基本:10秒で打ち切る timeout 10 コマンド # 単位を付ける(秒 / 分 / 時) timeout 30s コマンド timeout 5m コマンド # タイムアウト判定(124 ならタイムアウト) timeout 10 コマンド echo $? # 止まらないときは強制終了(10秒 + 猶予5秒で SIGKILL) timeout -k 5 10 コマンド # パイプ全体に制限をかける timeout 10 bash -c 'コマンドA | コマンドB' # Ctrl+C 相当(SIGINT)で止める timeout -s SIGINT 10 コマンド
今日の 3 行まとめ
timeout 時間 コマンドで実行時間に上限を付けられる。順番は 時間が先、コマンドが後- 終了ステータス
124はタイムアウトの合図。エラーではなく「予定どおり打ち切った」という意味 - SIGTERM を無視するプロセスには
-k 猶予秒 制限秒で二段構えにする。SIGKILL はいちばん最後の手だて