特定のコマンド(Ctrl-C
によってのみ終了可能)を5分間自動的に実行させる簡単な方法はありますか?
例えば:
minute-command 5-minutes ping www.google.com
または自分自身を終了させないその他のコマンド.
5分だけでなく、制限時間を指定できるようにしたいです。
この機能を提供するプログラムは少なくとも2つあります。
名
timelimit
- プロセスの絶対実行時間を実質的に制限します概要
timelimit [-pq] [-S killsig] [-s warnsig] [-T killtime] [-t warntime] command [arguments ...]
そして
名
timeout
- 時間制限付きでコマンドを実行する概要
timeout [OPTION] DURATION COMMAND [ARG]...
timeout [OPTION]
それらは次のようにパッケージされています。
$ dlocate `which timeout timelimit`
timelimit: /usr/bin/timelimit
coreutils: /usr/bin/timeout
/-----------------------------+------------+----------------\
| Feature | timelimit | timeout |
+=============================+============+================+
| time to run | -t time | first argument |
+-----------------------------+------------+----------------+
| terminate signal | -s signal | -s signal |
+-----------------------------+------------+----------------+
| grace period | -T time | -k time |
+-----------------------------+------------+----------------+
| kill signal | -S signal | (note 1) |
+-----------------------------+------------+----------------+
| propagate signals | -p | (note 2) |
\-----------------------------+------------+----------------/
ノート:
timeout
は常に最後の手段としてSIGKILL
を使います。timeout
には、子プログラムが終了したときにシグナルで終了する機能がありません。2つのプログラムの終了ステータスは異なりますが、まとめるのは難しいので、そのためにはマニュアルページを自分で参照することをお勧めします。
timeout
はデフォルトでより多くのシステムにインストールされるので(coreutils
は多くのディストリビューションの標準パッケージです)、timelimit
が提供する追加の機能が必要でない限り、それを使うことをお勧めします。
実際、これがtimeout
の目的です。
TIMEOUT(1) User Commands TIMEOUT(1)
NAME
timeout - run a command with a time limit
SYNOPSIS
timeout [OPTION] DURATION COMMAND [ARG]...
timeout [OPTION]
DESCRIPTION
Start COMMAND, and kill it if still running after DURATION.
lx@lxtp:~$ dpkg -S /usr/bin/timeout
coreutils: /usr/bin/timeout
bash
name__は組み込まれていません、coreutils私はこの解決法がbash
name__で外部の実行可能ファイルを呼び出さずに組み込みコマンドに頼って機能することを発見しました。それは最終的にさえインストールされていないシステム上で動作しますcoreutils [ 1 ]
YourCommand & read -t 300 ; kill $! # 1st version
YourCommand & read -t 300 || kill $! # 2nd version
説明:&
を使用してバックグラウンドでコマンドを送信すると、通常、そのPIDは内部変数$!
(最新バージョンのdash
name__に存在)に格納されます。 、csh
name__、bash
name__、tcsh
name__、zsh
name __...).
シェル間で実際に違いがあるのは、組み込みコマンドread
name__の存在です。[ 2 ] そして-t
オプションです。 1番目のバージョンでは、指定された秒数の前にユーザーが1行の入力を完了しないと、命令は終了し、エラー戻りコードが生成されます。
- t TIMEOUT入力行全体がTIMEOUT秒以内に読み取られなかった場合、読み取りをタイムアウトにして失敗を返します。
2番目のバージョンは1番目として動作しますが、単に押すだけで殺害タイムアウトを中止することができます enter。
確かに、タイムアウトが期限切れになったときのように、kill
name__コマンドがゼロ以外の戻りコードで終了した場合にのみ、or演算子||
がread
name__ステートメントを実行します。押すと enter その瞬間の前に、それは0を返すでしょう、そしてそれはあなたの前のコマンドを殺しません。
システムにcoreutilsが存在し、外部プログラムを呼び出すための時間とリソースを節約する必要がない場合、timeout
name__とsleep
name__はどちらも目標を達成するのに最適な方法です。
timeout
NAME _timeout
name__の使用は簡単です。
最初の失敗時には追加のkillシグナルを送るために-k
オプションを使うことを検討することができます。
timeout 5m YourCommand # 3rd version
sleep
NAME _sleep
name__を使えば、あなたのファンタジーを利用したり、インスピレーションを得たりすることができます。[]。あなたはあなたのコマンドをバックグラウンドまたはフォアグラウンドで残すことができることに注意してください(例えばtop
name__はフォアグラウンドにある必要があります)。
YourCommand & sleep 5m; kill $! # 4th Background
YourCommand & pid=$! ; (sleep 5m; kill $pid;) & # 5th Background
bash -c '(sleep 5m; kill $$) & exec YourCommand' # 6th Foreground
(cmdpid=$BASHPID; (sleep 5m; kill $cmdpid) & exec YourCommand) # 7th Foreground
説明
YourCommand
name__で実行してから、シェルのsleep
name__sを5分間実行します。それが終了すると、最後のバックグラウンドプロセス($!
)が強制終了されます。あなたはあなたの殻を止めます。YourCommand
name__を実行し、そのPIDを変数$pid
にすぐに格納します。その後、バックグラウンドでnap 5分実行し、その結果として保存されているPIDを強制終了します。このグループのコマンドをバックグラウンドで送信したので、シェルを停止することはありません。 $!
の値はバックグラウンドでの別のプログラムの最終的な実行によって更新される可能性があるため、PIDを変数に格納する必要があります。簡単に言うと、あなたはkill間違ったプロセスまたはまったくプロセスがないという危険を避けられます。$$
によって5分で自殺する新しいbashシェルと呼ばれ、それからフォアグラウンドに残っているあなたのコマンドが実行されます。cmdpid
name__)にPIDを格納し、バックグラウンド実行で送信された別のサブシェルで自分自身を強制終了してから、フォアグラウンドでYourCommandを実行するサブシェル()
が呼び出されます。もちろん、どのバージョンでも、デフォルトのものからextremekill -9
まで必要なkillシグナルを送ることができ、本当に必要なときにだけ使うことができます。
参考文献
あなたの特定のケースでは、ping
のほとんどの実装は-c
または--count
をサポートして、特定の回数のpingの後に終了します。
ping -c 300 Host.example.com
より一般的な解決策については、他の答えを見てください。
あなたはこれのような簡単なスクリプトでそれをすることができます:
#!/bin/bash
#
# $1 is the time to let the program run, and $2, $3, ... are the command itself.
#
"${@:2}" &
PID=$!
sleep "${@:1:1}"
kill -2 $PID
(シグナルSIGINT = 2は、下のコメントでMatija Nalisの提案に従って使用されています)。
(一般的ではない)bash式$@:...
:位置パラメータ($*, $@, "$*", "$@"
)の説明には、例えば以下の追加の指定があります。
"${@:START:COUNT}"
つまり、すべてのパラメータのうち、それらのCOUNT個を取得します。最初に取得されるパラメータは、START番目の位置にあるものです。 COUNTが省略されている場合は、STARTth位置から始めて、それらのすべてを最後まで取ります。 $0
はプログラム名です。 STARTが負の場合は、最後から数え始めます。COUNTは負にできないので、最後の引数は"${@:-1}"
になります。また、約には常に二重引用符で囲まれた位置パラメータが含まれます。
あなたはあなたの例でping
を述べているので。このコマンドには、一定時間経過後に停止するオプションがいくつかあります。
- w締切期限パケットの数にかかわらず ping が終了するまでのタイムアウトを秒単位で指定します。送信または受信されました。この場合、 ping はカウントパケットが送信された後に停止せず、締切期限が期限切れになるまで待機するまたはcount回のプローブが応答されるまで、またはネットワークからの何らかのエラー通知があるまで。
- Wtimeout応答を待つ時間(秒単位)。このオプションは、応答がない場合のタイムアウトのみに影響します。それ以外の場合、 ping は2つのRTTを待ちます。
-
man ping