5

CPU のアイドル状態が 50% を超える場合にのみ、cron ジョブ (bash スクリプト) を実行するにはどうすればよいですか?

TOPからCPUアイドルを取得できます

top -b -d 00.10 -n 3 |grep ^Cpu
Cpu(s): 0.3%us, 0.3%sy, 0.0%ni, 99.3%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st

私の現在の設定は次のとおりです。

crontab
0,15,30,45 * * * * /usr/bin/php /home/user/batchprocess.php
# I could use a bash script here to call PHP, if it is a good solution.

そして、PHP スクリプトで CPU のアイドル状態をチェックします。

batchprocess.php
proc_nice(10);
// wait for CPU idle
do{
    $cpu_stat = exec('top -b -d 00.10 -n 3 |grep ^Cpu');    
    $tmp = stristr($cpu_stat,'%id',TRUE);
    $cpuidle = trim(substr($tmp,strrpos($tmp,',')+1));
}while($cpuidle<$min_cpuidle);
// do actual processing here

私の現在の方法の問題は、CPU 使用率に関係なくプログラムを開始することです。また、TOP を実行する while ループは効率が悪いと感じます。CPUアイドルが50を超える場合にのみ開始したい

いくつかの追加情報:

  • CentOS 6.2、PHP5.3

  • シャットダウンしない EC2 インスタンスがいくつかあるので、アイドル時にそれらの処理能力を利用したいと考えています。ただし、サーバーに過度の負荷をかけないでください。(冗長化DBインスタンス、開発インスタンス、NATインスタンス)

  • EC2 オートスケーリング、スポットインスタンスを知っています。余分な容量を使いたいだけです。

  • バックグラウンド ジョブは画像圧縮です (CPU を集中的に使用し、I/O やネットワークはそれほど多くありません)。

どんな提案でも大歓迎です。前もって感謝します!


以下の入力に基づいて、私の場合は「いい」がより良い解決策であることに気付きました。CPU 使用率を追跡するのではなく、サーバーへの影響を最小限に抑えるために、目的を再調整する必要があります。

したがって、新しいセットアップは次のとおりです。

crontab
0,15,30,45 * * * * nice -20 /usr/bin/php /home/user/batchprocess.php

そしてPHPスクリプト:

batchprocess.php
if ($cpuidle < 50) 
    exit(0);
// do actual processing here

私はそれをテストし、私の発見を投稿します。


報告: 私はこのコードを DEV/PRD に通しましたが、非常にうまく動作します。TOCTOUの問題は解決しませんが、今のところは十分です。

4

2 に答える 2

7

これはTOCTOUの典型的なケースです。システムがアイドル状態かどうかを確認し、プロセスを開始します。しかし、チェック後、プロセスの開始時または開始前に、何か他の原因でシステム内の別のプロセスが開始され、システムにまだ負荷がかかります。必要以上に。

niceこれを行う「正しい」方法は、コマンドを使用してプロセスの優先度を低くすることです。ちなみに、CPU 使用率をチェックするループは 100% の CPU を使用するため、最初にアイドル状態であることを確認しない限り、おそらく機能しません。

すでに「proc_nice(10)」があるので、これで問題ありません。システムがビジー状態かどうかを特定するために労力を費やしても意味がありません。

コードの適切なポイントで、次のようなことを行うことができます。

 if (check_cpu_usage() > 50%) sleep(1second); 

しかし、それが十分に役立つかどうかはわかりません。システムがビジー状態の場合、「適切な」プロセスは CPU 時間をあまり使用しないため、より高い優先度で実行される他のプロセスと競合しません。

于 2013-01-14T20:23:01.967 に答える
1

システム負荷が 2.0 以下の場合にスクリプトを実行したい場合は、次のようなシェル スクリプトを使用できます。

#!/bin/sh
LOAD=`cat /proc/loadavg | cut -d" " -f1`
THRESHOLD=2.0
if [ $(bc <<< "$LOAD <= $THRESHOLD") -eq 1 ]; then
    $@
fi

たとえば として保存し、crontab ファイルのコマンドの前に/usr/local/bin/if-idle貼り付けます。if-idle

于 2013-04-01T13:33:14.527 に答える