【发布时间】:2020-08-04 18:37:42
【问题描述】:
错误:参数列表太长
sudo cp 和 find... -exec sudo cp 产量
/usr/bin/sudo(or find): Argument list too long
我的 Travis CI 构建输出中出现此错误。我的 .travis.yml 文件使用 shell 脚本 (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
我对随后的 find 命令也有同样的问题。我使用命名约定从 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,并将 arg max 设置为 8388608。在我的 deploy.sh 文件中,我 ulimit -s 9999999 将每个新构建的堆栈大小更改为 9999999 并将 arg max 更改为 2559999744。
2。命令变体
对于第一个sudo cp 命令,我尝试过:
- 将命令格式化为
for loop tar -cf - -C files... | tar xpf - -C target directory...- 格式化命令为
git diff ... | xargs cp ...
对于find 命令,我试过了:
-
find ... | xargs -n 1000 sudo cp ....- 添加到此命令的任何不同标志也不起作用。
-
find ... -exec cp ...- 任何标志或语法更改都会返回相同的错误
更改命令似乎不是解决方案
在本地重现错误后,我发现我的命令在与较少数量的文件(约 1000 个或更少)交互时已经正常工作。
但是,当git diff 的输出大约为1200-1500 个文件或更多 时,运行cp 和find 命令然后返回:
参数列表太长
此外,简单地从我的 shell 脚本中运行 find 或 cp 也会返回:
参数列表太长
因此,我对这些命令做什么似乎并不重要。更根本的原因是导致问题,但仅当 git diff 输出的文件数超过大约 1200 个文件时。
如何修复我的 cp 和 find 命令?
如何重现错误
以下是根据我的用例重现此错误的步骤。我使用了 VS Code,所以我建议你尽可能地像我一样复制它。请注意,您需要将以下代码中的USERNAME 替换为您的用户名。
第 1 步:Fork this repo。
第 2 步:在终端中按照以下步骤操作
cd force-app/main/default
mkdir 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 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”
cd .. #back to the sfdx-travisci folder
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;
【问题讨论】:
-
如果您在包含数千个文件的目录中使用通配符,就会发生这种情况。
-
@Barmar 这仍然无法解释为什么第一个
sudo cp命令也会返回错误消息,对吧。 -
你是说 40 字节的命令
git diff --name-only branch2 force-app/给出/usr/bin/git: Argument list too long?听起来您在环境变量中放入了太多数据。 -
我可以看到您正在做很多工作来解决这个问题,但我仍然没有看到任何迹象表明这与非常基本的 Argument list too long error for rm, cp, mv commands 不同。如果你不喜欢那个规范,还有其他来自 30 多年 Unix 博主的常见问题解答来解释它是如何工作的;参见例如in-ulm.de/~mascheck/various/argmax
-
无论如何,这里有一个重构,希望能做到你实际想要做的,并避免这个问题。 repl.it/repls/GloomyHollowBookmarks
标签: linux bash shell ubuntu travis-ci