了解 Windows 批处理文件和 Perl 的 system() 函数的交互



BATCH文件示例:

@echo off
echo starting
setlocal
cd c:tmp
set A=B
perl -e "$ENV{X}='Y'; system('cmd')"
echo finished

我运行这个脚本(在Windows7上),工作目录设置在c:.中正如预期的那样,脚本打开了一个新的命令shell,工作目录设置为c:tmp,环境设置为脚本中定义的环境。

作为下一步,我在这个shell中执行了Control-C,其中要求我执行Terminate batch job (Y/N)?.Y,回答这个问题时,我得到的错误消息是:

'Y' is not recognized as an internal or external command, operable program or batch file.

但是,我得到一个shell提示,当前目录显示为c:tmp。假设我再次键入Control-C。现在我看到:

c:tmp>^C
finished
c:>

我的提示显示我的工作目录回到了C: However,这个shell显示了一个有趣的行为。如果我在这个shell中反复点击ENTER,我得到以下输出:

c:>
c:tmp>
c:>
c:tmp>

更进一步,我知道我有两个shell在运行,交替地得到我的输入:一个工作目录设置为C:,另一个为C:tmp

知道这里发生了什么吗?有人能用他的Perl版本试用一下我的示例批处理脚本吗?顺便说一句,我使用Perl 5.8.8运行它,因为这是本项目中使用的版本。

是的,我看到了同样的行为。Ctrl+C以某种方式通过前台cmd.exe并应用于父perl进程,该进程可能会被终止(取决于Y/N答案,perl与批处理作业一起被终止)。当cmd处于交互模式时,它通常会忽略Ctrl+C,因此它泄漏到父进程似乎是一个错误。

附带说明:结果是,只剩下两个cmd shell试图读取()单个终端输入。只要一个人读到一行,他就会处理它,另一个人就会跳进去,有机会读()下一行。等等。

解决方法是告诉perl忽略SIGINT:

perl -e "$SIG{INT} = 'IGNORE'; ... "

您需要使用exit来完成前台cmd,而不是使用Ctrl+C。

最新更新