web-dev-qa-db-ja.com

特定のプロセスをCPU%に制限-Linux

次の問題があります。動的に生成された一部のプロセスがCPUを100%消費する傾向があります。特定の基準(プロセス名など)に一致するすべてのプロセスを特定のCPUパーセンテージに制限したいと思います。

私が解決しようとしている特定の問題は、folding @ homeワーカープロセスを利用することです。私が考えることができる最良の解決策は、定期的に実行され、cpulimitユーティリティを使用してプロセスを制限するPerlスクリプトです(詳細に興味がある場合は、これをチェックしてください ブログ投稿 )。動作しますが、ハックです:/

何か案は?プロセスの処理はOSに任せたい:)


提案に再度感謝しますが、私たちはまだポイントを逃しています:)

「slowDown」ソリューションは、本質的に「cpulimit」ユーティリティが実行するものです。スローダウンするプロセスについては引き続き注意が必要で、ワーカープロセスが終了したら「slowDown」プロセスを強制終了し、新しいワーカープロセス用に新しいプロセスを開始する必要があります。それはまさに、Perlスクリプトとcronジョブを使って行ったことです。

主な問題は、制限するプロセスが事前にわからないことです。それらは動的に生成されます。

たぶん、1人のユーザーのすべてのプロセスを特定のCPUパーセンテージに制限する方法はありますか? /etc/security/limits.confファイルでユーザーを制限できることを期待して、folding @ homeジョブを実行するためのユーザーをすでに設定しています。しかし、私が得ることができる最も近いのは、ユーザーごとの合計CPU時間です...

「このユーザーのプロセスのすべてのCPU%使用率の合計が50%を超えることはできません」と言うことができるとしたら、すばらしいでしょう。そして、その優先順位に関して、プロセスがCPUの50%を争うようにします...


皆さん、提案に感謝しますが、それは優先順位についてではありません-十分なCPU時間がある場合でも、CPU%を制限したいと思います。プロセスはすでに優先度が低いため、パフォーマンスの問題は発生しません。

CPUが長期間100%で実行されるのを防ぎたい...

31
asparagus

gzipで少し似た問題がありました。

gzipプロセスのCPUを減らしたいと仮定します。

    gzip backup.tar & sleep 2 & cpulimit --limit 10 -e gzip -z

オプション:

  • sleepが新しいcpulimitプロセスをすぐに受け取らないことがあるので、gzipは便利だと思いました
  • --limit 10gzip CPU使用率を10%に制限します
  • -zは、cpulimitプロセスが終了すると自動的にgzipを閉じます

もう1つのオプションは、cpulimitデーモンを実行することです。

21
Datageek

私は覚えておらず、UNIXスケジューラにこのようなものがあったとは思いません。他のプロセスを制御し、次のことを行う小さなプログラムが必要です。

loop
    wait for some time tR
    send SIGSTOP to the process you want to be scheduled
    wait for some time tP
    send SIGCONT to the process.
loopEnd

比率tR/tPはCPU負荷を制御します。


ここに概念の小さな証明があります。 「ビジー」はCPU時間を使い果たし、「slowDown」によってスローダウンさせたいプログラムです。

> cat > busy.c:
    main() { while (1) {}; }

> cc -o busy busy.c
> busy &
> top

Tasks: 192 total,   3 running, 189 sleeping,   0 stopped,   0 zombie
Cpu(s): 76.9% us,  6.6% sy,  0.0% ni, 11.9% id,  4.5% wa,  0.0% hi,  0.0% si
Mem:   6139696k total,  6114488k used,    25208k free,   115760k buffers
Swap:  9765368k total,  1606096k used,  8159272k free,  2620712k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
26539 cg        25   0  2416  292  220 R 90.0  0.0   3:25.79 busy
...

> cat > slowDown
while true; do
 kill -s SIGSTOP $1
 sleep 0.1
 kill -s SIGCONT $1
 sleep 0.1
done

> chmod +x slowDown
> slowDown 26539 &
> top
Tasks: 200 total,   4 running, 192 sleeping,   4 stopped,   0 zombie
Cpu(s): 48.5% us, 19.4% sy,  0.0% ni, 20.2% id,  9.8% wa,  0.2% hi,  2.0% si
Mem:   6139696k total,  6115376k used,    24320k free,    96676k buffers
Swap:  9765368k total,  1606096k used,  8159272k free,  2639796k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
26539 cg        16   0  2416  292  220 T 49.7  0.0   6:00.98 busy
...

わかりました。そのスクリプトにはさらに作業が必要です(たとえば、INTRがアップしていることに気をつけ、その時点で停止した場合に制御されたプロセスを続行できるようにするため)、要点はわかります。また、Cなどのスクリプトを記述して、コマンドラインの引数からCPU比率を計算します。

よろしく

13
blabla999

LinuxではCPU使用量を制限する解決策はないと思いますが、プロセスを特定のCPU使用量に制限するための許容できる方法があります。 http://ubuntuforums.org/showthread.php?t=992706

彼らが情報を削除した場合、ここに再びあります


  1. パッケージのインストール

  2. Cpulimitパッケージをインストールします。コード:

    Sudo apt-get install cpulimit

  3. Gawkパッケージをインストールします。コード:

    Sudo apt-get install gawk

  4. CPULIMITデーモンファイルの作成

Root権限でテキストエディターを開き、以下のデーモンスクリプトテキストを新しいファイル/usr/bin/cpulimit_daemon.shに保存します

コード:

#!/bin/bash
# ==============================================================
# CPU limit daemon - set PID's max. percentage CPU consumptions
# ==============================================================

# Variables
CPU_LIMIT=20        # Maximum percentage CPU consumption by each PID
DAEMON_INTERVAL=3   # Daemon check interval in seconds
BLACK_PROCESSES_LIST=   # Limit only processes defined in this variable. If variable is empty (default) all violating processes are limited.
WHITE_PROCESSES_LIST=   # Limit all processes except processes defined in this variable. If variable is empty (default) all violating processes are limited.

# Check if one of the variables BLACK_PROCESSES_LIST or WHITE_PROCESSES_LIST is defined.
if [[ -n "$BLACK_PROCESSES_LIST" &&  -n "$WHITE_PROCESSES_LIST" ]] ; then    # If both variables are defined then error is produced.
   echo "At least one or both of the variables BLACK_PROCESSES_LIST or WHITE_PROCESSES_LIST must be empty."
   exit 1
Elif [[ -n "$BLACK_PROCESSES_LIST" ]] ; then                                 # If this variable is non-empty then set NEW_PIDS_COMMAND variable to bellow command
   NEW_PIDS_COMMAND="top -b -n1 -c | grep -E '$BLACK_PROCESSES_LIST' | gawk '\$9>CPU_LIMIT {print \$1}' CPU_LIMIT=$CPU_LIMIT"
Elif [[ -n "$WHITE_PROCESSES_LIST" ]] ; then                                 # If this variable is non-empty then set NEW_PIDS_COMMAND variable to bellow command
   NEW_PIDS_COMMAND="top -b -n1 -c | gawk 'NR>6' | grep -E -v '$WHITE_PROCESSES_LIST' | gawk '\$9>CPU_LIMIT {print \$1}' CPU_LIMIT=$CPU_LIMIT"
else
   NEW_PIDS_COMMAND="top -b -n1 -c | gawk 'NR>6 && \$9>CPU_LIMIT {print \$1}' CPU_LIMIT=$CPU_LIMIT"
fi

# Search and limit violating PIDs
while sleep $DAEMON_INTERVAL
do
   NEW_PIDS=$(eval "$NEW_PIDS_COMMAND")                                                                    # Violating PIDs
   LIMITED_PIDS=$(ps -eo args | gawk '$1=="cpulimit" {print $3}')                                          # Already limited PIDs
   QUEUE_PIDS=$(comm -23 <(echo "$NEW_PIDS" | sort -u) <(echo "$LIMITED_PIDS" | sort -u) | grep -v '^$')   # PIDs in queue

   for i in $QUEUE_PIDS
   do
       cpulimit -p $i -l $CPU_LIMIT -z &   # Limit new violating processes
   done
done
  1. 環境のニーズに合わせて変数を変更

CPU_LIMITすべてのプロセスのCPU消費を20%以外の他のパーセンテージに省略したい場合は、上記のスクリプトでこの変数を変更します。 SMPコンピューター(1つ以上のCPUまたは1つ以上のコアを持つCPU)をお持ちの場合は、以下の「SMPコンピューターを使用する場合」の章をお読みください。

DAEMON_INTERVAL定期的なチェックを増やしたり減らしたりしたい場合は、上記のスクリプトでこの変数を変更します。間隔は秒単位で、デフォルトは3秒に設定されています。

BLACK_PROCESS_LISTおよびWHITE_PROCESSES_LIST変数BLACK_PROCESSES_LISTは、指定されたプロセスのみを制限します。変数が空の場合(デフォルト)、違反しているすべてのプロセスが制限されます。

変数WHITE_PROCESSES_LISTは、この変数で定義されたプロセスを除くすべてのプロセスを制限します。変数が空の場合(デフォルト)、違反しているすべてのプロセスが制限されます。

変数BLACK_PROCESSES_LISTおよびWHITE_PROCESSES_LISTの一方または両方を空にする必要があります。両方の変数が定義されていることは論理的ではありません。

区切り文字「|」を使用して、この2つの変数のいずれかに複数のプロセスを指定できます。 (二重引用符なし)。サンプル:mysql、firefoxおよびgeditプロセスを除くすべてのプロセスをcpulimitしたい場合は、変数を設定します:WHITE_PROCESSES_LIST = "mysql | firefox | gedit"

  1. デーモンを自動的に開始する手順AT起動時間

  2. Rootユーザーのファイル権限を設定します:コード:

    Sudo chmod 755 /usr/bin/cpulimit_daemon.sh

  3. Root権限でテキストエディターを開き、次のスクリプトを新しいファイル/etc/init.d/cpulimitに保存します。

コード:

#!/bin/sh
#
# Script to start CPU limit daemon
#
set -e

case "$1" in
start)
if [ $(ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh"  {print $1}' | wc -l) -eq 0 ]; then
    Nohup /usr/bin/cpulimit_daemon.sh >/dev/null 2>&1 &
    ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh"  {print}' | wc -l | gawk '{ if ($1 == 1) print " * cpulimit daemon started successfully"; else print " * cpulimit daemon can not be started" }'
else
    echo " * cpulimit daemon can't be started, because it is already running"
fi
;;
stop)
CPULIMIT_DAEMON=$(ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh"  {print $1}' | wc -l)
CPULIMIT_INSTANCE=$(ps -eo pid,args | gawk '$2=="cpulimit" {print $1}' | wc -l)
CPULIMIT_ALL=$((CPULIMIT_DAEMON + CPULIMIT_INSTANCE))
if [ $CPULIMIT_ALL -gt 0 ]; then
    if [ $CPULIMIT_DAEMON -gt 0 ]; then
        ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh"  {print $1}' | xargs kill -9   # kill cpulimit daemon
    fi

    if [ $CPULIMIT_INSTANCE -gt 0 ]; then
        ps -eo pid,args | gawk '$2=="cpulimit" {print $1}' | xargs kill -9                    # release cpulimited process to normal priority
    fi
    ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh"  {print}' | wc -l | gawk '{ if ($1 == 1) print " * cpulimit daemon can not be stopped"; else print " * cpulimit daemon stopped successfully" }'
else
    echo " * cpulimit daemon can't be stopped, because it is not running"
fi
;;
restart)
$0 stop
sleep 3
$0 start
;;
status)
ps -eo pid,args | gawk '$3=="/usr/bin/cpulimit_daemon.sh"  {print}' | wc -l | gawk '{ if ($1 == 1) print " * cpulimit daemon is running"; else print " * cpulimit daemon is not running" }'
;;
esac
exit 0
  1. ファイルの所有者をrootに変更します。

コード:

Sudo chown root:root /etc/init.d/cpulimit
  1. 権限を変更:

コード:

Sudo chmod 755 /etc/init.d/cpulimit
  1. 起動手順ディレクトリにスクリプトを追加します:コード:

    Sudo update-rc.d cpulimit defaults

  2. 再起動して、起動時にスクリプトがcpulimitデーモンを開始するかどうかを確認します。コード:

    須藤再起動

  3. デーモンを手動で確認、停止、開始、再起動する

注:このチュートリアルのデーモンとサービスの意味は同じです。

注:サービスコマンドの代わりにUbuntu 8.10より前(Ubuntu 8.04 LTSなど)を使用しているユーザーは、「Sudo /etc/init.d/cpulimit status/start/stop/restart」構文を使用するか、コマンドを使用してsysvconfigパッケージをインストールします:Sudo apt-get sysvconfigをインストールする

Cpulimitサービスが実行されているかどうかを確認するCheckコマンドは、サービスが実行されている場合は「cpulimitデーモンが実行されています」、サービスが実行されていない場合は「cpulimitデーモンが実行されていません」を返します。コード:

Sudo service cpulimit status

Cpulimitサービスの開始cpulimitデーモンを手動で開始して、CPU消費を省略し始めることができます。コード:

Sudo service cpulimit start

Stop cpulimit service Stopコマンドは、cpulimitデーモンを停止し(新しいプロセスは制限されません)、cpulimitが実行されていなかったときと同じように、既存のすべての制限されたプロセスにCPUへのフルアクセスを設定します。コード:

Sudo service cpulimit stop

Cpulimitサービスを再起動します。CPU_LIMIT、DAEMON_INTERVAL、BLACK_PROCESSES_LIST、WHITE_PROCESSES_LISTなど、/ usr/bin/cpulimit_daemon.shの一部の変数設定を変更した場合、設定を変更した後、サービスを再起動する必要があります。コード:

Sudo service cpulimit restart
  1. OR CPULIMITデーモンなしでCPU消費をチェックする

デーモンを使用しない場合1. cpulimitデーモンを停止します(Sudoサービスcpulimit stop)2.バックグラウンドでCPUを集中的に使用するタスクを実行します3.コマンドを実行します:topと%CPU列を確認します%CPUの結果はおそらく各プロセスで20%以上です。

デーモンをオンにして1. cpulimitデーモンを開始します(Sudoサービスcpulimit start)2.同じCPU集中タスクをバックグラウンドで実行します3.コマンドを実行します:topと%CPU列を確認します%CPUの結果はプロセスごとに最大20%になるはずです。注:デーモンは3秒間隔で違反プロセスをキャッチする必要があるため、最初は%CPUが20%を超える可能性があることを忘れないでください(デフォルトではスクリプトで設定されています)

  1. SMPコンピューターを使用している場合

私はこのコードをIntelデュアルコアCPUコンピュータでテストしました-これはSMPコンピュータのように動作します。トップコマンドとcpulimitはデフォルトでIrixモードで動作することを忘れないでください。20%は1つのCPUの20%を意味します。 2つのCPU(またはデュアルコア)がある場合、%CPUの合計は200%になります。 topコマンドでは、IrixモードをコマンドI(topコマンドの実行中に+ iを押す)でオフにでき、Solarisモードがオンになり、CPUの合計量がCPUの数で除算されるため、%CPUは100以下にすることができます任意の数のCPUコンピューターでの%。トップマンページのトップコマンドに関する詳細情報を読んでください(Iコマンドを検索してください)。また、cpulimitの公式ページで、SMPコンピューターでのcpulimitの動作に関する詳細もご覧ください。

しかし、cpulimitデーモンはSMPコンピューターでどのように動作しますか?常にIrixモード。したがって、CPUパワーの20%を2 CPUコンピュータに費やしたい場合は、cpulimitデーモンスクリプトのCPU_LIMIT変数に40%を使用する必要があります。

  1. CPULIMITデーモンとCPULIMITプログラムのアンインストール

Cpulimitデーモンを削除したい場合は、cpulimitデーモンを削除してcpulimitプログラムをアンインストールすることにより、システムをクリーンアップできます。

  1. Cpulimitデーモンコードを停止します。

    Sudo service cpulimit stop#cpulimitデーモンとすべてのcpulimitedプロセスを停止します

  2. 起動手順からデーモンを削除しますコード:

    Sudo update-rc.d -f cpulimit remove#シンボリックリンクを削除

  3. 起動手順コードを削除:

    Sudo rm /etc/init.d/cpulimit#cpulimit起動スクリプトを削除

  4. Cpulimitデーモンコードを削除します。

    Sudo rm /usr/bin/cpulimit_daemon.sh#cpulimitデーモンスクリプトを削除

  5. Cpulimitプログラムコードをアンインストールします。

    Sudo apt-get remove cpulimit

  6. Gawkプログラムのアンインストール他のスクリプトでこのプログラムが不要な場合は、リモートで実行できます。コード:

    Sudo apt-get remove gawk

  7. 著者についての注意

私はcpulimit(上記のbashスクリプト)のデーモンを書いたところです。私はcpulimitプロジェクトの作者ではありません。 cpulimitプログラムの詳細が必要な場合は、公式のcpulimit Webページ http://cpulimit.sourceforge.net/ をお読みください。

よろしく、Abcuser

7

Reniceを使用してプロセスの優先度を調整できるのに、なぜCPUの割合を制限するのですか? reniceを使用し、優先度を低く設定すると、プロセスは利用可能であればプロセッサーの100%を使用できますが、優先度の高い他のプロセスは必要なときにプロセスを取得し、ほとんど遅延はありません。

6
Kibbee

私にも同様の問題があり、スレッドで提示されている他の解決策ではまったく対処できません。私の解決策は今のところ私には有効ですが、特にプロセスがrootによって所有されている場合は、最適ではありません。
今のところ私の回避策は、rootが所有する実行時間の長いプロセスがないことを確認するために一生懸命試みることです(バックアップがユーザーとしてのみ行われるなど)。

私はちょうどgnomeのハードウェアセンサーアプレットをインストールし、CPUに高温と低温のアラームをセットアップしてから、各アラームに次のコマンドをセットアップしました。

低:

mv /tmp/hogs.txt /tmp/hogs.txt.$$ && cat /tmp/hogs.txt.$$ | xargs -n1 kill -CONT

高い:

touch /tmp/hogs.txt && ps -eo pcpu,pid | sort -n -r | head -1 | gawk '{ print $2 }' >> /tmp/hogs.txt && xargs -n1 kill -STOP < /tmp/hogs.txt

良いニュースは、私のコンピュータが過熱してクラッシュすることがなくなったことです。欠点は、ターミナルプロセスが停止するとターミナルから切断され、CONTシグナルを受信して​​も再接続されないことです。もう1つは、(特定のWebブラウザープラグインのように)過熱を引き起こした対話型プログラムの場合、CPUが冷めるのを待つ間、私がやっていることの途中でフリーズするということです。 CPUスケーリングでこれをグローバルレベルで処理するほうがいいですが、問題は、CPUに選択可能な設定が2つしかなく、遅い設定では過熱を防ぐのに十分なほど遅くないことです。

ここで繰り返しますが、これはプロセスの優先順位や再ナイスとはまったく関係がなく、長時間実行されるジョブの停止とは関係ありません。これは、CPU使用率が100%になりすぎないようにするためです。これは、ハードウェアが全容量で実行しているときに十分な速さで熱を放散できないためです(アイドル状態のCPUは、完全にロードされたCPUよりも発熱量が少ないため)。

役立つ可能性のある他の明らかな可能性は次のとおりです。

BIOSで全体的にCPU速度を下げる

ヒートシンクを交換するか、サーマルジェルを再塗布して、効果があるかどうかを確認します

圧縮空気でヒートシンクを掃除します

CPUファンを交換してください

[編集]注:BIOSで可変ファン速度を無効にしても、CPUが100%になっても過熱しません(asus p5q pro turbo)。 CPUが完全にロードされた状態で、各コアは49摂氏に達しています。

4
yapa

Cgroups 'cpu.sharesを使用しても、Nice値では実行できないことはありませんします。実際にプロセスを抑制したいようですが、それは間違いなく実行できます。

必要なパラメーターを定義するには、1つまたは2つのスクリプトを使用するか、編集/ etc/cgconfig.confする必要があります。

具体的には、値cpu.cfs_period_usおよびcpu.cfs_quota_us。その後、プロセスはcpu.cfs_quota_usマイクロ秒cpu.cfs_period_usマイクロ秒。

例えば:

cpu.cfs_period_us = 50000およびcpu.cfs_quota_us = 10000の場合、他に何が起こっていても、プロセスは最大CPU時間の20%を受け取ります。

このスクリーンショットでは、CPU時間の2%のプロセスを示しています。

2% CPU time

プロセスに関する限り、プロセスは100%で実行されています。

一方、設定cpu.sharesは、アイドルCPU時間の100%を使用できます。

この同様の例では、プロセスcpu.shares = 100(1024のうち)を指定しています。

cpu.shares

ご覧のように、プロセスはまだすべてのアイドルCPU時間を消費しています。

参照:

http://manpages.ubuntu.com/manpages/precise/man5/cgconfig.conf.5.htmlhttp://kennystechtalk.blogspot.co.uk/2015/04/ throttling-cpu-usage-with-linux-cgroups.html

3
Ken Sharp

また、特定のプロセスのCPU時間を制限する必要もありました。 Cpulimitは優れたツールですが、常に手動でPIDを見つけて手動でcpulimitを開始する必要があったので、もっと便利なものを求めていました。

私はこのbashスクリプトを思いつきました:

#!/bin/bash

function lp
{

ps aux | grep $1 | termsql "select COL1 from tbl" > /tmp/tmpfile

while read line
do
    TEST=`ps aux | grep "cpulimit -p $line" | wc -l`
    [[ $TEST -eq "2" ]] && continue #cpulimit is already running on this process
    cpulimit -p $line -l $2
done < /tmp/tmpfile

}

while true
do
    lp gnome-terminal 5
    lp system-journal 5
    sleep 10
done

この例では、各gnome-terminalインスタンスのCPU時間を5%に制限し、各システムジャーナルインスタンスのCPU時間も5%に制限しています。

この例では、termsqlという名前の別のスクリプトを使用してPIDを抽出しました。ここで取得できます: https://gitorious.org/termsql/termsql/source/master

2
user3573558

Cgroupを使用してCPU時間を制限できます。 OSは、質問で要求されるのと同じようにリソース管理を処理します。

ここに例のウィキがあります: https://wiki.archlinux.org/index.php/Cgroups

プロセスはすでに別のユーザーとして実行されているため、そのユーザーからのすべてのプロセスを制限するのが最も簡単なソリューションです。

1
Mathias

少なくとも2つのオプションが表示されます。

  • プロセスを作成するシェルで「ulimit -t」を使用します
  • プロセスの作成時に「Nice」を使用するか、実行時に「renice」を使用します
1
MatthieuP

PS + GREP +ニース

1
TravisO

これは、setrlimit(2)を使用して行うことができます(特にRLIMIT_CPUパラメータを設定することにより)。

0
psaccounts

いくつかのスリープコールをそこにスローすると、プロセスがCPUから一定時間強制的にオフになります。 1分に1回30秒スリープする場合、プロセスはその1分間の平均CPU使用率が50%を超えてはなりません。

0
Adam Jaskiewicz

Nice コマンドが役立つでしょう。

0
Jim Blizard