"인수 목록이 너무 깁니다": 명령을 변경하지 않고 어떻게 처리합니까?


18

과 같은 명령을 실행 ls */*/*/*/*.jpg하면 오류가 발생합니다.

-bash: /bin/ls: Argument list too long

왜 이런 일이 발생하는지 알고 있습니다. 명령에 대한 인수를위한 공간의 양에 커널 제한이 있기 때문입니다. 표준 조언은 인수에 너무 많은 공간이 필요하지 않도록 내가 사용하는 명령을 변경하는 것입니다 (예 : use findxargs).

명령을 변경하지 않으려면 어떻게합니까? 동일한 명령을 계속 사용하려면 어떻게합니까? 이 오류가 발생하지 않고 어떻게 작동하는지 어떻게 알 수 있습니까? 어떤 솔루션을 사용할 수 있습니까?


유용한 자료 : 배쉬 FAQ 95 . 명령을 변경하지 않으면 인수 목록의 최대 크기를 늘리거나 파일 수가 적도록 디렉토리 구조를 변경하기 위해 다시 컴파일하는 것 외에는 할 일이 많지 않습니다.
jw013

1
Linux 커널 버전을 기반으로 @ jw013을 사용하면 인수 목록을 늘릴 수 있습니다 . 최근 시스템의 변경 사항에 대한 자세한 내용 은 unix.stackexchange.com/a/45161/8979 를 참조하십시오 .
Ulrich Dangel

@UlrichDangel, 예, 가능합니다! 내 답변을 참조하십시오; 내 대답은 그것을 수행하는 방법을 보여줍니다 (리눅스에서 충분한 커널로)
DW

답변:


26

Linux에서 명령 인수의 최대 공간은 사용 가능한 스택 공간의 1/4입니다. 따라서 솔루션은 스택에 사용 가능한 공간을 늘리는 것입니다.

짧은 버전 : 같은 것을 실행

ulimit -s 65536

더 긴 버전 : 스택에 사용 가능한 기본 공간은 8192KB와 같습니다. 다음과 같이 사용 가능한 공간이 표시됩니다.

$ ulimit -s
8192

더 큰 숫자를 선택하고 스택에 사용할 수있는 공간을 설정하십시오. 예를 들어, 스택에 최대 65536KB를 허용하려면 다음을 실행하십시오.

$ ulimit -s 65536

시행 착오를 사용하여 이것이 얼마나 큰지에 대해 놀아야 할 수도 있습니다. 많은 경우에 이것은 명령을 수정하고 다음 구문을 해결할 필요가없는 빠르고 더러운 솔루션입니다.find , xargs(나는 그렇게 다른 혜택이 있습니다 실현하지만), 등.

나는 이것이 리눅스에 특정한 것이라고 믿는다. 다른 유닉스 운영 체제 (테스트되지 않음)에서는 도움이되지 않을 것으로 생각됩니다.


1
다음과 같이 작동하는지 확인할 수 있습니다. $ getconf ARG_MAX 2097152 $ ulimit -s 65535 $ getconf ARG_MAX 16776960
Alex

2

Linux Journal 기사 는 4 가지 솔루션을 제공합니다. 네 번째 솔루션 만 명령 변경을 포함하지 않습니다.

방법 # 4는 명령 줄 인수를 위해 커널 내에 할당 된 페이지 수를 수동으로 늘리는 과정입니다. include / linux / binfmts.h 파일을 보면 맨 위에 다음이 있습니다.

/*
 * MAX_ARG_PAGES defines the number of pages allocated for   arguments
 * and envelope for the new program. 32 should suffice, this gives
 * a maximum env+arg of 128kB w/4KB pages!
 */
#define MAX_ARG_PAGES 32

명령 행 인수 전용의 메모리 양을 늘리려면 MAX_ARG_PAGES 값을 더 높은 숫자로 제공하면됩니다. 이 편집 내용이 저장되면 평소처럼 재 컴파일, 설치 및 새 커널로 재부팅하면됩니다.

내 테스트 시스템에서는이 값을 64로 올려서 모든 문제를 해결할 수있었습니다. 광범위한 테스트 후에 스위치 이후 단일 문제가 발생하지 않았습니다. 이것은 이후에도 완전히 기대됩니다.MAX_ARG_PAGES64 설정 내가 생산할 수있는 가장 긴 명령 줄은 오늘날의 시스템 하드웨어 표준이 아닌 256KB의 시스템 메모리 만 차지할 됩니다.

방법 # 4의 장점은 분명하다. 이제 정상적으로 평소처럼 명령을 실행할 수 있으며 성공적으로 완료됩니다. 단점도 똑같이 분명합니다. 명령 행에서 사용 가능한 메모리 양을 사용 가능한 시스템 메모리 양보다 늘리면 자체 시스템에 DOS 공격을 작성하여 충돌을 일으킬 수 있습니다. 특히 다중 사용자 시스템에서는 모든 사용자에게 추가 메모리가 할당되므로 약간만 증가해도 큰 영향을 줄 수 있습니다. 따라서 방법 # 4가 적합한 옵션인지 판단하는 가장 안전한 방법이므로 항상 자신의 환경에서 광범위하게 테스트하십시오.

나는 그 제한이 심각하게 성가신 것에 동의합니다.


1

대신 다음을 ls */*/*/*/*.jpg시도하십시오.

echo */*/*/*/*.jpg | xargs ls

xargs(1) 시스템의 최대 인수 수가 무엇인지 알고 표준 입력을 분할하여 지정된 명령 행을 더 이상 제한없이 더 이상 인수없이 지정된 명령 줄을 여러 번 호출합니다. -n옵션을 사용한 OS 최대 값 ).

예를 들어, 한계가 3 개의 인수이고 5 개의 파일이 있다고 가정하십시오. 이 경우 두 번 xargs실행 ls됩니다.

  1. ls 1.jpg 2.jpg 3.jpg
  2. ls 4.jpg 5.jpg

이것은 항상 완벽하게 적합하지만 항상 그런 것은 아닙니다. 예를 들어 ls(1) 각각의 개별 호출이에 의해 주어진 항목의 하위 집합 만 정렬 하기 때문에 모든 항목을 올바르게 정렬 할 수는 없습니다 .lsxargs

다른 사람들이 제안한 한도를 초과 할 수는 있지만 여전히 한계가 있으며 언젠가 JPG 컬렉션이 다시 한계를 넘어 설 것입니다. 무한한 숫자를 처리 할 스크립트를 준비해야합니다 ...


아이디어 주셔서 감사합니다! 이것은 나쁜 해결 방법이 아닙니다. 두 가지주의 사항 : 1. 이름에 공백이있는 디렉토리 및 파일 이름이 손상되므로 완벽한 대체 방법이 아닙니다. 2.와 같은 문제로 실행 예정인가요 Argument list too long위해,하지만 echo대신의 ls경우 껍질에 echo없는 쉘 내장 명령? (아마도 그것은 대부분의 껍질에서 문제가되지 않으므로 어쩌면 관련이 없습니다.)
DW

1
예, 파일 이름의 특수 문자는 문제입니다. 가장 좋은 방법은 술어 find와 함께 사용 하고 옵션 -print0xargs사용 하여 출력을 파이프하는 -0것입니다. echo셸이 내장되어 있으며 exec(3) 의 명령 줄 제한이 없습니다 .
Mikhail T.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.