【问题标题】:Why do I get "usr/bin/cp(&find): Argument list too long"? [closed]为什么我得到“usr/bin/cp(&find): Argument list too long”? [关闭]
【发布时间】:2020-08-04 18:37:42
【问题描述】:

错误:参数列表太长

sudo cpfind... -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 命令,我尝试过:

  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 个或更少)交互时已经正常工作。

但是,当git diff 的输出大约为1200-1500 个文件或更多 时,运行cpfind 命令然后返回:

参数列表太长

此外,简单地从我的 shell 脚本中运行 findcp 也会返回:

参数列表太长

因此,我对这些命令做什么似乎并不重要。更根本的原因是导致问题,但仅当 git diff 输出的文件数超过大约 1200 个文件时。

如何修复我的 cpfind 命令?


如何重现错误

以下是根据我的用例重现此错误的步骤。我使用了 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.clsmyclass.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


【解决方案1】:

在大多数操作系统上,命令行长度都有限制。通常的解决方案不是使用命令行,而是使用管道,最终xargs 将批量文件作为参数取回。

例如你可以使用:

find . | xargs -n 1000 sudo cp ....

在这种情况下,xargs 将一次将参数拆分为 1000 个文件的批次,并在每个批次中执行 sudo cp。以这种方式,您应该不会有问题(但在非常长的目录和文件名上)。

如果您只想执行sudo 一次,您可能希望将find 移到sudo 中(警告:您可能有权以root 身份访问更多文件,并且您应该注意管道和重定向是在sudo 中完成的,而不是在调用 shell 中)。

注意:您还应该将diff 更改为git diff

我们经常在find 中使用-print0,在xargs 中使用-0,这样您就不会遇到文件名中的特殊字符的问题。 (在 POSIX 兼容系统中,文件名中禁止使用\U+0000)。

注意:如果它有效,您可能需要向创建原始文件的组发送带有补丁的错误报告(如果它不是由您发起的)。我们经常发现这样的错误:在特殊情况下失败的命令。

【讨论】:

  • 感谢您的回答。但是,无论有无sudo,我都会遇到与以前相同的错误。到目前为止,xargs 并没有给我带来好运,不管我尝试了哪些变化。
猜你喜欢
  • 1970-01-01
  • 2022-12-19
  • 1970-01-01
  • 2020-07-31
  • 1970-01-01
  • 1970-01-01
  • 2016-07-19
  • 2014-03-01
  • 2020-01-20
相关资源
最近更新 更多