gpt4 book ai didi

cmd - 批量输出重定向问题

转载 作者:行者123 更新时间:2023-12-04 15:54:52 24 4
gpt4 key购买 nike

我有一个脚本 a.cmd 调用另一个脚本 b.cmd,并重定向它的输出。被调用的脚本启动一个永不终止的可执行文件。可执行文件的输出被重定向到它自己的日志文件。简化代码:

a.cmd:

[1] @ECHO OFF
[2] SET LOG_FILE_NAME="log.txt"

[3] REM Start the b.cmd redirecting all output
[4] CALL b.cmd >> %LOG_FILE_NAME% 2>&1
[5] ECHO returned to a.cmd >> %LOG_FILE_NAME% 2>&1
[6] EXIT /B 0

b.cmd:
[1] @ECHO OFF

[2] SET ANOTHER_LOG_FILE_NAME="log2.txt"
[4] ECHO RunForEver.exe redirecting all output
[5] START CMD /C "RunForEver.exe >> %ANOTHER_LOG_FILE_NAME% 2>&1"
[6] ECHO b.cmd execution complete
[7] EXIT /B 0

(为方便起见,添加了行号)

我遇到的问题是 b.cmd 中的第 4 行似乎捕获了初始日志文件(LOG_FILE_NAME)的句柄,因为所有 b.cmd 输出都被重定向到它,并且在可执行文件(以及启动它的cmd)正在运行。
我没有排除这种行为,因为我认为只有启动命令本身的输出将被重定向到 LOG_FILE_NAME 日志文件,而实际运行 RunForEver.exe 可执行文件的其他进程的输出将被写入 ANOTHER_LOG_FILE_NAME。
结果,a.cmd 中的第 5 行出错,拒绝访问 LOG_FILE_NAME。

有人可以解释发生了什么吗?有没有办法避免这种情况?

我尝试从 b.cmd 内部将输出重定向到 LOG_FILE_NAME,但随后我在 b.cmd 的第 2 行收到拒绝访问错误。

提前致谢!

最佳答案

哇!这是一个令人着迷和令人不安的发现。

我没有解释,但我有一个解决方案。

在永无止境的过程开始后,只需避免对 log.txt 的任何额外重定向。这可以通过将括号内的代码块重定向一次来完成。

@ECHO OFF
SET LOG_FILE_NAME="log.txt"

>>%LOG_FILE_NAME% 2>&1 (
CALL b.cmd
ECHO returned to a.cmd
)
EXIT /B 0

或者通过重定向 CALLed 子例程的输出来代替。
@ECHO OFF
SET LOG_FILE_NAME="log.txt"

call :redirected >>%LOG_FILE_NAME% 2>&1
EXIT /B 0

:redirected
CALL b.cmd
ECHO returned to a.cmd
exit /b

如果您需要在 a.cmd 中选择性地重定向输出,则只需将非标准流重定向到您的文件一次,然后在 block 内选择性地将输出重定向到非标准流。
@ECHO OFF
SET LOG_FILE_NAME="log.txt"

3>>%LOG_FILE_NAME% (
echo normal output that is not redirected
CALL b.cmd >&3 2>&1
ECHO returned to a.cmd >&3 2>&1
)
EXIT /B 0

同样,可以使用 CALL 而不是带括号的 block 来完成相同的技术。

我开发了一个简单的、自包含的 TEST.BAT 脚本,任何人都可以运行它来演示问题。我在我的机器上称它为 TEST.BAT。
@echo off
del log*.txt 2>nul
echo begin >>LOG1.TXT 2>&1
call :test >>LOG1.TXT 2>&1
echo end >>LOG1.TXT 2>&1
exit /b

:test
echo before start
>nul 2>&1 (
echo ignored output
start "" cmd /c "echo start result >LOG2.TXT 2>&1 & pause >con"
)
echo after start
pause >con
exit /b

master 和 STARTed 进程都被暂停,因此允许我选择哪个进程首先完成。如果 STARTed 进程在 master 之前终止,那么一切都按预期工作,主控制台窗口的以下输出证明了这一点。
C:\test>test
Press any key to continue . . .

C:\test>type log*

LOG1.TXT


begin
before start
after start
end

LOG2.TXT


start result

C:\test>

下面是一个例子,如果我允许主进程在 STARTed 进程终止之前继续运行会发生什么:
C:\test>test
Press any key to continue . . .
The process cannot access the file because it is being used by another process.

C:\test>type log*

LOG1.TXT


begin
before start
after start

LOG2.TXT


start result

C:\test>

我发现这种行为令人不安的原因是我无法理解 STARTed 进程与 LOG1.TXT 有何关系。到 START 命令执行时,所有标准输出都已重定向到 nul,所以我不明白新进程是如何知道 LOG1.TXT 的,更不用说它是如何在其上建立排他锁的。 echo ignored output 的事实没有可检测到的输出证明标准输出已成功重定向到 nul。

关于cmd - 批量输出重定向问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20849558/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com