web-dev-qa-db-ja.com

プロセスとその子の総リソース(メモリ)を制限する方法

単一のプロセスのリソースを制約することについては、多くの質問と回答があります。 RLIMIT_ASは、topのようにVIRTと見なされるプロセスによって割り当てられる最大メモリを制限するために使用できます。トピックの詳細(例:ここ 特定のプロセスがUnixで使用できるメモリの量を制限する方法はありますか?

setrlimit(2)ドキュメンテーションは言う:

Fork(2)によって作成された子プロセスは、その親のリソース制限を継承します。リソース制限はexecve(2)全体で保持されます。

次のように理解する必要があります。

プロセスのRLIMIT_ASが2GBの場合、2GBを超えるメモリを割り当てることはできません。子を生成すると、2GBのアドレススペース制限が子に渡されますが、カウントは0から始まります。2つのプロセスを合わせて最大4GBのメモリを使用できます。

しかし、プロセスのツリー全体によって割り当てられたメモリの合計を制約するのに役立つ方法は何でしょうか?

17
jpe

これがあなたの質問に答えるかどうかはわかりませんが、私はこれを見つけました Perlスクリプト まさにあなたが探していることを行うと主張しています。スクリプトは、プロセスとその子のリソース使用を起動して確認することにより、制限を適用するための独自のシステムを実装します。それはよく文書化され説明されているようで、最近更新されました。

Slmが彼のコメントで述べたように、cgroupもこれに使用できます。 Linuxを使用している場合は、libcgroupsを探す必要があります。cgroupを管理するためのユーティリティをインストールする必要がある場合があります。

Sudo cgcreate -t $USER:$USER -a $USER:$USER -g memory:myGroup

$USERがユーザーであることを確認してください。

これで、ユーザーは/sys/fs/cgroup/memory/myGroupのc​​groupメモリ設定にアクセスできるようになります。

次に、次のようにして、制限を500 MBに設定できます。

echo 500000000 > /sys/fs/cgroup/memory/myGroup/memory.limit_in_bytes

Vimを実行しましょう:

cgexec -g memory:myGroup vim

Vimプロセスとそのすべての子は、500 MBのRAMの使用に制限されるはずです。 ただし、この制限はRAMにのみ適用され、スワップには適用されません。プロセスが制限に達すると、プロセスは開始しますスワッピング:これを回避できるかどうかはわかりませんが、cgroupsを使用してスワップの使用を制限する方法が見つかりません。

10
arnefm

Ubuntuで使用されているcgmanagerを使用して、これを行うスクリプトを作成しました。 1つの利点は、これがrootアクセスを必要としないことです。 cgroup管理は少しディストリビューション固有なので、systemd cgroup管理を使用するディストリビューションでこれが機能するかどうかはわかりません。

#!/bin/sh

set -eu

if [ "$#" -lt 2 ]
then
    echo Usage: `basename $0` "<limit> <command>..."
    exit 1
fi

limit="$1"
shift
cgname="limitmem_$$"
echo "limiting memory to $limit (cgroup $cgname) for command $@"

cgm create memory "$cgname" >/dev/null
cgm setvalue memory "$cgname" memory.limit_in_bytes "$limit" >/dev/null
# try also limiting swap usage, but this fails if the system has no swap
cgm setvalue memory "$cgname" memsw.limit_in_bytes "$limit" >/dev/null 2>&1 || true

# spawn subshell to run in the cgroup
set +e
(
set -e
cgm movepid memory "$cgname" `sh -c 'echo $PPID'` > /dev/null
exec "$@"
)
# grab exit code
exitcode=`echo $?`

set -e

echo -n "peak memory used: "
cgm getvalue memory "$cgname" memory.max_usage_in_bytes | tail -1 | cut -f2 -d\"

cgm remove memory "$cgname" >/dev/null
exit $exitcode

使用法:パスにlimitmemとして保存し、実行可能にします。次に、実行します。 limitmem 1G command...。これにより、実際に使用されるメモリが制限されます。これに達した場合、OOMキラーはプロセスまたはその子の1つを強制終了しますが、このコマンドとは関係のないランダムなものは強制終了しません。

2
JanKanis

https://unix.stackexchange.com/a/536046/4319

Systemdベースのディストリビューションでは、systemd-runを介してcgroupを間接的に使用することもできます。例えば。 pdftoppmを500MのRAMに制限する場合は、次を使用します。

systemd-run --scope -p MemoryLimit=500M pdftoppm

...