bash 4.3がスクリプトにメモリを割り当て続けるのはなぜですか?

bash 4.3がスクリプトにメモリを割り当て続けるのはなぜですか?

このシェルスクリプトがbashで徐々に多くのメモリを消費するのはなぜですか?ローカル変数を使用しません。の値は直ちに終了するcpidので、繰り返すたびに変更されますが、大きすぎるべきではlsありません。

関連するシェルスクリプトは単に子プロセスを監視し、そのプロセスが開始されたことを確認します。スクリプトが呼び出されます。run-always

set -euf

# monitor a child process
# see if it's up

cpid=
while : ; do
    # if cpid isn't set, spawn child
    if [ -z "$cpid" ]; then
       "$@" &
       cpid="$!"
    fi

    # if child isn't active unset cpid
    if ps -o pid= -p "$cpid"; then
        :
    else
        cpid=
    fi

    sleep 1
done

すぐに終了するプロセス(例ls:)にこれを使用すると、スクリプトを実行すると次のメモリ使用量が発生します。dash run-always ls

4476kbで、絶対に大きくなりません。

これは、Linuxで毎秒メモリ使用量を取得するために使用するコマンドです。から直接メモリと最大メモリ使用量を取得する方法があるかもしれませんが、psこれで作業が完了します。

 while : ; do cat /proc/"$(ps a | grep run-always | grep -v grep | awk '{print $1}')"/status | grep -i 'vmsize\|vmpeak' ; sleep 1; done

を使用して上記のスクリプトを実行すると、dashメモリ使用量はまったく増加せず、私のコンピュータ上で着実に4476kbを維持します。

ただし、bash()を使用すると、bash run-always ls10秒ごとに数キロバイトのメモリがさらに割り当てられ、決して解放されません。

バッシュはなぜこのようなことをするのか?

出力例:

VmPeak:    16676 kB
VmSize:    16676 kB
VmPeak:    16676 kB
VmSize:    16676 kB
VmPeak:    16676 kB
VmSize:    16676 kB
VmPeak:    16676 kB
VmSize:    16676 kB
VmPeak:    16676 kB
VmSize:    16676 kB
VmPeak:    16676 kB
VmSize:    16676 kB
VmPeak:    16676 kB
VmSize:    16676 kB
VmPeak:    16676 kB
VmSize:    16676 kB
VmPeak:    16676 kB
VmSize:    16676 kB
VmPeak:    16676 kB
VmSize:    16676 kB
VmPeak:    16676 kB
VmSize:    16676 kB
VmPeak:    16680 kB
VmSize:    16680 kB
VmPeak:    16680 kB
VmSize:    16680 kB
VmPeak:    16680 kB
VmSize:    16680 kB
VmPeak:    16680 kB
VmSize:    16680 kB
VmPeak:    16680 kB
VmSize:    16680 kB
VmPeak:    16680 kB
VmSize:    16680 kB
VmPeak:    16680 kB
VmSize:    16680 kB
VmPeak:    16680 kB
VmSize:    16680 kB
VmPeak:    16680 kB
VmSize:    16680 kB
VmPeak:    16684 kB
VmSize:    16684 kB
VmPeak:    16684 kB
VmSize:    16684 kB
VmPeak:    16684 kB
VmSize:    16684 kB
VmPeak:    16684 kB
VmSize:    16684 kB
VmPeak:    16684 kB
VmSize:    16684 kB
VmPeak:    16684 kB
VmSize:    16684 kB
VmPeak:    16684 kB
VmSize:    16684 kB
VmPeak:    16684 kB
VmSize:    16684 kB
VmPeak:    16684 kB
VmSize:    16684 kB
VmPeak:    16684 kB
VmSize:    16684 kB
VmPeak:    16684 kB
VmSize:    16684 kB
VmPeak:    16684 kB
VmSize:    16684 kB
VmPeak:    16684 kB
VmSize:    16684 kB
VmPeak:    16684 kB
VmSize:    16684 kB
VmPeak:    16688 kB
VmSize:    16688 kB
VmPeak:    16688 kB
VmSize:    16688 kB
VmPeak:    16688 kB
VmSize:    16688 kB
VmPeak:    16688 kB
VmSize:    16688 kB
VmPeak:    16688 kB
VmSize:    16688 kB
VmPeak:    16688 kB
VmSize:    16688 kB
VmPeak:    16688 kB
VmSize:    16688 kB
VmPeak:    16688 kB
VmSize:    16688 kB
VmPeak:    16688 kB
VmSize:    16688 kB
VmPeak:    16688 kB
VmSize:    16688 kB
VmPeak:    16692 kB
VmSize:    16692 kB

ベストアンサー1

Bash は、アクティブな作業テーブルに各バックグラウンド プロセスを保持します。以前のジョブを明示的に確認せずに新しいジョブを作成するため、テーブルが無制限に大きくなる可能性があります。次のバックグラウンドプロセスを開始する前にプロセスをバックグラウンドに進めるか、disown終了ステータスを確認すると問題が消えます。jobs

たとえば、このスクリプトバージョンはメモリ使用量を増やしません。

set -euf

# monitor a child process
# see if it's up

cpid=
while : ; do
    # if cpid isn't set, spawn child
    if [ -z "$cpid" ]; then
       "$@" &
       disown $!       # Don't waste memory on this red-headed child
       cpid="$!"
    fi

    # if child isn't active unset cpid
    if ps -o pid= -p "$cpid"; then
        :
    else
        cpid=
    fi

    sleep 1
done

おすすめ記事