kingtermite kingtermite - 1 month ago 12
Bash Question

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

I've done a ton of searching on this, but none of the answers I've found worked or ended up being relevant. I hope someone can help and I hope this might be a common enough problem to help others.

I've taken a batch file (that worked) and have been reworking it to be better formatted, a bit more structured, etc.... There is a line in the function ":build" that redirects STDERR to STDOUT using the common 2>&1 method in the piping from a command.




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





The line in question is:
cleartool rebase -rec %rebaseOptions% -force -abort >> %rebaseLog% 2>&1

This is in the "if %rebase%" block, which ironically isn't even being called. I'm guessing it's failing just during the parse.

Can anyone see why this might be giving me the "2>&1 was unexpected at this time." error?

Answer

I'm pretty sure you have misdiagnosed where the error is.

I believe the error is in the following block:

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%
  )

Note that you define buildLog within the block, and then attempt to use it within the same block. Of course the expansion will be empty because the value did not exist when the block is parsed. So these two lines

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

become

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

And you have your error.

Simply define the value before the block.

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%
  )

Other issues:

  • You are getting extra spaces in your date strings because your assignments have an unwanted trailing space. Best to use quotes when using SET because then everything after the last quote is ignored, and you don't have to worry about hidden trailing spaces
set "tsyear=%date:~-4%"  Everything after the last quote is ignored
  • Even if you fix the trailing space issue, you still can get a leading space in the hour value because %TIME% will left pad with space instead of 0 if the time is before 10am.

  • You should be aware that your :getTS routine is highly dependent on your locale. For example, it does not work on my machine - it introduces a / into the value. A simple search yields much better ways to get current timestamp with WMIC in a way that is locale agnostic.