【问题标题】:How to use wintee to redirect STDERR only?如何使用 wintee 仅重定向 STDERR?
【发布时间】:2017-02-14 11:19:41
【问题描述】:

我目前正在使用wintee 记录来自测试脚本的结果消息。命令如下所示:

test_name.bat [parameters] 2>&1 | wtee log.txt

但是,我只想将 STDERR 存档到文件中,同时仍将 STDOUT 和 STDERR 显示到控制台。问题出在 wintee 的限制:它似乎只 fork STDIN、STDOUT 和输入文件。

这是我想要做的:

  1. 将 STDOUT 重定向到流 3(未使用的流)
  2. 将 STDERR 重定向到 STDOUT
  3. 将流 3(重定向的 STDOUT)重定向到 STDERR

这样,控制台仍将显示两个流的消息,而 wintee 只会从(原来的)STDERR 派生消息。

但是,我不确定是否可能,因为我对流重定向的理解很浅。我正在尝试查看是否可以使用介于两者之间的另一个流将 STDOUT 重定向到 STDERR:

echo Hello World! 3>&2 >3

但是,它没有打印任何东西。

我想要在本地批处理中完成的工作(可选地借助其他工具)?如果是这样,我做错了什么?

【问题讨论】:

    标签: windows batch-file cmd io-redirection


    【解决方案1】:
    Set Arg = WScript.Arguments
    set WshShell = createObject("Wscript.Shell")
    Set Inp = WScript.Stdin
    Set Outp = Wscript.Stdout   
    On Error Resume Next
    
    Set Fso = CreateObject("Scripting.FileSystemObject")
    Set File = Fso.CreateTextFile(Arg(0), True)
    If err.number <> 0 then
        Outp.WriteLine "Error: " & err.number & " " & err.description & " from " & err.source
        err.clear
        wscript.exit
    End If
    Do Until Inp.AtEndOfStream
        Line=Inp.readline
        outp.writeline Line
        File.WriteLine Line
    Loop
    

    这三通标准输出。将第 4 行更改为 Set Outp = Wscript.Stderr 将使其成为 Tee StdErr。

    使用dir | cscript //nologo Tee.vbs

    【讨论】:

    • 我猜使用字符串中缺少日志文件,对吧?无论如何,如果我指定或不指定,我会收到错误 9(下标超出范围);当我将Arg(1) 更改为Arg(0) 时,不会出现错误;你能告诉我为什么会这样吗? (Arg(0) 应该指向脚本本身,Arg(1) 应该指向第一个参数,对吗?)
    • 不在 VBScript 中。这就是 CMD 的规则。在 VBScript 中,第一个参数是 arg(0)。 %~dp0 的 [几乎] 等价于 wscript.ScriptFullName
    • 啊,我明白了,这解释了我遇到的错误;谢谢...所以Arg(1) 需要在您的脚本中更改为Arg(0)...
    • 是的,它是更大文件的一部分,其中 Arg(0) 是子命令。所以是的改变。
    • 较大的文件称为过滤器,在这里1drv.ms/w/s!AvqkaKIXzvDigWyNPt14cNh-m9Ji
    【解决方案2】:

    我不知道wintee 命令,但我想我可以帮你解决重定向问题:

    您应该写以下内容,而不是 test_name.bat [parameters] 2&gt;&amp;1 | wtee log.txt

    (test_name.bat [parameters] 2>&1 1> con) | wtee log.txt
    

    这会将 STDOUT 处的文本写入控制台,将 STDERR 处的数据重定向到 STDOUT,然后将其传递给 @ 987654326@命令。

    请注意,控制台会在任何 STDERR 数据之前显示所有原始 STDOUT,因为前者是立即显示的,而后者是通过 wtee 传递的。使用纯重定向黑客,不可能保留返回数据的原始顺序。 如果您坚持这样做,则需要使用具有所需功能的wintee 以外的工具。 编辑: 特别是,管道是瓶颈,因为只有一个通道,即 STDIN,它将数据传递到该通道。所以如果你坚持STDOUTSRDERR数据按原顺序显示,同时将一个流的数据保存到文件,你别无选择,只能修改脚本test_name.bat 并避免管道。


    我试图解释使用管道左侧的命令dir ":",它会在 STDOUTSTDERR 处产生输出(因为无效路径":"):

    D:\Data> dir ":"
     Volume in drive D has no label.
     Volume Seriel Number is 0000-0000
    
     Directory of D:\Data
    
    File Not Found
    

    File Not Found 消息出现在 STDERR,而其余消息出现在 STDOUT(您可以通过像 2&gt; nul1&gt; nul 这样的重定向来证明流)。

    在管道的右侧,我正在使用命令find /V "",它只是将它在STDIN 接收到的所有数据传递并显示在控制台上:

    D:\Data> dir ":" | find /V ""
    File Not Found
     Volume in drive D has no label.
     Volume Seriel Number is 0000-0000
    
     Directory of D:\Data
    

    控制台输出的更改顺序说明了发生了什么:STDERR 立即显示,而 STDOUT 在显示之前先通过管道。

    现在让我们从您的命令行应用重定向2&gt;&amp;1

    D:\Data> (dir ":" 2>&1) | find /V ""
     Volume in drive D has no label.
     Volume Seriel Number is 0000-0000
    
     Directory of D:\Data
    
    File Not Found
    

    这会将 STDERR 重定向到 STDOUT,因此原始 STDOUT 数据与重定向的数据一起通过管道传输。将find /V "" 替换为(&gt; nul find /V "") 证明管道的右侧确实接收到了所有数据。

    现在让我们添加 1&gt; con 部分,它构成了 STDOUT 到控制台的显式重定向:

    D:\Data> (dir ":" 2>&1 1> con) | find /V ""
     Volume in drive D has no label.
     Volume Seriel Number is 0000-0000
    
     Directory of D:\Data
    
    File Not Found
    

    输出包含所有原始数据。再次将find /V "" 替换为(&gt; nul find /V "") 证明这一次,管道的右侧确实只收到File Not Found 消息,该消息最初出现在STDERR,但STDOUT 数据未通过管道传输。


    只是一个旁注:
    如果你想用纯 做类似wintee 的事情,事情就会变得非常复杂——参见this example...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-24
      • 2014-09-30
      • 2010-09-05
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      • 2014-07-22
      相关资源
      最近更新 更多