如何在遇到错误时终止批处理文件?

Jos*_*off 270 batch-file

我有一个批处理文件,它使用不同的参数反复调用相同的可执行文件.如果其中一个调用返回任何级别的错误代码,如何使其立即终止?

基本上,我想要相当于MSBuild的ContinueOnError=false.

sys*_*USE 275

检查errorlevel一个if语句,然后exit /b(仅退出b atch文件,而不是整个cmd.exe进程)获取0以外的值.

same-executable-over-and-over.exe /with different "parameters"
if %errorlevel% neq 0 exit /b %errorlevel%
Run Code Online (Sandbox Code Playgroud)

如果希望errorlevel的值传播到批处理文件之外

if %errorlevel% neq 0 exit /b %errorlevel%
Run Code Online (Sandbox Code Playgroud)

但如果这是在里面for它有点棘手.你需要更像的东西:

setlocal enabledelayedexpansion
for %%f in (C:\Windows\*) do (
    same-executable-over-and-over.exe /with different "parameters"
    if !errorlevel! neq 0 exit /b !errorlevel!
)
Run Code Online (Sandbox Code Playgroud)

编辑:您必须在每个命令后检查错误.cmd.exe/command.com批处理中没有全局"on error goto"类型的构造.我还根据CodeMonkey更新了我的代码,尽管我在XP或Vista上的任何批处理攻击中都没有遇到负面的错误级别.

  • 有没有办法为整个文件说明一次?"在错误转到"或类似的东西? (11认同)
  • 负错误级别检查+1.如果一个脚本由于否定结果而无声地失败. (3认同)
  • 请注意,对于某些命令(例如 Robocopy),有一些退出代码 > 0,这并不是真正的错误 https://ss64.com/nt/robocopy-exit.html (3认同)
  • 启用/禁用延迟扩展或启用/禁用命令扩展(`neq` 所需)与使用 `if not errorlevel 1 exit /B` 无关,如 Microsoft 在支持文章 [使用命令重定向运算符] (https:// technet.microsoft.com/en-us/library/bb490982.aspx) 以及在 cmd 窗口中运行 `if /?` 的帮助输出。当前的错误级别(退出代码)保持在退出处理与`exit /B` 的批处理文件。注意:带有参数`/B`的`exit`需要启用命令扩展,参见[GOTO :EOF返回到哪里?](http://stackoverflow.com/questions/37515901/) (2认同)

Fow*_*owl 238

添加|| goto :label到每一行,然后定义一个:label.

例如,创建此.cmd文件:

@echo off

echo Starting very complicated batch file...
ping -invalid-arg || goto :error
echo OH noes, this shouldn't have succeeded.
goto :EOF

:error
echo Failed with error #%errorlevel%.
exit /b %errorlevel%
Run Code Online (Sandbox Code Playgroud)

另请参阅有关退出批处理文件子例程的问题.

  • 比"if-errorlevel"更好,更有用! (18认同)
  • 在大多数shell脚本语言中,这是一个非常常见的习惯用语,并且它读得很好:"这样做,或者如果它失败了就行了......" (4认同)
  • 我使用SET来手动跟踪行号:`command || (SET ErrorLine = 102 && goto:error)` (3认同)
  • @jpmc26是的,确实是对自己证明 - `cmd/k exit -1 && echo success || echo fail` - 打印失败. (3认同)
  • 您甚至可以使用类似`command || 之类的东西来避免标签 退出 /b %errorlevel%` (2认同)

Ben*_*hon 85

最短的:

command || exit /b
Run Code Online (Sandbox Code Playgroud)

如果需要,可以设置退出代码:

command || exit /b 666
Run Code Online (Sandbox Code Playgroud)

你也可以记录:

command || echo ERROR && exit /b
Run Code Online (Sandbox Code Playgroud)

  • @FrankSchwieterman,是的,当你调用`exit/b`时,`%ERRORLEVEL%`是不变的,所以转发了错误代码 (5认同)
  • exit/b是否偶然返回原始失败的退出代码? (4认同)

小智 24

一个小的更新,您应该将"if errorlevel 1"的检查更改为以下内容...

IF %ERRORLEVEL% NEQ 0 
Run Code Online (Sandbox Code Playgroud)

这是因为在XP上你可以得到负数作为错误.0 =没有问题,其他任何问题.

并记住DOS处理"IF ERRORLEVEL"测试的方式.如果您要检查的数字是该数字或更高,它将返回true,因此如果您要查找特定的错误编号,则需要以255开头并减少.


Eri*_*sty 13

这是BASH和Windows CMD 的多语言程序,它运行一系列命令并在其中任何一个失败时退出:

#!/bin/bash 2> nul

:; set -o errexit
:; function goto() { return $?; }

command 1 || goto :error

command 2 || goto :error

command 3 || goto :error

:; exit 0
exit /b 0

:error
exit /b %errorlevel%
Run Code Online (Sandbox Code Playgroud)

我过去曾使用过这种类型的东西来进行多平台连续集成脚本.


Xar*_*arn 8

我更喜欢OR形式的命令,因为我发现它们最具可读性(而不是在每个命令之后都有一个if).然而,这种天真的做法,command || exit /b %ERRORLEVEL%错误的.

这是因为批次在首次读取行时扩展变量,而不是在使用它们时扩展变量.这意味着如果command上面的行失败,批处理文件将正确退出,但它会以返回代码0退出,因为这就是%ERRORLEVEL%行开头的值.显然,这在我们的脚本中是不可取的,因此我们必须启用 延迟扩展,如下所示:

SETLOCAL EnableDelayedExpansion

command-1 || exit /b !ERRORLEVEL!
command-2 || exit /b !ERRORLEVEL!
command-3 || exit /b !ERRORLEVEL!
command-4 || exit /b !ERRORLEVEL!
Run Code Online (Sandbox Code Playgroud)

此代码段将执行命令1-4,如果其中任何一个失败,它将使用与失败命令相同的退出代码退出.

  • 您的代码是正确的,但我相信对于简单任务来说不必要地冗长:不带参数的“exit /b”将保留错误级别。您的示例可以简化为“command-1 ||” exit /b` -- 更短并且不再需要 EnableDelayedExpansion。但是,您的代码确实演示了 EnableDelayedExpansion 的有效使用,有人可能会在此基础上构建,例如: `command-1 || (echo Error=!errorlevel! && exit /b)`。 (5认同)