不要な遅延なしにコマンドをbashでタイムアウトする


283

この回答のコマンドラインコマンド一定の時間が経過するコマンドを自動殺します

は、bashコマンドラインから実行時間の長いコマンドをタイムアウトする1行の方法を提案しています。

( /path/to/slow command with options ) & sleep 5 ; kill $!

ただし、特定の「長時間実行」コマンドがタイムアウトよりも早く終了する可能性があります。(これを「通常は長時間実行するが時々高速」なコマンド、または楽しみのためにtlrbsfと呼びましょう。)

したがって、この気の利いた1ライナーアプローチにはいくつかの問題があります。まず、これsleepは条件付きではないため、シーケンスの完了にかかる時間に望ましくない下限が設定されます。tlrbsfコマンドが2秒で終了するスリープには、30 秒、2分、さらには5分を考慮してください。これは非常に望ましくありません。第二に、killは無条件であるため、このシーケンスは、実行されていないプロセスを強制終了し、それについて駄々をこねることを試みます。

そう...

通常は長時間実行されるが時々高速な("tlrbsf")コマンドをタイムアウトする方法はありますか。

  • bash実装があります(他の質問にはすでにPerlとCの回答があります)
  • tlrbsfプログラムの終了、またはタイムアウトの経過のどちらか早い方で終了します
  • 存在しない/実行されていないプロセスを強制終了しません(またはオプションで、不正な強制終了について文句を言いません)
  • ワンライナーである必要はありません
  • CygwinまたはLinuxで実行できます

...ボーナスポイントについては、フォアグラウンドでtlrbsfコマンドを実行し、バックグラウンドで「スリープ」または追加のプロセスを実行します。これにより、tlrbsfコマンドのstdin / stdout / stderrをリダイレクトできます。直接実行しますか?

その場合は、コードを共有してください。そうでない場合は、その理由を説明してください。

私は前述の例をハックするためにしばらく費やしてきましたが、bashスキルの限界に達しています。


5
同様の別の質問:stackoverflow.com/questions/526782/…(ただし、ここでの「timeout3」の回答の方がはるかに良いと思います)。
system PAUSE

2
gnu timeoutユーティリティを使用しない理由は何ですか?
クリスジョンソン

timeout素晴らしいです!複数のコマンド(複数行スクリプト)で使用することもできますstackoverflow.com/a/61888916/658497
Noam Manos

回答:


149

これはまさにあなたが求めていることだと思います:

http://www.bashcookbook.com/bashinfo/source/bash-4.0/examples/scripts/timeout3

#!/bin/bash
#
# The Bash shell script executes a command with a time-out.
# Upon time-out expiration SIGTERM (15) is sent to the process. If the signal
# is blocked, then the subsequent SIGKILL (9) terminates it.
#
# Based on the Bash documentation example.

# Hello Chet,
# please find attached a "little easier"  :-)  to comprehend
# time-out example.  If you find it suitable, feel free to include
# anywhere: the very same logic as in the original examples/scripts, a
# little more transparent implementation to my taste.
#
# Dmitry V Golovashkin <Dmitry.Golovashkin@sas.com>

scriptName="${0##*/}"

declare -i DEFAULT_TIMEOUT=9
declare -i DEFAULT_INTERVAL=1
declare -i DEFAULT_DELAY=1

# Timeout.
declare -i timeout=DEFAULT_TIMEOUT
# Interval between checks if the process is still alive.
declare -i interval=DEFAULT_INTERVAL
# Delay between posting the SIGTERM signal and destroying the process by SIGKILL.
declare -i delay=DEFAULT_DELAY

function printUsage() {
    cat <<EOF

Synopsis
    $scriptName [-t timeout] [-i interval] [-d delay] command
    Execute a command with a time-out.
    Upon time-out expiration SIGTERM (15) is sent to the process. If SIGTERM
    signal is blocked, then the subsequent SIGKILL (9) terminates it.

    -t timeout
        Number of seconds to wait for command completion.
        Default value: $DEFAULT_TIMEOUT seconds.

    -i interval
        Interval between checks if the process is still alive.
        Positive integer, default value: $DEFAULT_INTERVAL seconds.

    -d delay
        Delay between posting the SIGTERM signal and destroying the
        process by SIGKILL. Default value: $DEFAULT_DELAY seconds.

As of today, Bash does not support floating point arithmetic (sleep does),
therefore all delay/time values must be integers.
EOF
}

# Options.
while getopts ":t:i:d:" option; do
    case "$option" in
        t) timeout=$OPTARG ;;
        i) interval=$OPTARG ;;
        d) delay=$OPTARG ;;
        *) printUsage; exit 1 ;;
    esac
done
shift $((OPTIND - 1))

# $# should be at least 1 (the command to execute), however it may be strictly
# greater than 1 if the command itself has options.
if (($# == 0 || interval <= 0)); then
    printUsage
    exit 1
fi

# kill -0 pid   Exit code indicates if a signal may be sent to $pid process.
(
    ((t = timeout))

    while ((t > 0)); do
        sleep $interval
        kill -0 $$ || exit 0
        ((t -= interval))
    done

    # Be nice, post SIGTERM first.
    # The 'exit 0' below will be executed if any preceeding command fails.
    kill -s SIGTERM $$ && kill -0 $$ || exit 0
    sleep $delay
    kill -s SIGKILL $$
) 2> /dev/null &

exec "$@"

これは、背景部分に$$を使用する鋭いトリックです。ハングしたtlrbsfをすぐに殺すことができるのは素晴らしいことです。しかし、うーん、あなたはポーリング間隔を選択する必要があります。また、ポーリングの設定が低すぎると、CPUが一定のシグナルで消費され、tlrbsfがさらに長く実行されます。
system PAUSE

7
ポーリング間隔を選択する必要はありません。デフォルトの1があり、これで十分です。そして、チェックは非常に安価で、オーバーヘッドは無視できます。tlrbsfが著しく長くなるとは思えません。私はスリープ30でテストし、それを使用した場合と使用しない場合で0.000msの差が出ました。
ジュリアーノ

6
そうです、今それがわかります。そして、ポーリング間隔==タイムアウトを設定した場合、それは私の正確な要件を満たします。パイプラインでも機能し、バックグラウンド全体で機能し、複数のインスタンスや他の実行中のジョブで機能します。甘い、ありがとう!
system PAUSE

シグナルを送信するとサブシェルが終了するので、すべてのkillコマンドを1行に並べるとそれらが保持されると思いました。stderr出力を有効にして、予期しないエラーを表示しました。 stackoverflow.com/questions/687948/...
ウナギghEEz

1
@Julianoこれはタイムアウトを処理する優れた方法であり、非常に便利です。タイムアウト後にプロセスが強制終了されたときにスクリプトが終了コード143を返すようにする方法はあるのでしょうか。killコマンドの直後に「exit 143」を追加しようとしましたが、呼び出し元のスクリプトで常に終了コード0が返されます。
Salman A. Kagzi 2013

528

おそらくtimeoutcoreutilsでコマンドを探しています。これはcoreutilsの一部であるため、技術的にはCソリューションですが、それでもcoreutilsです。info timeout詳細については。次に例を示します。

timeout 5 /path/to/slow/command with options

21
Macでは、Macportsまたは自作でインストールできます。
Ivan Z. Siu 2012年

23
OS XでHomebrewを使用してインストールすると、コマンドはgtimeout
ethicalhack3r

5
... 2003年以前のcoreutilsを使用しているどのOSを使用していますか?
キース

5
@キース:CentOS 5.10、例えば:-(
通知があるまで一時停止。

9
明確にするために、OSX / macで必要なhomebrewコマンドはbrew install coreutilsであり、を使用できますgtimeout
Ohad Schneider

37

このソリューションは、bashモニターモードに関係なく機能します。適切な信号を使用してyour_commandを終了できます

#!/bin/sh
( your_command ) & pid=$!
( sleep $TIMEOUT && kill -HUP $pid ) 2>/dev/null & watcher=$!
wait $pid 2>/dev/null && pkill -HUP -P $watcher

ウォッチャーは、指定されたタイムアウト後にyour_commandを強制終了します。スクリプトは遅いタスクを待ち、ウォッチャーを終了します。wait別のシェルの子であるプロセスでは機能しないことに注意してください。

例:

  • your_commandが2秒以上実行され、終了しました

your_commandが中断されました

( sleep 20 ) & pid=$!
( sleep 2 && kill -HUP $pid ) 2>/dev/null & watcher=$!
if wait $pid 2>/dev/null; then
    echo "your_command finished"
    pkill -HUP -P $watcher
    wait $watcher
else
    echo "your_command interrupted"
fi
  • your_commandはタイムアウト(20秒)の前に終了しました

your_commandが終了しました

( sleep 2 ) & pid=$!
( sleep 20 && kill -HUP $pid ) 2>/dev/null & watcher=$!
if wait $pid 2>/dev/null; then
    echo "your_command finished"
    pkill -HUP -P $watcher
    wait $watcher
else
    echo "your_command interrupted"
fi

1
wait待機しているプロセスの終了ステータスを返します。したがって、コマンドが割り当てられた時間内に終了するが、終了ステータスがゼロ以外の場合、ここでのロジックはタイムアウトしたように動作します(つまり、print)your_command interrupted。代わりに、なしでを実行し、pidがまだ存在するかどうかを確認できます。存在する場合は、タイムアウトしなかったことがわかります。waitif$watcher
George Hawkins、

なぜこれkillが一方のケースで使用されるのか、もう一方のケースで使用される理由がわかりませんpkillpkillこれを正しく動作させるには、両方に使用する必要がありました。コマンドをでラップした場合は()、を使用pkillして強制終了する必要があると思います。ただし、内にコマンドが1つしかない場合は、動作が異なる可能性があり()ます。
nobar

神はあなたを祝福します:)
Darko Miletic

22

どうぞ。

timeout --signal=SIGINT 10 /path/to/slow command with options

あなたは、変更される可能性SIGINT10、あなたが望むよう;)


3
"timeout"は(少なくとも)Redhat、Centos、Suse、Ubuntu のcoreutilsパッケージの一部なので、持っていない場合はインストールする必要があります。
Akom

それは本当に役に立ちます!!!!!! yingtedの「タイムアウト5 / path / to / slow / command with options」が機能しないことがある理由を知っていますか?
Decula

残念ながら、これはcoreutilsFreeBSD のパッケージには含まれていません。
ポールビセックス

18

あなたは完全にこれbash 4.3以上でこれを行うことができます:

_timeout() { ( set +b; sleep "$1" & "${@:2}" & wait -n; r=$?; kill -9 `jobs -p`; exit $r; ) }
  • 例: _timeout 5 longrunning_command args
  • 例: { _timeout 5 producer || echo KABOOM $?; } | consumer
  • 例: producer | { _timeout 5 consumer1; consumer2; }
  • 例: { while date; do sleep .3; done; } | _timeout 5 cat | less

  • Bash 4.3が必要 wait -n

  • コマンドが強制終了された場合は137を返し、それ以外の場合はコマンドの戻り値を返します。
  • パイプに使えます。(ここでフォアグラウンドにする必要はありません!)
  • 内部シェルコマンドまたは関数でも動作します。
  • サブシェルで実行されるため、現在のシェルに変数をエクスポートできません。申し訳ありません。

戻りコードが必要ない場合は、これをさらに簡単にすることができます。

_timeout() { ( set +b; sleep "$1" & "${@:2}" & wait -n; kill -9 `jobs -p`; ) }

ノート:

  • 厳密に言うと;in は必要ありませんが; ); }-caseとの一貫性が高まります。また、set +bおそらくはそのままにすることもできますが、申し訳ありませんが安全です。

  • --forground(おそらく)を除いて、すべてのバリアントtimeoutサポートを実装できます。 --preserve-statusただし、少し難しいです。これは読者のための演習として残されています;)

このレシピはシェルで「自然に」使用できます(のように自然ですflock fd):

(
set +b
sleep 20 &
{
YOUR SHELL CODE HERE
} &
wait -n
kill `jobs -p`
)

ただし、上記で説明したように、この方法で環境変数を封入シェルに再エクスポートすることはできません。

編集:

現実の例:時間__git_ps1がかかりすぎる場合のタイムアウト(遅いSSHFSリンクなどの場合):

eval "__orig$(declare -f __git_ps1)" && __git_ps1() { ( git() { _timeout 0.3 /usr/bin/git "$@"; }; _timeout 0.3 __orig__git_ps1 "$@"; ) }

Edit2:バグ修正。私はそれexit 137が必要ではないことに気づき_timeout、同時に信頼できなくなりました。

Edit3:git非常に難しいので、満足に動作するにはダブルトリックが必要です。

Edit4:実世界のGITの例の_最初のa を忘れました_timeout


1
バッシュ4石。以上です。
system PAUSE

1
これには実際にはBash 4.3以降が必要です。 cc. The 'wait' builtin has a new '-n' option to wait for the next child to change status. From:tiswww.case.edu/php/chet/bash/NEWS
Ben Reser

17

私は「timelimit」を好んでいます。これは少なくともdebianのパッケージを持っています。

http://devel.ringlet.net/sysutils/timelimit/

coreutilsの "timeout"よりも少し優れています。これは、プロセスを強制終了するときに何かを出力し、デフォルトではしばらくしてからSIGKILLも送信するためです。


それはかなりうまく機能していないようです:/ $ time timelimit -T2 sleep 10 real 0m10.003s user 0m0.000s sys 0m0.000s
hithwen

3
-T2ではなく-t2を使用してください。大きな-Tは、SIGTERMを送信してからSIGKILLを送信するまでの時間です。
maxy '27 / 06/27

1
私はtimelimit 1.8がforkでうまく機能するように継ぎ目を付けない(timelimit -t1 ./a_forking_prog2つのプロセスのうちの1つだけをkillする)が、タイムアウトは機能することを追加したいと思います。
ジェレミーコチョイ2013

プロセスを強制終了するときにタイムアウトで何かを出力したい場合は、「-v」フラグを使用してください。

10

slowcommand1秒後にタイムアウトするには:

timeout 1 slowcommand || echo "I failed, perhaps due to time out"

コマンドがタイムアウトしたか、独自の理由で失敗したかを判断するには、ステータスコードが124かどうかを確認します。

# ping for 3 seconds, but timeout after only 1 second
timeout 1 ping 8.8.8.8 -w3
EXIT_STATUS=$?
if [ $EXIT_STATUS -eq 124 ]
then
echo 'Process Timed Out!'
else
echo 'Process did not timeout. Something else went wrong.'
fi
exit $EXIT_STATUS

終了ステータスが124の場合、timeoutコマンドが原因でタイムアウトになったのか、コマンド自体の内部タイムアウトロジックが原因でコマンド自体が終了してから124が返されたのかがわからないことに注意してください。どちらの場合も安全に想定できます。ただし、なんらかのタイムアウトが発生した。



8

ちょっとハッキーですが、動作します。他のフォアグラウンドプロセスがある場合は機能しません(これを修正してください!)

sleep TIMEOUT & SPID=${!}; (YOUR COMMAND HERE; kill ${SPID}) & CPID=${!}; fg 1; kill ${CPID}

実際には、あなたの「ボーナス」基準を満たせば、それを元に戻すことができると思います。

(YOUR COMMAND HERE & SPID=${!}; (sleep TIMEOUT; kill ${SPID}) & CPID=${!}; fg 1; kill ${CPID}) < asdf > fdsa

(ls -ltR / cygdrive / c / windows&SPID = $ {!};(sleep 1s; kill $ {SPID})&CPID = $ {!}; fg 1; kill $ {CPID})> fdsa
システムの一時停止

bash:fg:ジョブ制御なし
システムPAUSE

@system PAUSE、set -m、と思います。
ストレッジャー2009年

ログインシェルにジョブ制御(set -m)があります。これは、$-のhimBHコンテンツの「m」ですが、サブシェルでは表示されないようです。おそらくCygwinアーティファクト。grumble
システムPAUSE

スクリプトで「fg」を使用しないでください。「ヘルプ待機」をお読みください。
lhunath 2009年

8

タイムアウトはおそらく最初に試す方法です。タイムアウトした場合は、通知または別のコマンドを実行する必要がある場合があります。かなりの検索と実験を行った後、私はこのbashスクリプトを思いつきました。

if 
    timeout 20s COMMAND_YOU_WANT_TO_EXECUTE;
    timeout 20s AS_MANY_COMMANDS_AS_YOU_WANT;
then
    echo 'OK'; #if you want a positive response
else
    echo 'Not OK';
    AND_ALTERNATIVE_COMMANDS
fi

5

コードが明確な単純なスクリプト。に保存/usr/local/bin/run

#!/bin/bash

# run
# Run command with timeout $1 seconds.

# Timeout seconds
timeout_seconds="$1"
shift

# PID
pid=$$

# Start timeout
(
  sleep "$timeout_seconds"
  echo "Timed out after $timeout_seconds seconds"
  kill -- -$pid &>/dev/null
) &
timeout_pid=$!

# Run
"$@"

# Stop timeout
kill $timeout_pid &>/dev/null

実行時間が長すぎるコマンドをタイムアウトにします。

$ run 2 sleep 10
Timed out after 2 seconds
Terminated
$

完了するコマンドの場合は直ちに終了します。

$ run 10 sleep 2
$

3

programタイムアウト後(例:3秒)に終了するプログラムの名前(と仮定しましょう)がわかっている場合は、単純でやや汚い代替ソリューションを提供できます。

(sleep 3 && killall program) & ./program

システムコールでベンチマークプロセスを呼び出すと、これは完全に機能します。


2
これにより、たまたま名前を使用している他のプロセスが強制終了され、名前が変更された場合(たとえば、に書き込むことによりargv[0]、おそらく他のハックでより多くのスペースを作ることにより)、指定された名前のプロセスは強制終了されません。
2012

一定時間後にDockerコンテナーを停止しようとすると、この便利なバリエーションが見つかりました。Dockerクライアントは、フォアグラウンドで実行されていたコンテナーを実際に停止するような方法でTERM / INT / KILLを受け入れないようでした。したがって、コンテナに名前を付けて使用すると(sleep 3 && docker stop <container>) &うまくいきました。ありがとう!
Mat Schaffer 2015

はい、それはダートで制限されていますが、次のように改善できます:{ sleep 5 && kill -9 $(ps -fe | grep "program" | grep $$ | tr -s " " | cut -d" " -f2); } & SLEEPPID=$!; bash -c "program" && kill -9 $SLEEPPID"このようにして、現在のシェルのジョブのみを殺します。
トン

2

ありますcratimeout(UnixおよびLinuxシステム用にCで書かれた)マーティンCracauerで。

# cf. http://www.cons.org/cracauer/software.html
# usage: cratimeout timeout_in_msec cmd args
cratimeout 5000 sleep 1
cratimeout 5000 sleep 600
cratimeout 5000 tail -f /dev/null
cratimeout 5000 sh -c 'while sleep 1; do date; done'

「特に、信号の動作を維持します。」そのオプションがあればうれしい!
システムポーズ

1

OS Xはまだbash 4を使用しておらず、/ usr / bin / timeoutも使用していないため、/ usr / bin / timeout(Tinoの回答)。パラメータの検証、ヘルプ、使用法、および他の信号のサポートは、読者の課題です。

# implement /usr/bin/timeout only if it doesn't exist
[ -n "$(type -p timeout 2>&1)" ] || function timeout { (
    set -m +b
    sleep "$1" &
    SPID=${!}
    ("${@:2}"; RETVAL=$?; kill ${SPID}; exit $RETVAL) &
    CPID=${!}
    wait %1
    SLEEPRETVAL=$?
    if [ $SLEEPRETVAL -eq 0 ] && kill ${CPID} >/dev/null 2>&1 ; then
      RETVAL=124
      # When you need to make sure it dies
      #(sleep 1; kill -9 ${CPID} >/dev/null 2>&1)&
      wait %2
    else
      wait %2
      RETVAL=$?
    fi
    return $RETVAL
) }

0

99%の場合、答えはタイムアウトロジックを実装することではありません。タイムアウトロジックは、ほとんどすべての状況で、他の問題があり、代わりに修正する必要があることを示す赤い警告サインです。

プロセスがn秒後にハングまたは中断することがありますか?次に、理由を見つけて、代わりに修正します。

余談ですが、ストレッジャーのソリューションを正しく実行するには、fg 1の代わりに待機 "$ SPID"を使用する必要があります。スクリプトではジョブを制御できないためです(それをオンにしようとするのはばかげています)。さらに、fg 1は、以前にスクリプトで他のジョブを開始しなかったという事実に依存しています。


4
ソース(およびネットワークスイッチなどのほとんどのハードウェア)の100%にアクセスできるので、タイムアウトよりも優れた解決策があることに同意します。ただし、「tlrbsf」がクローズドソースのバイナリのみの場合は、その制限を回避する必要がある場合があります。
システムの一時停止

@lhunathは、「スクリプトで、あなたは、ジョブ制御を持っている(とそれをオンにしようとする愚かである)していない」 -ここで明確にしてください:stackoverflow.com/questions/690266/...
システムPAUSE

@system PAUSE:返信stackoverflow.com/questions/690266/…は正しい、私もそれにコメントしました。
lhunath 2009年

29
lhunath、あなたが言っていることは意味がありません。たとえば、ネットワークを経由する必要があるときはいつでも、タイムアウトが良いオプションである場合がたくさんあります。
ネイト・マレー

例外:既に実行中のソフトウェアにタイムアウトの問題がないかどうかを確認するためのテストスクリプトを作成しているとします。
peterh-モニカを復活させる

0

シェルコンテキストを保持し、タイムアウトを許可するという問題が発生しました。それに関する唯一の問題は、タイムアウト時にスクリプトの実行が停止することですが、表示されたニーズには問題ありません。

#!/usr/bin/env bash

safe_kill()
{
  ps aux | grep -v grep | grep $1 >/dev/null && kill ${2:-} $1
}

my_timeout()
{
  typeset _my_timeout _waiter_pid _return
  _my_timeout=$1
  echo "Timeout($_my_timeout) running: $*"
  shift
  (
    trap "return 0" USR1
    sleep $_my_timeout
    echo "Timeout($_my_timeout) reached for: $*"
    safe_kill $$
  ) &
  _waiter_pid=$!
  "$@" || _return=$?
  safe_kill $_waiter_pid -USR1
  echo "Timeout($_my_timeout) ran: $*"
  return ${_return:-0}
}

my_timeout 3 cd scripts
my_timeout 3 pwd
my_timeout 3 true  && echo true || echo false
my_timeout 3 false && echo true || echo false
my_timeout 3 sleep 10
my_timeout 3 pwd

出力:

Timeout(3) running: 3 cd scripts
Timeout(3) ran: cd scripts
Timeout(3) running: 3 pwd
/home/mpapis/projects/rvm/rvm/scripts
Timeout(3) ran: pwd
Timeout(3) running: 3 true
Timeout(3) ran: true
true
Timeout(3) running: 3 false
Timeout(3) ran: false
false
Timeout(3) running: 3 sleep 10
Timeout(3) reached for: sleep 10
Terminated

もちろん、私は呼ばれるディレクトリがあったと思います scripts


0
#! /bin/bash
timeout=10
interval=1
delay=3
(
    ((t = timeout)) || :

    while ((t > 0)); do
        echo "$t"
        sleep $interval
        # Check if the process still exists.
        kill -0 $$ 2> /dev/null || exit 0
        ((t -= interval)) || :
    done

    # Be nice, post SIGTERM first.
    { echo SIGTERM to $$ ; kill -s TERM $$ ; sleep $delay ; kill -0 $$ 2> /dev/null && { echo SIGKILL to $$ ; kill -s KILL $$ ; } ; }
) &

exec "$@"

@Tinoすみませんプロセスの終了行を変更した理由と、これを共有することが重要だと思った理由を忘れてしまいました。残念ながら私はこれを書き留めませんでした。おそらく、kill -s TERMの成功を確認する前に一時停止する必要があることがわかりました。クックブックからの2008年のスクリプトは、SIGTERMを送信した直後にプロセスの状態をチェックしているようで、SIGKILLを停止したプロセスに送信しようとしてエラーが発生する可能性があります。
eel ghEEz 2015

0

私の問題は多分少し異なっていました:リモートマシンでsshを介してコマンドを開始し、コマンドがハングした場合にシェルと子を殺したいと思います。

私は今以下を使用します:

ssh server '( sleep 60 && kill -9 0 ) 2>/dev/null & my_command; RC=$? ; sleep 1 ; pkill -P $! ; exit $RC'

このように、コマンドは、タイムアウトが発生した場合は255を返し、成功した場合はコマンドのリターンコードを返します。

sshセッションからのプロセスの強制終了は、対話型シェルとは異なる方法で処理されることに注意してください。ただし、-tオプションを使用してsshに疑似端末を割り当てることもできるため、インタラクティブシェルのように機能します。


0

これは、子プロセスの生成に依存しないバージョンです。この機能を組み込んだスタンドアロンスクリプトが必要でした。また、部分的なポーリング間隔も実行されるため、より速くポーリングできます。タイムアウトが優先されたでしょう-しかし、私は古いサーバーで立ち往生しています

# wait_on_command <timeout> <poll interval> command
wait_on_command()
{
    local timeout=$1; shift
    local interval=$1; shift
    $* &
    local child=$!

    loops=$(bc <<< "($timeout * (1 / $interval)) + 0.5" | sed 's/\..*//g')
    ((t = loops))
    while ((t > 0)); do
        sleep $interval
        kill -0 $child &>/dev/null || return
        ((t -= 1))
    done

    kill $child &>/dev/null || kill -0 $child &>/dev/null || return
    sleep $interval
    kill -9 $child &>/dev/null
    echo Timed out
}

slow_command()
{
    sleep 2
    echo Completed normally
}

# wait 1 sec in 0.1 sec increments
wait_on_command 1 0.1 slow_command

# or call an external command
wait_on_command 1 0.1 sleep 10

-1

非常に単純な方法:

# command & sleep 5; pkill -9 -x -f "command"

pkillコマンド(オプション-f)あなたは、引数を使用して、特定のコマンドを殺すか、古いプロセスを殺す避けるために、-nを指定することができます。


これは本質的にOPが彼の投稿に持っているものであり、OPが彼が望んでいないことを示していると思いますよね?常に完全なスリープ遅延を待機するためです。
Etan Reisner、2015

-1

@loupの答えに基づいて構築しています ...

プロセスをタイムアウトしてkill job / pid出力を無音にする場合は、次のコマンドを実行します。

( (sleep 1 && killall program 2>/dev/null) &) && program --version 

これにより、バックグラウンドプロセスがサブシェルに配置され、ジョブの出力が表示されなくなります。


-3

私はphpスクリプトを呼び出すcronジョブを持っていて、時々、それはphpスクリプトでスタックします。この解決策は私にとって完璧でした。

私が使う:

scripttimeout -t 60 /script.php

1
なにscripttimeout
rudolfbyker
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.