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

답변2

이 문제는 대시에서 발생하지 않는다는 것을 발견했기 때문에 이것이 버그로 인해 발생할 가능성이 가장 높다는 것은 분명합니다.

bash-3.x를 사용하면 성장하지만 매우 느리게 진행됩니다. 여전히 다른 쉘보다 빠릅니다.

귀하의 bash 버전과 관련된 버그 보고서를 작성하는 것이 좋습니다.

참고: 몇 가지 테스트를 했는데, 아무리 기다려도 전혀 자라지 않는 쉘은 두 개뿐입니다. 그리고 mksh원래 쉘은 sbrk() 대신 malloc()을 사용하도록 변환되지 않았습니다.Bourne Shell

다른 모든 껍질은 매우 천천히 자랍니다.

관련 정보