我面临一种奇怪的情况,即我编写的批处理文件报告了错误的退出状态。这是重现该问题的最小示例:
bug.cmd
echo before
if "" == "" (
echo first if
exit /b 1
if "" == "" (
echo second if
)
)
echo after
如果我运行此脚本(使用Python,但是当以其他方式启动时实际上也会出现问题),这是我得到的:
python -c "from subprocess import Popen as po; print 'exit status: %d' % po(['bug.cmd']).wait()"
echo before
before
if "" == "" (
echo first if
exit /b 1
if "" == "" (echo second if )
)
first if
exit status: 0
注意如何exit status
报告,0
即使exit /b 1
应该如此1
。
现在很奇怪的是,如果我删除了innerif
子句(这没关系,因为之后的所有内容exit /b 1
都不应该执行),然后尝试启动它:
ok.cmd
echo before
if "" == "" (
echo first if
exit /b 1
)
echo after
我再次启动它:
python -c "from subprocess import Popen as po; print 'exit status: %d' % po(['ok.cmd']).wait()"
echo before
before
(environment) F:\pf\mm_3.0.1\RendezVous\Services\Matchmaking>if "" == "" (
echo first if
exit /b 1
)
first if
exit status: 1
现在exit status
正确地报告为1
。
我不知道是什么原因造成的。嵌套if
语句是否非法?
我如何正确并可靠地批量发出脚本退出状态的信号?
注意:调用exit 1
(不带/b
)不是一个选择,因为它会杀死整个解释器并阻止使用本地脚本。
正如@dbenham指出的那样,“ [i] fa命令EXIT /B
在同一命令块中的之后解析,即使随后的命令从不执行,问题也会显现出来”。在这种特殊情况下,IF
语句的主体基本上被评估为
(echo first if) & (exit /b 1) & (if "" == "" (echo second if))
其中&
运算符是函数cmd!eComSep
(即命令分隔符)。的EXIT /B 1
命令(功能cmd!eExit
)是由全局变量设定评价cmd!LastRetCode
为1,然后执行基本GOTO :EOF
。当它返回时,第二个eComSep
seescmd!GotoFlag
被设置,因此跳过评估右侧。在这种情况下,它也忽略左侧的返回码,而是返回SUCCESS
(0)。这被传递到堆栈上,成为进程退出代码。
下面,我包括了用于运行bug.cmd和ok.cmd的调试会话。
bug.cmd:
(test) C:\Temp>cdb -oxi ld python
Microsoft (R) Windows Debugger Version 6.12.0002.633 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.
CommandLine: python
Symbol search path is: symsrv*symsrv.dll*
C:\Symbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
(1404.10b4): Break instruction exception - code 80000003 (first chance)
ntdll!LdrpDoDebuggerBreak+0x30:
00000000`77848700 cc int 3
0:000> g
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:44:40)
[MSC v.1600 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from subprocess import Popen as po
>>> po('bug.cmd').wait()
Symbol search path is: symsrv*symsrv.dll*
C:\Symbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
(1818.1a90): Break instruction exception - code 80000003 (first chance)
ntdll!LdrpDoDebuggerBreak+0x30:
00000000`77848700 cc int 3
1:005> bp cmd!eExit
1:005> g
(test) C:\Temp>echo before
before
(test) C:\Temp>if "" == "" (
echo first if
exit /b 1
if "" == "" (echo second if )
)
first if
Breakpoint 0 hit
cmd!eExit:
00000000`4a6e8288 48895c2410 mov qword ptr [rsp+10h],rbx
ss:00000000`002fed78=0000000000000000
1:005> kc
Call Site
cmd!eExit
cmd!FindFixAndRun
cmd!Dispatch
cmd!eComSep
cmd!Dispatch
cmd!eComSep
cmd!Dispatch
cmd!Dispatch
cmd!eIf
cmd!Dispatch
cmd!BatLoop
cmd!BatProc
cmd!ECWork
cmd!ExtCom
cmd!FindFixAndRun
cmd!Dispatch
cmd!main
cmd!LUAGetUserType
kernel32!BaseThreadInitThunk
ntdll!RtlUserThreadStart
1:005> db cmd!GotoFlag l1
00000000`4a70e0c9 00 .
1:005> pt
cmd!eExit+0xe1:
00000000`4a6e8371 c3 ret
1:005> r rax
rax=0000000000000001
1:005> dd cmd!LastRetCode l1
00000000`4a70e188 00000001
1:005> db cmd!GotoFlag l1
00000000`4a70e0c9 01 .
1:005> gu;gu;gu
cmd!eComSep+0x14:
00000000`4a6e6218 803daa7e020000 cmp byte ptr [cmd!GotoFlag
(00000000`4a70e0c9)],0
ds:00000000`4a70e0c9=01
1:005> p
cmd!eComSep+0x1b:
00000000`4a6e621f 0f85bd4d0100 jne cmd!eComSep+0x1d
(00000000`4a6fafe2) [br=1]
1:005>
cmd!eComSep+0x1d:
00000000`4a6fafe2 33c0 xor eax,eax
1:005> pt
cmd!eComSep+0x31:
00000000`4a6e6235 c3 ret
1:005> r rax
rax=0000000000000000
1:005> bp ntdll!RtlExitUserProcess
1:005> g
Breakpoint 1 hit
ntdll!RtlExitUserProcess:
00000000`777c3830 48895c2408 mov qword ptr [rsp+8],rbx
ss:00000000`0029f6b0=00000000003e5638
1:005> r rcx
rcx=0000000000000000
1:005> g
ntdll!ZwTerminateProcess+0xa:
00000000`777ede7a c3 ret
1:005> g
0
ok.cmd:
>>> po('ok.cmd').wait()
Symbol search path is: symsrv*symsrv.dll*
C:\Symbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
(ce4.b94): Break instruction exception - code 80000003 (first chance)
ntdll!LdrpDoDebuggerBreak+0x30:
00000000`77848700 cc int 3
1:002> bp cmd!eExit
1:002> g
(test) C:\Temp>echo before
before
(test) C:\Temp>if "" == "" (
echo first if
exit /b 1
)
first if
Breakpoint 0 hit
cmd!eExit:
00000000`4a6e8288 48895c2410 mov qword ptr [rsp+10h],rbx
ss:00000000`0015e808=0000000000000000
1:002> kc
Call Site
cmd!eExit
cmd!FindFixAndRun
cmd!Dispatch
cmd!eComSep
cmd!Dispatch
cmd!Dispatch
cmd!eIf
cmd!Dispatch
cmd!BatLoop
cmd!BatProc
cmd!ECWork
cmd!ExtCom
cmd!FindFixAndRun
cmd!Dispatch
cmd!main
cmd!LUAGetUserType
kernel32!BaseThreadInitThunk
ntdll!RtlUserThreadStart
1:002> gu;gu;gu
cmd!eComSep+0x2c:
00000000`4a6e6230 4883c420 add rsp,20h
1:002> p
cmd!eComSep+0x30:
00000000`4a6e6234 5b pop rbx
1:002> p
cmd!eComSep+0x31:
00000000`4a6e6235 c3 ret
1:002> r rax
rax=0000000000000001
1:002> bp ntdll!RtlExitUserProcess
1:002> g
Breakpoint 1 hit
ntdll!RtlExitUserProcess:
00000000`777c3830 48895c2408 mov qword ptr [rsp+8],rbx
ss:00000000`0015f750=00000000002b5638
1:002> r rcx
rcx=0000000000000001
1:002> g
ntdll!ZwTerminateProcess+0xa:
00000000`777ede7a c3 ret
1:002> g
1
在ok.cmd情况下,cmd!eComSep
在堆栈跟踪中仅出现一次。该exit /b 1
命令被评估为右侧操作数,因此查看的代码GotoFlag
永远不会运行。取而代之的是,返回代码1沿栈传递,成为流程退出代码。
我正在写一个批处理应用程序,我想在我的应用程序逻辑识别问题并返回时立即设置退出状态。 例如,我正在Writer的write方法中设置以下状态。
我正在创建一个非常通用的Spring批处理应用程序,在该应用程序中,我从YAML文件中读取了大量配置,并动态地创建作业并注册如下所示的作业, 所有这些都是在Configuration类中完成的。之后,我会像下面这样启动所有的工作, 我从下面的另一个线程开始做, 这是可行的,但问题是它不会等待所有的作业,当它完成第一个作业时,应用程序将退出。我如何让这等到所有的作业完成,然后退出。
为了Spark Streaming应用程序能够在集群中稳定运行,系统应该能够以足够的速度处理接收的数据(即处理速度应该大于或等于接收数据的速度)。这可以通过流的网络UI观察得到。批处理时间应该小于批间隔时间。 根据流计算的性质,批间隔时间可能显著的影响数据处理速率,这个速率可以通过应用程序维持。可以考虑WordCountNetwork这个例子,对于一个特定的数据处理速率,系统可能可以每2秒打印一次
...there are dark corners in the Bourne shell, and people use all of them. Chet Ramey exit 命令一般用于结束一个脚本,就像C语言的exit一样。它也能返回一个值给父进程。 每一个命令都能返回一个退出状态(有时也看做 返回状态 ).一个命令执行成功返回0,一个执行不成功的命令则返回一个非零值,此值通常可以被解释
问题内容: 我试图: 根据搜索条件查找文档, 如果找到,请更新一些属性 如果没有插入带有某些属性的文档。 我正在使用,因为我也在执行单个插入操作。我想在一次操作中完成所有操作。 但是,它什么都不会导致为更新/向上插入操作插入任何内容。 这是插入文档: 这是最新资料: 这就是我试图更新/更新的方式: 为什么不更新/更新呢? 注意 那是使用水线ORM的JS代码,它也使用mongodb本机驱动程序。 问
问题内容: 与Linux中的类似,有没有一种方法可以获取Windows批处理文件()中程序的退出状态? 假设该程序在成功执行时失败,在失败时失败,我如何将这些退出值捕获在文件中? 问题答案: 使用%ERRORLEVEL%。您不喜欢批处理文件清晰明了吗?:)