다음과 같은 명령에서:
find /data ! -type d -exec rm -f {} +
+
일괄 실행 에 사용됩니다 rm -f
. find
가능한 한 많은 매개변수를 일괄 처리해야 합니다. 하지만 한계를 어떻게 알 수 있나요?
답변1
로 지정된 명령을 호출할 때 find
일괄 인수 기능에 대한 제한은 일반적으로 커널에 의해 결정됩니다. 이는 함수 계열에 제공되는 인수의 최대 크기입니다. POSIX는 매개변수의 최대 크기와 관련된 값을 검색하는 두 가지 방법을 정의합니다.-exec
+
exec
그리고 환경주다전화exec
.
첫 번째는 상수이므로 빌드할 때 실행 파일을 "포함"하게 됩니다.ARG_MAX
끊임없는존재하다 limits.h
:
매개변수의 최대 길이구현하다기능에는 환경 데이터가 포함됩니다.
두 번째는 런타임에 사용할 수 있습니다.sysconf
기능, 특히 _SC_ARG_MAX
논쟁.
설정된 제한 ARG_MAX
(둘 다 {ARG_MAX} 변수에 대한 액세스를 제공하므로 위의 두 방법 모두에 적용 가능)은 다음과 같습니다.POSIX에 의해 지정됨, 에 대한 -exec
:
두 개 이상의 경로 이름 집합의 크기는 유틸리티 실행으로 인해 시스템의 {ARG_MAX} 제한이 초과되지 않도록 제한되어야 합니다.
같은 이유xargs
:
이것매개변수유틸리티는 명령줄이 호출될 때 결합된 인수와 환경 목록이 표시되도록 명령줄 길이를 제한해야 합니다(참조:구현하다시스템 인터페이스 볼륨의 POSIX.1-2017 함수 계열)은 {ARG_MAX}-2048바이트를 초과해서는 안 됩니다.
다양한 구현에서는 이러한 제한을 다양한 방식으로 적용하며 때로는 위의 상수로 표시된 것보다 작은 값을 적용하기도 합니다. 예를 들어, OpenBSD는 최대 명령줄 길이를 확인하지만 임의로 제한하기도 합니다 find
.sysconf
숫자매개변수 수가 5000개에 도달했습니다.소스 코드자세한 내용(감사합니다.모스비참고용). GNU는 find
를 확인 sysconf
하고 필요한 경우 지정된 제한으로 대체하고 지정된 2048바이트 여백을 추가합니다 ARG_MAX
( GNU 및 여기에서 구현을 공유합니다).find
xargs
find
xargs
특정 커널은 자체 변형을 추가할 수도 있습니다.명령의 단일 매개변수의 최대 크기를 정의하는 것은 무엇입니까?이것은 Linux에 대해 논의됩니다. 스택 요구 사항이 다르기 때문에 Solaris에는 생성된 프로세스( find
OR xargs
프로세스가 아니라 향후 하위 프로세스)가 32비트인지 64비트인지에 따라 고려해야 할 제한 사항이 다릅니다.libfind
자세한 내용(감사합니다.교활한포인터의 경우). 허드매개변수 제한이 전혀 없습니다..
답변2
나는 최근에 여기서 일반적인 규칙을 언급했습니다.
이 규칙의 유효한 구현은 내 자신의 것입니다 libfind
.https://sourceforge.net/p/schillix-on/schillix-on/ci/default/tree/usr/src/lib/libfind/find.c#l2020
여기서 주요 문제는 libfind
현재 환경 크기와 호출되는 프로그램이 32비트 프로그램인지 64비트 프로그램인지 여부를 알아야 한다는 것입니다. 왜냐하면 다양한 제한 사항이 있기 때문입니다.
libfind
32/64비트를 구분하는 이유는 과거에는 32비트 프로그램을 호출할 때 더 큰 프로젝트의 소스 코드 줄 수를 얻기 위해 64비트 쉘에서 호출할 find -name '*.c' -exec count -t {} +
때 종종 제한에 부딪혔기 때문입니다.libfind
count
Solaris find
구현에서는 Solaris가 64비트 조회를 제공하지 않기 때문에 이러한 구별을 할 필요가 없습니다. 따라서 32비트 제한을 사용하면 가능한 최대 매개변수 목록 크기를 사용하지 않더라도 어떤 경우에도 최소한 작동합니다.
참고: Linux의 단일 매개변수(128k)로 인해 find
불필요한 추가 제한이 적용될 가능성은 거의 없습니다. make
전체 셸 명령줄이 단일 인수로 전달되기 때문에 이는 실제 문제입니다. 반면, 긴 명령을 분할하는 코드가 포함되어 있지 않기 make
때문에 사전 확인은 없습니다 .make
추신: 저는 방금 Solaris에서 흥미로운 제한 사항을 발견했습니다. 둘 다 from 을 통해 프로그램을 호출하고, xargs
호출할 프로그램이 스크립트가 없는 스크립트인 경우 구현에서는 스크립트의 쉘을 호출하고 고정 인수 정렬 매개변수를 사용하여 다시 시작합니다. 크기 배열. 배열에는 255개의 항목만 있으므로 명령이 간단한 쉘 스크립트인 경우 및에 대한 매개변수는 255개로 제한됩니다. 프로그램이 그러한 스크립트이고 arglist에 255개 이상의 인수가 포함되어 있으면 .find
execvp()
libc
#!
execvp()
xargs
find
execvp()
E2BIG
여기서 문제는 를 통해 생성된 프로세스에서 호출될 수 있기 때문에 malloc()
내부에서 사용할 수 없다는 것입니다 . 호출 되면 부모의 할당된 메모리가 유효하지 않게 됩니다. 반대편의 호출은 항상 성공하지만 로컬 스택 크기가 초과되는 상황이 발생할 수 있습니다.execvp()
execvp()
vfork()
execvp()
malloc()
alloca()
SIGSEGV