timeoutコマンドで制限時間付きでコマンドを実行する方法|ハングアップ対策とシェルスクリプト活用も

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Linuxtips, シェルスクリプト > timeoutコマンドで制限時間付きでコマンドを実行する方法|ハングアップ対策とシェルスクリプト活用も
「コマンドを実行したら、いつまで経っても終わらない」
サーバー運用をしていると、ネットワーク遅延やデッドロックでコマンドがハングアップするケースは珍しくありません。

この記事では、timeout コマンドを使って制限時間付きでコマンドを実行する方法を解説します。
シェルスクリプトでのタイムアウト処理、終了コードの読み方、実務でよく使う組み合わせパターンまでカバーします。

この記事のポイント

・timeout コマンドで指定秒数を超えたプロセスを自動終了できる
・終了コード 124 で「タイムアウトによる終了」を判定できる
・--kill-after で SIGTERM の後に SIGKILL を送るダブル保険が設定できる
・cron ジョブや API 呼び出しのハングアップ対策として積極的に使う


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
図解60P/登録10秒/解除も3秒 / 詳細はこちら

timeoutコマンドとは|なぜ必要なのか

サーバー運用で「コマンドがハングアップする」ケースには主に3つの原因があります。

・NFS や SMB マウント先がネットワーク経路の問題で応答しなくなった
・curl や wget でリモートホストが無応答のまま接続を保持している
・デッドロックが発生したプロセスがいつまでもロックを解放しない

このような状況に対処するのが timeout コマンドです。
指定した秒数が経過してもコマンドが終了しなかった場合、シグナルを送って強制終了します。

実行環境:RHEL 9.4 / Ubuntu 24.04 LTS(coreutils パッケージに含まれる)

基本的な使い方

1. 書式と基本動作を確認する

書式は非常にシンプルです。

# 基本書式 timeout 秒数 コマンド [引数...] # 例: 5秒以内に終わらなければ終了する $ timeout 5 sleep 10 $ echo $? 124

上記を実行すると sleep 10 は 5 秒で強制終了され、終了コード 124 が返ります。

タイムアウトが発生しなかった場合は、実行したコマンドの終了コードがそのまま返ります。
このため、スクリプト内では「終了コード 124 = タイムアウトによる終了」として判定できます。

2. 時間単位を指定する

秒数の代わりに単位付きで指定できます。

# 30秒(単位なしの数値は秒) timeout 30 コマンド # 2分 timeout 2m コマンド # 1時間 timeout 1h コマンド # 90分(分単位で指定) timeout 90m コマンド

使える単位は s(秒)・m(分)・h(時間)・d(日)です。

3. 送信するシグナルを変更する

デフォルトでは SIGTERM(番号15)が送信されます。
プロセスによっては SIGTERM を無視するものがあるため、-s オプションでシグナルを指定できます。

# SIGKILL(強制終了)を送信する timeout -s SIGKILL 10 コマンド # シグナル番号で指定(9=SIGKILL) timeout -s 9 10 コマンド

応用・実務Tips

1. --kill-after でダブル保険をかける

SIGTERM を送ってもプロセスが終了しないケースがあります。
--kill-after(短縮形 -k)を使うと、SIGTERM の後に指定秒数待って、まだ動いていれば SIGKILL を送ります。

# 30秒でSIGTERM → さらに10秒待ってSIGKILL timeout --kill-after=10 30 コマンド # 短縮形 timeout -k 10 30 コマンド

サーバー上のバッチ処理では、このパターンを標準化しておくことでゾンビプロセスの発生を防げます。

2. シェルスクリプトでタイムアウト判定する

#!/bin/bash # 外部APIを30秒以内に呼び出す例 timeout 30 curl -s https://api.example.com/status -o /tmp/api_result.json EXIT_CODE=$? if [ $EXIT_CODE -eq 124 ]; then echo "ERROR: APIへの接続がタイムアウトしました" >&2 exit 1 elif [ $EXIT_CODE -ne 0 ]; then echo "ERROR: curl が失敗しました(終了コード: ${EXIT_CODE})" >&2 exit 1 fi echo "API応答を取得しました" cat /tmp/api_result.json

$? を変数に保存するのがポイントです。
if 文の直前に他のコマンドを挟むと終了コードが上書きされるため、必ず変数に退避してから判定します。

3. cron ジョブのハングアップ対策

cron で定期実行しているジョブがハングアップすると、次の実行が重複して起動されます。
timeout を組み合わせることでジョブの最大実行時間を保証できます。

# /etc/cron.d/backup-job の設定例 # バックアップスクリプトを最大115分でタイムアウトさせる 0 2 * * * root timeout -k 60 115m /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

私が運用しているサーバーでも、NFS マウント先のストレージ障害でバックアップスクリプトが数時間ハングアップした経験があります。
その後、全バッチジョブに timeout を標準導入しました。

なお、Apache のタイムアウト設定は timeout コマンドではなく httpd.conf の Timeout ディレクティブで行います。
詳しくはApache タイムアウト設定の詳細を参照してください。

4. 対話型コマンドに使う場合の注意

パスワードを求める SSH や sudo のような対話型コマンドは、
timeout ではなく SSH の ConnectTimeout オプションなど専用の設定を使うのが適切です。

# SSH接続のタイムアウトは -o ConnectTimeout が正しい ssh -o ConnectTimeout=10 user@192.0.2.10 "コマンド" # コマンド全体に上限をかけたい場合は timeout との組み合わせも有効 timeout 60 ssh -o ConnectTimeout=10 user@192.0.2.10 "バッチ処理.sh"

トラブルシュート|よくある問題と対処法

「タイムアウトしているはずなのにプロセスが残る」

SIGTERM を無視するプロセスや、子プロセスを生成して制御が分散している場合に起きます。
--kill-after を必ず併用してください。

それでも残る場合は、setsid でプロセスグループリーダーにしてから timeout を実行すると効果的です。

# setsid でプロセスグループをまとめて timeout にかける timeout --kill-after=5 30 setsid コマンド # プロセスが残っているか確認(ss / lsof でポートを確認するのも有効) ss -tlnp | grep ポート番号

ハングアップしたプロセスが特定のポートを掴んでいる場合は、Linux ポート確認の全コマンドを参考に特定してください。

「timeout: failed to run command: No such file or directory」

コマンド名のスペルミス、またはコマンドが PATH に含まれていないことが原因です。

# コマンドが存在するか確認する which コマンド名 type コマンド名 # 絶対パスで指定する timeout 30 /usr/local/bin/myscript.sh

「古いシステムで timeout コマンドが見つからない」

timeout は coreutils 7.0 以降(2009年リリース)に含まれます。
RHEL 6 以前など古い環境では未インストールの場合があります。

# インストール確認(RHEL/Rocky 系) rpm -q coreutils # インストール確認(Ubuntu/Debian 系) dpkg -l coreutils # バージョン確認 timeout --version

本記事のまとめ

やりたいこと コマンド
30秒でタイムアウトさせる timeout 30 コマンド
2分でタイムアウトさせる timeout 2m コマンド
SIGTERM後10秒でSIGKILL timeout --kill-after=10 30 コマンド
終了コードでタイムアウト判定 EXIT=$?; [ $EXIT -eq 124 ]
シグナル種別を指定する timeout -s SIGKILL 10 コマンド
SSH接続タイムアウト(推奨) ssh -o ConnectTimeout=10 user@host
Linux でコマンドがハングアップする状況は、ネットワーク障害やストレージ障害など予測不能なタイミングで発生します。

timeout コマンドをシェルスクリプトや cron ジョブに組み込んでおくことで、
ハングアップが起きても影響を最小限に抑えられます。

シグナル処理の詳細についてはLinux 基本コマンドの解説もあわせて参考にしてください。

シェルスクリプトの書き方や、サーバー運用の「型」が身についていますか?

timeout コマンドひとつとっても、終了コードの読み方や --kill-after の使い所を知らなければ、ハングアップが起きたときに対処できません。
ネットの切れ端の情報をコピペするだけでなく、現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。

「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

登録10秒/合わなければ解除3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として15年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。