web-dev-qa-db-ja.com

5分間コマンドを実行させる簡単な方法は何ですか?

特定のコマンド(Ctrl-Cによってのみ終了可能)を5分間自動的に実行させる簡単な方法はありますか?

例えば:

minute-command 5-minutes ping www.google.com

または自分自身を終了させないその他のコマンド.

5分だけでなく、制限時間を指定できるようにしたいです。

64
eckhart

この機能を提供するプログラムは少なくとも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)       |
\-----------------------------+------------+----------------/

ノート:

  1. timeoutは常に最後の手段としてSIGKILLを使います。
  2. timeoutには、子プログラムが終了したときにシグナルで終了する機能がありません。

2つのプログラムの終了ステータスは異なりますが、まとめるのは難しいので、そのためにはマニュアルページを自分で参照することをお勧めします。

timeoutはデフォルトでより多くのシステムにインストールされるので(coreutilsは多くのディストリビューションの標準パッケージです)、timelimitが提供する追加の機能が必要でない限り、それを使うことをお勧めします。

65
Toby Speight

実際、これが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
87
Gombai Sándor

純粋なbashname__は組み込まれていません、coreutils

私はこの解決法がbashname__で外部の実行可能ファイルを呼び出さずに組み込みコマンドに頼って機能することを発見しました。それは最終的にさえインストールされていないシステム上で動作しますcoreutils [ 1 ]

YourCommand & read -t 300 ;  kill $!                           # 1st version
YourCommand & read -t 300 || kill $!                           # 2nd version 

説明&を使用してバックグラウンドでコマンドを送信すると、通常、そのPIDは内部変数$!(最新バージョンのdashname__に存在)に格納されます。 、cshname__、bashname__、tcshname__、zshname __...).
シェル間で実際に違いがあるのは、組み込みコマンドreadname__の存在です。[ 2 ] そして-tオプションです。 1番目のバージョンでは、指定された秒数の前にユーザーが1行の入力を完了しないと、命令は終了し、エラー戻りコードが生成されます。

- t TIMEOUT入力行全体がTIMEOUT秒以内に読み取られなかった場合、読み取りをタイムアウトにして失敗を返します。

2番目のバージョンは1番目として動作しますが、単に押すだけで殺害タイムアウトを中止することができます enter
確かに、タイムアウトが期限切れになったときのように、killname__コマンドがゼロ以外の戻りコードで終了した場合にのみ、or演算子||readname__ステートメントを実行します。押すと enter その瞬間の前に、それは0を返すでしょう、そしてそれはあなたの前のコマンドを殺しません。


Coreutilsソリューション [ 1 ]

システムにcoreutilsが存在し、外部プログラムを呼び出すための時間とリソースを節約する必要がない場合、timeoutname__とsleepname__はどちらも目標を達成するのに最適な方法です。

timeoutNAME _timeoutname__の使用は簡単です。
最初の失敗時には追加のkillシグナルを送るために-kオプションを使うことを検討することができます。

timeout 5m YourCommand                                         # 3rd version 

sleepNAME _sleepname__を使えば、あなたのファンタジーを利用したり、インスピレーションを得たりすることができます。[]。あなたはあなたのコマンドをバックグラウンドまたはフォアグラウンドで残すことができることに注意してください(例えばtopname__はフォアグラウンドにある必要があります)。

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

説明

  • 4番目のバージョンでは、バックグラウンドYourCommandname__で実行してから、シェルのsleepname__sを5分間実行します。それが終了すると、最後のバックグラウンドプロセス($!)が強制終了されます。あなたはあなたの殻を止めます。
  • 5番目のバージョンでは、代わりにバックグラウンドでYourCommandname__を実行し、そのPIDを変数$pidにすぐに格納します。その後、バックグラウンドでnap 5分実行し、その結果として保存されているPIDを強制終了します。このグループのコマンドをバックグラウンドで送信したので、シェルを停止することはありません。 $!の値はバックグラウンドでの別のプログラムの最終的な実行によって更新される可能性があるため、PIDを変数に格納する必要があります。簡単に言うと、あなたはkill間違ったプロセスまたはまったくプロセスがないという危険を避けられます。
  • 6番目のバージョンでは、 $$ によって5分で自殺する新しいbashシェルと呼ばれ、それからフォアグラウンドに残っているあなたのコマンドが実行されます。
  • 7番目のバージョンでは、変数(cmdpidname__)にPIDを格納し、バックグラウンド実行で送信された別のサブシェルで自分自身を強制終了してから、フォアグラウンドでYourCommandを実行するサブシェル()が呼び出されます。

もちろん、どのバージョンでも、デフォルトのものからextremekill -9まで必要なkillシグナルを送ることができ、本当に必要なときにだけ使うことができます。

参考文献

  • [ 1 ] Coreutils
  • [ 2 ] Bash初心者ガイド
  • [] BashFAQ
15
Hastur

あなたの特定のケースでは、pingのほとんどの実装は-cまたは--countをサポートして、特定の回数のpingの後に終了します。

ping -c 300 Host.example.com

より一般的な解決策については、他の答えを見てください。

10
Toby Speight

あなたはこれのような簡単なスクリプトでそれをすることができます:

#!/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}"になります。また、約には常に二重引用符で囲まれた位置パラメータが含まれます。

8
MariusMatutiae

あなたはあなたの例でpingを述べているので。このコマンドには、一定時間経過後に停止するオプションがいくつかあります。

  • w締切期限パケットの数にかかわらず ping が終了するまでのタイムアウトを秒単位で指定します。送信または受信されました。この場合、 ping カウントパケットが送信された後に停止せず、締切期限が期限切れになるまで待機するまたはcount回のプローブが応答されるまで、またはネットワークからの何らかのエラー通知があるまで。
  • Wtimeout応答を待つ時間(秒単位)。このオプションは、応答がない場合のタイムアウトのみに影響します。それ以外の場合、 ping は2つのRTTを待ちます。

- man ping

4
user2428118