如何在第一个错误时停止xargs?

51

我有一个 pages.txt 文件,里面有100个URL。我想逐个检查它们,并在第一个问题上失败。这是我正在做的事情:

cat pages.txt | xargs -n 1 curl --silent \
  --output /dev/null --write-out '%{url_effective}: %{http_code}\n'; echo $?

退出代码为1,但我只在整个文件完成时才看到它。如何在第一个问题上停止?


你真的需要一条命令完成它吗?还是用脚本可以吗? - Sir Celsius
2
我想使用 xargs,因为它有 -P 选项。 - yegor256
如果你正在寻找并行执行,你可能也想调查GNU parallel... 它比xargs简单的模型更具灵活性... - twalberg
1
只是一则提醒:xargs 已经预装在大多数系统中。 parallel 需要额外安装步骤。如果这对某些人很重要的话。 - 425nesp
2个回答

77

通用方法

xargs -n 1 sh -c '<your_command> $0 || exit 255' < input

具体情况

xargs -n 1 sh -c 'curl --silent --output /dev/null \
    --write-out "%{url_effective}: %{http_code}\n" $0 || exit 255' < pages.txt

说明

对于pages.txt中的每个URL,逐一执行命令sh -c 'curl ... $0 || exit 255'-n 1),如果命令失败则强制退出并返回255

引用自man xargs:

如果任何一个命令调用以状态码255退出,则xargs将立即停止而不读取任何进一步的输入。当发生这种情况时,会在stderr上发布错误消息。


1
完美。我有一个脚本来校验文件的校验和。由于我通常一次要处理整个磁盘,这对于一个简单的shell脚本循环来说是太多参数了。通常情况下,如果我按下control-c因为我看到了错误或其他问题,xargs会继续生成其余的进程。加入exit 255可以解决这个问题。这也意味着如果发生IO错误导致驱动器离线,所有操作都将停止在导致错误的文件处。 - Bill

3
我还没有找到使用 xargs 实现你所要求的功能的方法,但是通过 read 循环可能会是你寻找的答案。
while read URL; do
  curl --silent \
    --output /dev/null --write-out '%{url_effective}: %{http_code}\n' $URL;
  RET=$?;
  echo $RET;
  if [ $RET -ne 0 ]; then break; fi
done < pages.txt

2
问题在于我无法并行运行它们,而 xargs 则有 -P 选项可以实现并行。 - yegor256
@yegor256 你是说你想要并行启动进程,但在“第一个”进程退出时停止?哪个进程是执行/失败的“第一个”?当它们中的一个失败时,正在处理的那些进程会发生什么? - Christopher Schultz
通常情况下,如果我使用xargs,那是因为我在命令行中有太多的参数。对于退出代码255的提示对我有效。当我按下Ctrl+C时,它也正确地处理了中止问题。 - Bill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接