TeamCity 7.0.1 command line build step and ERRORLEVEL - teamcity

I have a build step in my build configuration thats runner type "Command Line", running a custom script.
The script is executing Robocopy:
robocopy "%teamcity.build.workingDir%\Code" "\\target\d$\Web\Target Sites" /E /NP /LOG:robocopy.log
if ERRORLEVEL GEQ 4 (
"D:\blat.exe" "robocopy.log" -to me#me.com -f me#me.com -subject "Error during robocopy on TEAMCITY" -server mail.me.com
)
exit /B 0
The Robocopy command is working fine but I keep getting an email and in the build log I keep seeing:
GEQ was unexpected at this time.
The ERRORLEVEL check isn't working for some reason?
I tried IF %ERRORLEVEL% GEQ but this breaks my build has TeamCity expects me to pass a build parameter.
Does this only work as an "Executable with parameters"?

Neil, you might try escaping the percent sign.
Try IF %%ERRORLEVEL%% GEQ ...

I've just run into this problem, and appreciate #John's answer.
Here is what I came up with:
robocopy [from] [to] /MIR
REM http://ss64.com/nt/robocopy-exit.html
IF %%ERRORLEVEL%% EQU 0 (
ECHO No errors occurred, and no copying was done; The source and destination directory trees are completely synchronized.
EXIT 0
)
IF %%ERRORLEVEL%% EQU 1 (
ECHO One or more files were copied successfully, new files have arrived.
EXIT 0
)
IF %%ERRORLEVEL%% EQU 2 (
ECHO Some Extra files or directories were detected. No files were copied.
EXIT 0
)
IF %%ERRORLEVEL%% GEQ 3 (
ECHO Robocopy Exit Codes: http://ss64.com/nt/robocopy-exit.html
EXIT %%ERRORLEVEL%%
)

Related

How to make the script stop execution when an error occurres

I have a Windows bat file with the following content:
setlocal EnableDelayedExpansion
rem Stop batch script loop if a command failed.
#echo OFF
FOR %%a in (x86 x86_64 armeabi-v7a arm64-v8a) do (
set MY_ANDROID_BUILD_ABI=%%a
FOR %%m in (debug release) DO (
set MY_MODE=%%m
echo !MY_MODE! -^> !MY_ANDROID_BUILD_ABI!
cd D:\dev\libs\QT6.4\android\!MY_MODE!\!MY_ANDROID_BUILD_ABI!
rem some further build commands go here
cmake --build . --parallel && cmake --install .
)
)
it iterates over build configurations and executes multiple commands inside nested loop to build some library.
How to make the script exit the loop and stop execution when an error occurres?
For example, the script should stop if a directory does not exist or cmake command failed.
Should I add
IF %ERRORLEVEL% NEQ 0 (
echo "Previous command execution failed."
exit %ERRORLEVEL%
)
after each command?
Yes, you need to add some kind of error checking, since cmd doesn't have built-in exceptions. The full solution is to add after each command:
(command)
if ERRORLEVEL 1 (
echo failure message, maybe to some log
exit !ERRORLEVEL!
)
You can use the shorthand suggested in #Gerhard's comment:
(command) || (echo failure message& exit /b !ERRORLEVEL! )
In either case, beware of using %ERRORLEVEL%, as it's expanded too early. As your code correctly shows, use !ERRORLEVEL! (which requires setlocal EnabledDelayedExpansion), or use the special if ERRORLEVEL 1 format.

How to make a batch file sleep for some time inside an if statement?

I am trying to write the below code, and I want it to display the error before it exits, but whenever I run it, it exits right away.
#echo off
cd "haha"
if %errorlevel% 1 (
echo Failure reason given is %errorlevel%
sleep 5
exit /b %errorlevel%
)
echo files deleted successfully!
del /Q *
pause
I have also tried timeout /t 5 doesn't seem to work.
This should work :
#echo off
cd "haha" 2>nul
if %errorlevel%==1 (
echo Failure reason given is %errorlevel%
timeout /t 5
exit /b %errorlevel%
)
The correct syntax is
if errorlevel 1 (
meaning if errorlevel is 1 or greater
OR
if %errorlevel% geq 1 (
which means the same thing.
As it stands, cmd is interpreting you code as
if 1 1 (
(assuming errorlevel is 1). This is a syntax error, so cmd shows a message. If you are running by point-click and giggle, the window will close. If you are running from the prompt, then cmd will report a syntax error.
Be warned however that executing an exit statement from the prompt will abort the cmd instance. Better to use goto :eof unless you have good reason otherwise.
timeout /t 5 should work, but will generate a countdown.
timeout /t 5 >nul should appear simply to wait. The issue is that you have to solve the if syntax first, else the timeout instruction won't be reached.

Calling different function on error. Windows Batch

I've got a little script that will check for new files in a folder, and it will print all of the PDF files. Whenever the print fails, the %errorlevel% variable will go up to 1. I'm trying to use an if statement with goto and labels to get it to work but I can't figure out what is going on.
The script is:
:printfile
echo printing %1
set fname=%1
set fullFname="print\STW_Print\STW_Printer_TEST\%fname:~1%
echo ERLVL: %errorlevel%
"C:\Program Files (x86)\SumatraPDF\SumatraPDF.exe" -silent -print-to "\\s8011\OPS_2055_IS" %
echo ERLVL: %errorlevel%
set logFilename=%DATE:~4,2%-%DATE:~7,2%-%DATE:~10,4%
if %errorlevel% neq 0 goto error
echo Moving %fname% to printed
move %fullFname% STW_printed
echo %time% %1 Printed on STWTEST and Moved>> Printlogs\TEST-%logFilename%-log.txt
goto eof
:error
echo Moving %fname% to failed
move %fullFname% STW_failed
echo %time% %1 Failed on STWTEST and Moved>> Printlogs\TEST-%logFilename%-log.txt
GOTO eof
:eof
The line that calls the script:
for /f "tokens=*" %%i in ('dir print\STW_Print\STW_Printer_TEST\*.pdf /b') do (call :printfile "%%i")
And my output:
printing "BADTEST (2) - Copy.pdf"
ERLVL: 0
ERLVL: 1
Moving "BADTEST (2) - Copy.pdf" to printed
1 file(s) moved.
printing "BADTEST (2).pdf"
ERLVL: 0
ERLVL: 1
Moving "BADTEST (2).pdf" to printed
1 file(s) moved.
printing "BADTEST (3) - Copy.pdf"
ERLVL: 0
ERLVL: 1
Moving "BADTEST (3) - Copy.pdf" to printed
1 file(s) moved.
I can't figure out why it's not moving to failed. Any help would be greatly appreciated!
It is because you check errorlevel after doing the SET command... which clears errorlevel. Move your 'set logfilename...' line farther up. Also, when using errolevel you can just do
if errorlevel 1 goto :error

Jenkins and return code from windows batch

I using a Jenkins (on a windows machine) job to compile some code for different targets via Ant.
For doing so, I wrap the call to the ant target within a (windows) batch loop like this:
#echo off
for %%t in (target1 target2 target3) do (
ant -f build.xml build -DPARAM_TARGET=%%t
)
That was my first idea ... but this codes leads to an successful build even if (e.g.) target1 failed. So I put some more lines to the windows batch build step to get more overview. Also I have checekdout the code to get the same workingspace than Jenkins has to my local machine and add an test.bat to check the windows batch code can work at all.
#echo off
for %%t in (target1 target2 target3) do (
ant -f build.xml build -DPARAM_TARGET=%%t
echo ELVL: %ERRORLEVEL%
IF NOT %ERRORLEVEL% == 0 (
echo ABORT: %ERRORLEVEL%
exit /b %ERRORLEVEL%
) ELSE (
echo PROCEED: %ERRORLEVEL%
)
)
Testing this on my local windows machine shows the expected behaviour - here on success:
BUILD SUCCESSFUL
Total time: 3 seconds
ELVL: 0
PROCEED: 0
And on failure:
BUILD FAILED
C:\Work\...
C:\Work\...
Total time: 0 seconds
ELVL: 9009
ABORT: 9009
The same code on Jenkins do this:
BUILD FAILED
C:\Work\...
C:\Work\...
Total time: 4 seconds
ELVL: 0
PROCEED: 0
After using google for a while it reveals, that the return code from calling the Ant target is not properly passed to the java enviornment wherefrom Jenkins do the calls. I have tested around using "call" or "set ERRORLEVEL=1" something like this, but haven't found a soloution yet.
Anyone has an idea?
Put the loop (target1-3) into a system groovy script and hande the callc manually - does that work?
Regards
I think your problem is because you read %ERROR_LEVEL% in a for loop.
I think you must use setlocal EnableDelayedExpansion
EnableDelayedExpansion : Expand variables at execution time rather than at parse time.
(ref is here)
Try to do something like this :
setlocal EnableDelayedExpansion
for %%t in (target1 target2 target3) do (
ant -f build.xml build -DPARAM_TARGET=%%t
echo ELVL: !ERRORLEVEL!
IF NOT !ERRORLEVEL! == 0 (
echo ABORT: !ERRORLEVEL!
exit /b !ERRORLEVEL!
) ELSE (
echo PROCEED: !ERRORLEVEL!
)
)
It don't explain why it runs on your computer... maybe because the EnableDelayedExpansion is already set in your dos windows.
EDIT
In batch-file :
%var% will be expanded when the code is parsed (i.e. before execution !)
!var! will be expanded when the code is executed
Since you are in a loop : %ERROR_LEVEL% is expanded once (i.e. just before first execution). But what you need is to re-expand ERROR_LEVEL for each iteration and that's the purpose of !ERROR_LEVEL! syntax.
#echo off
for %%t in (target1 target2 target3) do (
ant -f build.xml build -DPARAM_TARGET=%%t
echo ELVL: %ERRORLEVEL%
IF NOT %ERRORLEVEL% == 0 (
echo ABORT: %ERRORLEVEL%
exit /b %ERRORLEVEL%
) ELSE (
echo PROCEED: %ERRORLEVEL%
)
)
IIRC The issue is that ant.bat is a batch file, so you need to call it, e.g.
#ECHO OFF
FOR %%t IN (target1 target2 target3) DO (
CALL ant.bat -f build.xml build -DPARAM_TARGET=%%t
ECHO ELVL: %ERRORLEVEL%
IF NOT %ERRORLEVEL% == 0 (
ECHO ABORT: %ERRORLEVEL%
EXIT /b %ERRORLEVEL%
) ELSE (
ECHO PROCEED: %ERRORLEVEL%
)
)
Update
Actually there is a nicer way:
#ECHO OFF
FOR %%t IN (target1 target2 target3) DO (
CALL ant.bat -f build.xml build -DPARAM_TARGET=%%t || EXIT /b 1
)

Need help modifying script to use individual files, instead of all files at once

I was wondering if anyone could help me with a very simple rework of this script I inherited. I have no previous experience with batch files and needed to modify this already working script in a very simple manner.
Currently, this script does the following:
- Monitors a folder and looks to see if there are files in it
- If there are, it executes a FTP transfer via command line
- Then, it moves the files into a archive folder created and named with the current timestamp and writes something to a text log file
- If there are no files, the script exits and does nothing.
As of now, the script is looking for, processing, and moving all the files at once. I was looking to see if I could be pointed int the right direction with help on how to modify the script so that it does each file one by one, instead of using . everywhere. Ultimately, I think all I need to do is figure out how to do the loop correctly and read/store the filenames to use as variables instead of using . Any help would be appreciated.
#ECHO OFF
:: Set count of files = 0
SET X=0
:: Set timestamp for processed folders
set TIMESTAMP=%DATE:~10,4%%DATE:~4,2%%DATE:~7,2%-%TIME:~0,2%.%TIME:~3,2%.%TIME:~6,2%.%TIME:~9,2%
:: If more than 0 files exist begin ftp and file archival otherwise exit
FOR %%i IN (c:\Encoded_HL7_Vanderbilt\*.*) DO IF EXIST %%i (SET X=1)
IF [%X%] gtr [0] (cd\..\..
cd\"Program Files (x86)\Ipswitch\WS_FTP 12"
IF ERRORLEVEL 1 (echo %TIMESTAMP% Error switching to ftp program directory>E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.error.txt
exit)
wsftppro -s local:C:\Encoded_HL7_Vanderbilt\*.* -d Vandy!Vanderbilt:/incoming/
IF ERRORLEVEL 1 (echo %TIMESTAMP% Error transmitting file to ftp server>E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.error.txt
exit)
md "E:\Processed_HL7_Vanderbilt\%1\%TIMESTAMP%"
IF ERRORLEVEL 1 (echo %TIMESTAMP% Error creating archive directory>E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.error.txt
exit)
move "C:\Encoded_HL7_Vanderbilt\*.*" "E:\Processed_HL7_Vanderbilt%1\%TIMESTAMP%"
IF ERRORLEVEL 1 (echo %TIMESTAMP% Error moving files to archive directory>E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.error.txt
exit)) ELSE (exit)
echo %TIMESTAMP% File transfer completed successfully>E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.success.txt
exit
Give this a walk around the park: if any file generates an error then it will stop processing further files.
#ECHO OFF
set "folder=%~1"
:: Set timestamp for processed folders
set TIMESTAMP=%DATE:~10,4%%DATE:~4,2%%DATE:~7,2%-%TIME:~0,2%.%TIME:~3,2%.%TIME:~6,2%.%TIME:~9,2%
:: If more than 0 files exist begin ftp and file archival otherwise exit
FOR %%a IN (c:\Encoded_HL7_Vanderbilt\*.*) DO (
cd\"Program Files (x86)\Ipswitch\WS_FTP 12"
IF ERRORLEVEL 1 (echo %TIMESTAMP% Error switching to ftp program directory>E:\HL7_Vanderbilt_log\%folder%\%TIMESTAMP%.error.txt
goto :done)
wsftppro -s local:%%a -d Vandy!Vanderbilt:/incoming/
IF ERRORLEVEL 1 (echo %TIMESTAMP% Error transmitting "%%a" file to ftp server>E:\HL7_Vanderbilt_log\%folder%\%TIMESTAMP%.error.txt
goto :done)
md "E:\Processed_HL7_Vanderbilt\%folder%\%TIMESTAMP%" 2>nul
IF ERRORLEVEL 1 (echo %TIMESTAMP% Error creating archive directory>E:\HL7_Vanderbilt_log\%folder%\%TIMESTAMP%.error.txt
goto :done)
move "%%a" "E:\Processed_HL7_Vanderbilt\%folder%\%TIMESTAMP%"
IF ERRORLEVEL 1 (echo %TIMESTAMP% Error moving "%%a" file to archive directory>E:\HL7_Vanderbilt_log\%folder%\%TIMESTAMP%.error.txt
goto :done)
)
echo %TIMESTAMP% File transfers completed successfully or no files were found>E:\HL7_Vanderbilt_log\%folder%\%TIMESTAMP%.success.txt
exit
:done
goto :EOF
try this, it might work for you:
#ECHO OFF &SETLOCAL
:: Set count of files = 0
SET /a count=0
:: Set timestamp for processed folders
set "TIMESTAMP=%DATE:~10,4%%DATE:~4,2%%DATE:~7,2%-%TIME:~0,2%.%TIME:~3,2%.%TIME:~6,2%.%TIME:~9,2%"
cd "%ProgramFiles(x86)%\Ipswitch\WS_FTP 12" || (
echo %TIMESTAMP% Error switching to ftp program directory>"E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.error.txt"
exit /b 1
)
md "E:\Processed_HL7_Vanderbilt\%1\%TIMESTAMP%" || (
echo %TIMESTAMP% Error creating archive directory>"E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.error.txt"
exit /b 1
)
:: If more than 0 files exist begin ftp and file archival otherwise exit
FOR %%i IN (c:\Encoded_HL7_Vanderbilt\*) DO (
set /a count+=1
REM I don't know the wsftppro command line parameters, pls. check the man page
wsftppro -s local:"%%~i" -d Vandy!Vanderbilt:/incoming/ || (
echo %TIMESTAMP% Error transmitting file to ftp server>"E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.error.txt"
exit /b 1
)
move "%%~i" "E:\Processed_HL7_Vanderbilt\%1\%TIMESTAMP%" || (
echo %TIMESTAMP% Error moving files to archive directory>"E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.error.txt"
exit /b 1
)
)
if %count% equ 0 (
rd "E:\Processed_HL7_Vanderbilt\%1\%TIMESTAMP%" 2>nul
exit /b 1
)
echo %TIMESTAMP% File transfer completed successfully>"E:\HL7_Vanderbilt_log\%1\%TIMESTAMP%.success.txt"

Resources