将 Windows 批处理文件中的输出重定向到脚本内部。

huangapple go评论105阅读模式
英文:

Redirect output from a Windows batch file within the script

问题

我正在尝试创建一个Windows批处理文件(主脚本),将其所有输出重定向到文件,同时仍然在屏幕上显示输出。我不能更改调用主脚本的所有代码 - 我需要更改主脚本本身。

我有一个解决方案,需要通过从另一个批处理文件(tee_start.bat)再次调用主脚本来进行“引导”。

我确定我要避免的是重构调用main.bat的所有其他脚本以使用tee命令 - 如果我可以在main.bat中放置一些新代码,那将是一个更小、更安全的更改。

是否有一种方法可以做到这一点,而不涉及像我下面所做的重新启动主文件?
例如,是否有一个cmd.exe或powershell.exe命令可以说“接管我的当前标准输出并将其tee出来” - 或者tee是否以某种方式支持此行为,而我错过了它?
或者,作为替代方案,我应该满足于我已经实施的最不侵入性的方法?

我已经实施了一个解决方案如下:

main.bat

  1. REM 这是引导模式的示例 - 它将重新启动此主脚本,并记录所有输出
  2. call tee_start.bat %~dpnx0 %*
  3. echo 此输出应同时出现在屏幕控制台和日志文件中

tee_start.bat

  1. REM 为了引导输出重定向 - 此脚本被调用两次 - 一次用powershell tee命令初始化日志记录
  2. REM 第二次,它只是回显日志信息并返回而不执行任何操作
  3. if x%LOG_FILE% neq x (
  4. echo 引导过程:%1%
  5. echo 转义参数:%ADDL_ARGS%
  6. echo 日志文件:%LOG_FILE%
  7. goto :EOF
  8. )
  9. set ADDL_ARGS=
  10. :loop_start
  11. shift
  12. if x%1 == x goto :after_loop
  13. REM 保留输入中的参数结构(带引号或不带引号)
  14. set ADDL_ARGS=%ADDL_ARGS% "%~1"
  15. goto loop_start
  16. :after_loop
  17. SET LOG_FILE=/path/to/some/logfile.log
  18. powershell "%1% %ADDL_ARGS% 2>&1 | tee -Append %LOG_FILE%"
英文:

I am trying to make a Windows batch file (the main script) redirect all of it's output to a file while still displaying it on the screen. I cannot change all the code that calls the main script - I need to change the main script itself.

I have a solution that requires "bootstrapping" the main script by calling it again from another bat file (tee_start.bat).
What I'm sure I want to avoid is refactoring all the other scripts that call main.bat to use the tee command - it will be a much smaller, safer change if I can put some new code in main.bat.

Is there a way to do this that does not involve restarting the main file as I am doing below?
For example, is there a cmd.exe or powershell.exe command that says "Take my current STDOUT and tee it" - or does tee somehow support this behavior and I missed it?
Or, alternatively, should I settle for what I have implemented as the least invasive method?

I have implemented a solution as follows:

main.bat

  1. REM this is an example of bootstrap mode - it will restart this main script with all output logged
  2. call tee_start.bat %~dpnx0 %*
  3. echo This output should appear both in the screen console and in a log file

tee_start.bat

  1. REM in order to bootstrap the output redirection - this script gets called twice - once to initialize logging with powershell tee command
  2. REM second time, it just echoes log information and returns without doing anything
  3. if x%LOG_FILE% neq x (
  4. echo Bootstrapped Process: %1%
  5. echo Escaped Arguments: %ADDL_ARGS%
  6. echo Log File: %LOG_FILE%
  7. goto :EOF
  8. )
  9. set ADDL_ARGS=
  10. :loop_start
  11. shift
  12. if x%1 == x goto :after_loop
  13. REM preserve argument structure (quoted or not) from the input
  14. set ADDL_ARGS=%ADDL_ARGS% \"%~1\"
  15. goto loop_start
  16. :after_loop
  17. SET LOG_FILE=/path/to/some/logfile.log
  18. powershell "%1% %ADDL_ARGS% 2>&1 | tee -Append %LOG_FILE%"

答案1

得分: 4

以下是翻译好的部分:

  1. <!-- language-all: sh -->
  2. 我建议采用以下方法,无需辅助的 `tee_start.bat` 文件:
  3. `main.bat` 内容(将输出到当前文件夹中的 `log.txt`;根据需要进行调整):
  4. @echo off & setlocal
  5. if defined LOGFILE goto :DO_IT
  6. set "LOGFILE=log.txt"
  7. :: 使用重定向重新调用
  8. "%~f0" %* 2>&1 | powershell -NoProfile -Command "$input | Tee-Object -FilePath \"%LOGFILE%\"; \"[output captured in: %LOGFILE%]\""
  9. exit /b
  10. :DO_IT
  11. :: 示例输出
  12. echo [args: %*]
  13. echo 输出到标准输出
  14. echo 输出到标准错误 >&2
  15. echo [完成]

Tee-Object 使用固定的字符编码,在 Windows PowerShell(powershell.exe)中是“Unicode”(UTF-16LE),在 PowerShell(Core)7+(pwsh.exe)中是(无BOM的UTF-8)。

  1. <details>
  2. <summary>英文:</summary>
  3. &lt;!-- language-all: sh --&gt;
  4. I suggest the following approach, which makes do without the aux. `tee_start.bat` file:
  5. `main.bat` content (outputs to `log.txt` in the current folder; adjust as needed):

@echo off & setlocal

if defined LOGFILE goto :DO_IT

  1. set &quot;LOGFILE=log.txt&quot;
  2. :: Reinvoke with teeing
  3. &quot;%~f0&quot; %* 2&gt;&amp;1 | powershell -NoProfile -Command &quot;$input | Tee-Object -FilePath \&quot;%LOGFILE%\&quot;; \&quot;[output captured in: %LOGFILE%]\&quot;&quot;
  4. exit /b

:DO_IT

:: Sample output
echo [args: %*]
echo to stdout
echo to stderr >&2
echo [done]

  1. * [`Tee-Object`](https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/tee-object) uses a _fixed_ character encoding, which is notably &quot;Unicode&quot; (UTF-16LE) in Windows PowerShell ([`powershell.exe`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe)), and (BOM-less UTF-8) in PowerShell (Core) 7+ ([`pwsh.exe`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_pwsh)).
  2. </details>

huangapple
  • 本文由 发表于 2023年1月9日 04:08:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/75050918.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定