오류: 매개변수 목록이 너무 깁니다.

오류: 매개변수 목록이 너무 깁니다.

오류: 매개변수 목록이 너무 깁니다.

sudo cp그리고 find... -exec sudo cp출력

/usr/bin/sudo(or find): Argument list too long

Travis CI 빌드 출력에서 ​​이 오류가 발생합니다. 내 .travis.yml 파일은 쉘 스크립트(deploy.sh)를 사용하여 Branch2의 force-app 폴더에 대해 실행되고 git diff출력(수천 개의 파일)은 cp새 디렉터리에 있습니다.

sudo cp --parents $(git diff --name-only branch2 force-app/) $DEPLOYDIRECTORY;

오류는 두 줄입니다.

./deploy.sh: line 122: /usr/bin/git: Argument list too long
./deploy.sh: line 122: /usr/bin/sudo: Argument list too long

저도 나중에 똑같은 문제가 있었어요찾다주문하다. 나는 명명 규칙을 사용하여 git diff의 각 파일에 해당하는 파일을 찾아 복사합니다.

for FILE in $GIT_DIFF_FILES; do
    if [[ $FILE == *Test.cls ]]; then
        find $classPath -maxdepth1 -samefile "$FILE-meta.xml" -exec sudo cp --parents {} $DEPLOY_DIRECTORY +
    fi;
done;

다시 오류가 발생합니다 ./deploy.sh: line 142: /usr/bin/find: Argument list too long.

노트:Travis CI는 이 빌드를 위해 Ubuntu Linux(Xenial) 가상 환경을 실행하고 있습니다.


내가 시도한 것

1.스택 크기 재설정

Travis CI는 자동으로 스택 크기를 다음과 같이 설정합니다.8192인수 최대값은8388608새로운 빌드마다. 내 배포.sh 파일에서 ulimit -s 9999999스택 크기를 다음으로 변경했습니다.9999999인수 최대값은2559999744새로운 빌드마다.

2. 명령 변경

sudo cp내가 시도한 첫 번째 명령은 다음과 같습니다 .

  1. 포맷 명령은for loop
  2. tar -cf - -C files... | tar xpf - -C target directory...
  3. 포맷 명령은git diff ... | xargs cp ...

find내가 시도한 명령에 대해 :

  1. find ... | xargs -n 1000 sudo cp ....
    • 이 명령에 추가된 다른 플래그도 효과가 없습니다.
  2. find ... -exec cp ...
    • 플래그나 구문을 변경하면 동일한 오류가 반환됩니다.

명령을 변경하는 것은 해결책이 아닌 것 같습니다.

로컬에서 오류를 재현한 후 소수의 파일(~1000개 이하)과 상호 작용할 때 내 명령이 이미 제대로 작동하는 것을 발견했습니다.

그러나 출력이 cp대략 다음과 같을 때findgit diff1200~1500개 이상의 파일그런 다음 다음을 반환합니다.

매개변수 목록이 너무 깁니다.

또한, 또는 내 쉘 스크립트를 실행하면 다음 find도 반환됩니다.cp

매개변수 목록이 너무 깁니다.

따라서 이 명령으로 무엇을 하는지는 중요하지 않은 것 같습니다. 보다 근본적인 원인은 문제의 원인이지만 출력되는 파일 개수가 git diff약 1200개 파일을 초과하는 경우에만 해당됩니다.

cpmy 및 명령을 어떻게 수정합니까 find?


오류를 재현하는 방법

내 사용 사례에 따라 이 오류를 재현하기 위해 수행해야 하는 단계는 다음과 같습니다. 저는 VS Code를 사용했기 때문에 최대한 저와 비슷하게 복제해 보시길 권해 드립니다. USERNAME다음 코드를 사용자 이름으로 바꿔야 합니다 .

1단계: 포크이 창고.

2단계: 터미널에서 아래 코드의 각 줄을 한 번에 한 줄씩 실행합니다.

cd force-app/main/default

새 폴더 "diff"를 만듭니다. 그런 다음 아래에서 계속하십시오.

git checkout -b branch2
cd force-app/main/default/classes

//comment하단에 추가myclass.cls그리고myclass.cls-meta.xml문서. 변경 사항을 저장하다.

for n in {001..1500}; do cp myclass.cls myclass$n.cls; done
for n in {001..1500}; do cp myclass.cls-meta.xml myclass$n.cls-meta.xml; done
git add .
git commit -m “first commit”
git push --set-upstream origin branch2
git checkout master
for n in {001..1500}; do cp myclass.cls myclass$n.cls; done
for n in {001..1500}; do cp myclass.cls-meta.xml myclass$n.cls-meta.xml; done
git add .
git commit -m “second commit”
git push

cdsfdx-travisci 폴더로 돌아갑니다.

sudo cp -p $(git diff --name-only branch2 /Users/USERNAME/sfdx-travisci/force-app/main/default/classes) /Users/USERNAME/sfdx-travisci/force-app/main/default/diff

for file in $(sudo cp -p $(git diff --name-only branch2 /Users/USERNAME/sfdx-travisci/force-app/main/default/classes) /Users/USERNAME/sfdx-travisci/force-app/main/default/diff); do if [[ $file == *.cls ]]; then find /Users/USERNAME/sfdx-travisci/force-app/main/default/classes -samefile “$file-meta.xml” -exec sudo cp -p {} /Users/USERNAME/sfdx-travisci/force-app/main/default/diff +; fi; done;

답변1

복잡한 복사 명령 대체:

tar -cf - -C /home/auser/data . | tar xpf - -C /home/auser/data2

답변2

몇 가지 해결 방법을 시도하는 것보다 오류의 원인을 이해하는 것이 좋습니다. 해당 매개변수가 최대 매개변수 길이를 초과하여 오류가 발생합니다.앞으로명령을 호출하십시오.

이런 일이 발생할 수 있는 이유는

  • 셸 확장으로 인해 너무 긴 매개변수 목록이 생성됨
  • 너무 긴 인수 목록을 전달하는 find가족 함수라는 프로세스(예: ).exec

이 명령은 getconf ARG_MAX인수의 최대 길이를 알려줍니다.

주문하다

cp $(git diff --name-only branch2 force-app/) ...

git명령을 실행한 다음 해당 출력을 인수로 전달하는 것을 의미합니다 cp. 이 출력이 인수의 최대 길이를 초과하면 위의 오류가 발생합니다.

주문하다

find ... -exec cp -t target {} +

별로 다르지 않습니다. 명령 +끝 에서 중괄호 대신 발견된 모든 파일의 이름을 전달하라고 find지시하기 때문입니다.find

따라서 해결책은 거대한 매개변수 문자열을 생성하지 않는 명령을 공식화하는 방법을 찾는 것입니다. xargs아니면 명령 대체가 당신의 친구일 수도 있습니다.

@AaronD.Marasco가 댓글에서 언급했듯이:

find ... -print0 | xargs -0 cp {} target

( xargs최대 인수 길이를 담당합니다. 여기서 중괄호는 인수 xargs가 아닌 인수 에 대한 것이지만 find동일한 의미를 갖습니다.)

또는 프로세스 대체를 사용하십시오(이 경우 덜 효율적임).

while IFS= read -d $'\0' -r Filename; do
  # do something with $Filename:
  cp "$Filename" target
done < <(find ... -print0)

자세한 내용은 find및 매뉴얼 페이지를 참조하십시오 xargs.

관련 정보