批处理文件:“此时 2>&1 出乎意料。”

batch file: "2>&1 was unexpected at this time."

我对此进行了大量搜索,但 none 我找到的答案有效或最终是相关的。我希望有人能提供帮助,我希望这可能是一个足够普遍的问题来帮助其他人。

我已经获取了一个批处理文件(有效)并且一直在对其进行修改以使其格式更好,结构更合理等......函数“:build”中有一行重定向了 STDERR在命令的管道中使用常见的 2>&1 方法到 STDOUT。


rem EnableDelayedExpansion
@echo off

setlocal

rem ##########################################################
rem NOTE: User should have enviornment variable already set
rem up for ToolsBasePath to point to the views directory for
rem US Tools.
rem ##########################################################


rem ##########################################################
rem Global Setup
rem ##########################################################

echo Global Setup: Setup enviornment variables used for build script

title Creating Time Stamp
call :getTS     REM timestamp is now in variable %TIMESTAMP% 

rem This file creates logs either at NBLDir (e.g. c:\_NightlyBuildLogs)
title Initializing script variables
set ViewDirC=C:\views
set NBLDir=C:\_NightlyBuildLogs
set path=%ToolsBasePath%\stp\bin;C:\Windows\Microsoft.NET\Framework\v4.0.30319;%path%
set nightlyLog=%NBLDir%\%TIMESTAMP%_nightly.log

REM Initialize all build/update variables to 0
set update=0
set rebase=0
set rebaseComplete=0
set sync=0
set sconsClean=0
set sconsBuild=0
set cab=0

rem Create header for Nightly Build Log
echo ######################################################### >>%nightlyLog%
echo Nightly Build Log >> %nightlyLog%
time /T  >> %nightlyLog%
echo ######################################################### >>%nightlyLog%
echo: >> %nightlyLog%
echo PATH=%PATH% >> %nightlyLog%
echo ViewDirC=%ViewDirC% >> %nightlyLog%
echo ToolsBasePath=%ToolsBasePath% >> %nightlyLog%
echo NBLDir=%NBLDir% >> %nightlyLog%
echo: >> %nightlyLog%


rem Update US Tools
title Updating US Tools (~10 minutes)
echo Update US Tools (~10 minutes)  
time /t
echo Update US Tools >> %nightlyLog%
time /T  >> %nightlyLog%
echo ######################################################### >>%nightlyLog%
rem Comment this out for now just to skip it to test the build portion
rem call cchar_EWS_updateUSTools.cmd %TIMESTAMP%
echo Update of US Tools Complete >> %nightlyLog%
time /T  >> %nightlyLog%
time /t
echo:

title Building V2016 (~60 minutes) 
echo Build V2016 (~60 minutes) 
echo Build V2016 (~60 minutes) >> %nightlyLog%
time /T
time /T  >> %nightlyLog%
echo ######################################################### >> %nightlyLog%
call :BuildV2016
echo Build of V2016 Complete >> %nightlyLog%
time /T  >> %nightlyLog%
time /T
echo:


rem END of Main()
goto :end


:BuildV2016
cd /d %ViewDirC%\cchar_V2016DEV_EWS

rem Base ClearCase Settings
set update=0

rem UCM ClearCase Settings
set rebase=0
set rebaseComplete=0

rem Note: sync is like update, only really beneficial if others are
rem delivering to your stream or you are working on more than one view.
set sync=0

rem SCons Builds Settings
set sconsClean=0
set sconsBuild=1
set cab=1

echo Starting Build of V2016 >> %nightlyLog%
call :build
exit /b


rem ##########################################################
rem Build section, recommend you make no modifications below here.
rem ##########################################################
goto :end

:build
echo ######################################################### >> %nightlyLog%
echo Building/Updating from %cd%
echo Building/Updating from %cd% >> %nightlyLog%
time /T  >> %nightlyLog%
time /T

echo rebase=%rebase% >> %nightlyLog%
echo sync=%sync% >> %nightlyLog%
echo update=%update% >> %nightlyLog%
echo sconsClean=%sconsClean% >> %nightlyLog%
echo sconsBuild=%sconsBuild% >> %nightlyLog%
echo cab=%cab% >> %nightlyLog%

set vgr=1
set qlab=0
if %vgr% == 1 set buildDir=vgrDevEnv\build\
if %qlab% == 1 set buildDir=QlabCore\build\

if %rebaseComplete% == 1 (
  set rebase=1
  set rebaseOptions=-complete
  ) else ( set rebaseOptions= )


rem Perform Rebase
set rebaseLog=%NBLDir%\%TIMESTAMP%_rebase.log
if %rebase% == 1 (
  echo rebaseLog=%rebaseLog% >> %nightlyLog%
  set update=0
  set sync=0
  echo Rebasing %rebaseLog% >> %nightlyLog%
  cleartool rebase -rec %rebaseOptions% -force -abort >> %rebaseLog% 2>&1
  )

if %sync% == 1 (
  echo Syncing... >> %nightlyLog%
  cleartool setcs -stream
  )

if %update% == 1 (
  echo Updating %cd%... >> %nightlyLog%
  cleartool setcs -current
  )

rem Build SCONS
if %sconsClean% == 1 sconsCount.exe -clean >> %nightlyLog% 2>&1

if %sconsBuild% == 1 (
  set buildLog=%NBLDir%\%TIMESTAMP%_build.log
  echo buildLog=%buildLog% >> %nightlyLog%
  echo Building SCons %buildLog% >> %nightlyLog%
  call %buildDir%scons.bat -k > %buildLog% 2>&1
  sconsCount.exe >> %buildLog% 2>&1
  wxsMissingFileTest >> %buildLog%
  SConsBuildReport %buildLog% >> %nightlyLog%
  )

REM Build Cabs  
if %cab% == 1 (
  set cabLog=%NBLDir%\%NBLDir%\%TIMESTAMP%_cab.log
  echo cabLog=%cabLog% >> %nightlyLog%
  echo Creating CAB files >> %nightlyLog%
  call %buildDir%cabs.bat >> %cabLog%
  )

rem exit from :Build

exit /b


:getTS
REM Slice the %date% string to get date parts
set tsyear=%date:~-4% 
set tsmonth=%date:~4,2% 
set tsday=%date:~7,2% 

REM Put date parts together, subtituting "" for the " " because for
REM some reason the shell adds a space to each variable.
set TSDATE=%tsyear: =%%tsmonth: =%%tsday: =%

REM Slice the %time% string to get time parts
set tshour=%time:~0,2%
set tsminute=%time:~3,2%
set tsseconds=%time:~6,2%
set tsmilliseconds=%time:~-2%

REM Put time parts together, subtituting "" for the " " because for
REM some reason the shell adds a space to each variable.
set TSTIME=%tshour: =%%tsminute: =%%tsseconds: =%%tsmilliseconds: =%

set TIMESTAMP=%TSDATE%%TSTIME%
exit /b


:end
echo ######################################################### >> %nightlyLog%
echo Build(s) completed >> %nightlyLog%
time /T  >> %nightlyLog%
endlocal

有问题的行是: cleartool rebase -rec %rebaseOptions% -force -abort >> %rebaseLog% 2>&1

这是在 "if %rebase%" 块中,具有讽刺意味的是,它甚至没有被调用。我猜它只是在解析过程中失败了。

谁能明白为什么这可能会给我“此时 2>&1 出乎意料。”错误?

在大多数情况下,引用 %buildLog%、%nightlyLog%、%rebaseLog% 是个好习惯(除非您正在回显这些变量的内容),因为它们中可能有空格或特殊字符。

cleartool rebase -rec %rebaseOptions% -force -abort >> "%rebaseLog%" 2>>&1

如果还不能解决问题,请临时在行上方添加@ECHO ON

如果 %rebase% == 1 (

所以你可以看到发生了什么。

此外,如果您要附加 STDOUT 的输出,您可能也打算附加 STDERR 的输出。如上所示 2>>&1... 虽然那不是你的问题。

我认为问题行是:

163   call %buildDir%scons.bat -k > %buildLog% 2>&1

注释掉或删除 @echo off,我机器上的输出以:

结尾
C:\Users\pwatson\t>rem Build SCONS

C:\Users\pwatson\t>if 0 == 1 sconsCount.exe -clean  1>>C:\_NightlyBuildLogs[=11=]-26-1-213054826_nightly.log 2>&1
2>&1 was unexpected at this time.
C:\Users\pwatson\t>  call vgrDevEnv\build\scons.bat -k >  2>&1

这使得标准输出似乎没有目标文件名。这是因为没有使用延迟扩展。在 if 块内,将 %buildLog% 替换为 !buildLog!

下一个街区也是如此。使用 !cabLog! 而不是 %cabLog%.

我敢肯定你误诊了错误所在。

我认为错误在以下块中:

if %sconsBuild% == 1 (
  set buildLog=%NBLDir%\%TIMESTAMP%_build.log
  echo buildLog=%buildLog% >> %nightlyLog%
  echo Building SCons %buildLog% >> %nightlyLog%
  call %buildDir%scons.bat -k > %buildLog% 2>&1
  sconsCount.exe >> %buildLog% 2>&1
  wxsMissingFileTest >> %buildLog%
  SConsBuildReport %buildLog% >> %nightlyLog%
  )

请注意,您在块中定义了 buildLog,然后尝试在同一块中使用它。当然,扩展将是空的,因为在解析块时该值不存在。所以这两行

  call %buildDir%scons.bat -k > %buildLog% 2>&1
  sconsCount.exe >> %buildLog% 2>&1

成为

  call vgrDevEnv\build\scons.bat -k >  2>&1
  sconsCount.exe >>  2>&1

你有错误。

只需定义块前的值即可。

set buildLog=%NBLDir%\%TIMESTAMP%_build.log
if %sconsBuild% == 1 (
  echo buildLog=%buildLog% >> %nightlyLog%
  echo Building SCons %buildLog% >> %nightlyLog%
  call %buildDir%scons.bat -k > %buildLog% 2>&1
  sconsCount.exe >> %buildLog% 2>&1
  wxsMissingFileTest >> %buildLog%
  SConsBuildReport %buildLog% >> %nightlyLog%
  )

其他问题:

  • 您的日期字符串中有额外的 space,因为您的作业有不需要的尾随 space。最好在使用 SET 时使用引号,因为这样最后一个引号之后的所有内容都会被忽略,而且您不必担心隐藏尾随 spaces
set "tsyear=%date:~-4%"  Everything after the last quote is ignored
  • 即使您修复了尾随 space 问题,您仍然可以在小时值中获得前导 space,因为 %TIME% 将用 space 而不是 0 如果时间在上午 10 点之前。

  • 您应该知道您的 :getTS 例程高度依赖于您的语言环境。例如,它在我的机器上不起作用——它在值中引入了 /。一个简单的搜索产生了更好的方法来以与区域设置无关的方式使用 WMIC 获取当前时间戳。