Trapping errors using cmd.exe in SQL Server job - sql-server

I have a job that runs a batch file as step1. I edited the batch file ( mybatch.bat ) as follows:
call sub: >>mylog.txt
exit /b %ERRORLEVEL%
command1
command2
As you can see I forgot to add the sub. The job step is
cmd.exe mybatch.bat || echo %ERRORLEVEL% .
The job runs as successful and the history is as follows:
call :sub 1>>D:\Server_Directory\Logging\Cmd_Shell\SQL_APD_download.log The system cannot find the batch label specified - sub C:\Windows\system32>exit /b 1 0. Process Exit Code 0. The step succeeded.
How do I get SQL to fail the job, and not report Exit Code 0 ?

Related

Execution script bat using control-M

i have case regarding control-M.
I have simple script batch and plan execute using control-M job, below detail script :
1.MasterParam.bat
#echo
Set PathPackage=D:\test\
2.Main.bat
#echo off
Set PackageName=Package.dtsx
Call MasterParam.bat
Dtexec /f %PathPackage%%PackageName%
If %errorlevel% NEQ 0 ( exit /b %errorlevel%)
Question :
Can control-M execution script.bat with containing Call another scritp.bat?
wheter control-M stop the job if script.bat return errorlevel !=0?
In addition to the original answers, note that you can run Control-M jobs as direct commands (instead of executing .bat or .cmd files) which is often a better way to control the task (and works fine with dtexec /F ...).
If %errorlevel% NEQ 0 command means Not Equal to 0 and yes control-M can stop the job if script.bat return errorlevel !=0
By using Call MasterParam.bat or even by Call MasterParam
u can also pass parameters while calling the script -Calls one batch program from another without stopping the parent batch program. The call command accepts labels as the target of the call.

Network connection - batch file runs and adds my error message at end

I'm having an issue when I run a batch file. When the script successfully connects to the internet and runs, the failed message is still coming up. When I intentionally fail the script, I get a "network error 53". How do I check for this? I did not see any information on errorlevels besides:
"if errorlevel 1 goto failed:" and then create a failed message
Script runs successfully: Error message stills come up after everything runs properly. Meaning..my "failed: " message still occurs.
Network connection fails: ":failed" part runs as it should
#echo off
cls
ping XXXXXXX
#echo off
net use o: \\XXXXXXXXX
if errorlevel 1 goto failed:
#echo on
ping XXXXXXXXX
killdisk.exe -XXXXXX -XXXX
:failed
echo Unable to access the network share. Please confirm your Ethernet connection and try again.
echo Please press a key to exit or the prompt will exit after 30 seconds.
PAUSE 30
echo EXITING
To facilitate a variety of possible use cases, the Windows Command Prompt doesn't stop executing when it reaches a label (i.e. :failed).
In order to stop execution before the label, you can put one of the following commands before your label:
EXIT - This command closes the command prompt. If you call other batch files or subroutines within your batch, this is not what you want. The EXIT command will close the command prompt window and stop processing everything.
GOTO:EOF - The GOTO command generally takes a label such as your :failed, but in this case :EOF is a special reserved label that tells the command prompt to skip to the end of the current batch file. This would then return control to the batch file that called this one.
Further reading:
Exit - SS64
Goto - SS64

Why can't get exit code of batch file executed with command start?

When I run command Start C:\temp\sub2.bat in a command prompt window, errorlevel set is 4 and this is correct because a file which is indicated in batch does not exist. But when I run through this below, errorlevel returns 0. I have no idea why the exit codes are different.
Can anyone give me an advice for the reason?
#echo off
Call :Sub1
GOTO :EOF
:Sub1
start C:\temp\sub2.bat
echo %errorLevel%
Read the answer on How to call a batch file that is one level up from the current directory? It explains the 4 methods which exist to run a batch file from within a batch file and what are the differences.
You use command start which results in starting a new command process running parallel to the command process already executing your batch file for execution of C:\temp\sub2.bat.
The current command process immediately continues the execution of posted batch file and evaluates the exit code of command start which is 0 on successfully starting the executable or batch file.
You should use the command call to run the batch file as subroutine in your batch file and which makes it possible to evaluate the exit code set by C:\temp\sub2.bat.
#echo off
call C:\temp\sub2.bat
if errorlevel 1 echo There was an error with exit code %ERRORLEVEL%.
It would be also possible to start the other batch file in a new command process and what on its termination for example with exit 4 in current batch file.
#echo off
start /wait C:\temp\sub2.bat
if errorlevel 1 echo There was an error with exit code %ERRORLEVEL%.
In general it is not advisable to use exit without option /B as this results always in exiting the command process independent on calling hierarchy which makes it also impossible to debug a batch file by running it from within a command prompt window.
In case of C:\temp\sub2.bat really contains exit ExitCode without option /B and for some unknown reason the batch file can't be edited, it is really necessary to start C:\temp\sub2.bat in a separate command process and wait for its termination with start /wait.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
echo /?
exit /?
if /?
start /?
Read also the Microsoft support article Testing for a Specific Error Level in Batch Files.
See also the Stack Overflow questions:
What are the ERRORLEVEL values set by internal cmd.exe commands?
Which cmd.exe internal commands clear the ERRORLEVEL to 0 upon success?

I need my batch file to execute 3 files at the same time - wait for them to finish - then move on to send the email

Here's what I've got:
START 1_0.bat
START 1_0_1.bat
START 1_0_2.bat
START /w sendEmail -f blaahg#gmail.com -t blahg#gmail.com .....
Anyway,
I want it to simulataneously execute the first three items (which it is) then wait for all of them to complete - then execute the last email step. It's currently not waiting to execute the last step.
REM start the processes, giving them a "unique" title:
START "MyProcess1" 1_0.bat
START "MyProcess2" 1_0_1.bat
START "MyProcess3" 1_0_2.bat
:loop
timeout /t 1 >nul
REM check if a task with the "unique" title is still running:
tasklist /v|find "MyProcess">nul && goto :loop
echo all tasks have finished.
&& works as "if previous command (find) was successful, then...
Best to put these into another batch file like step1.bat
Step1.bat
START 1_0.bat
START 1_0_1.bat
START 1_0_2.bat
Then in your main have
START /wait step1.bat
START /w sendEmail -f blaahg#gmail.com -t blahg#gmail.com .....
You may use a file as flag to indicate that a given Batch file is running. Create a flag file for each running Batch file and remove it before each Batch file ends:
echo X > 1_0.flg
START 1_0.bat
echo X > 1_0_1.flg
START 1_0_1.bat
echo X > 1_0_2.flg
START 1_0_2.bat
rem Wait for all previous Batch files to end
:wait
if exist *.flg goto wait
START /w sendEmail -f blaahg#gmail.com -t blahg#gmail.com .....
And remove the flag file in each one of the Batch files this way:
del "%~N0.flg"
... or directly writing the name of each Batch file in the DEL command.
You may also insert a ping -n 2 localhost > NUL command in the :wait cycle in order to not spend too much CPU in the wait cycle. Increment the 2 value if you wish.

Can't run multiple batch files sequentially from master batch file in Win7

I have a bunch of batch files that each start a bunch of executables to run concurrently. Each batch file starts 30 executables. When those 30 are done, I want the next batch of executables to run, again 30 at a time. The .exe's are called using the "start" command in the batch files and they work just fine - I can run the individual batch files for each group of 30 exe's and they run concurrently like they should.
I have created a "master" batch file that calls each sub-batch file but I can't figure out how to get it to run the sub-batch files in sequence, waiting for one to finish before starting the next.
If the master batch file is like this:
Batch1.bat
Batch2.bat
Batch3.bat
then only the first batch file is called - the others are never called.
If the master batch file is like this:
call Batch1.bat
call Batch2.bat
call Batch3.bat
then all of the sub-batch files start running at the same time and I get hundreds of executables trying to start up at the same time.
How do I make the master batch file call the first batch file, wait for it to finish, then call the next, wait for it to finish, then call the next, etc?
Thanks in advance,
rgames
When starting another batch CALL will start it in the same window and the called batch has access to the same variable context. So it can also change variables which affects the caller.
Using wait in your batch file to call the executable will wait for them to exit before.
START /WAIT batch1.bat
START /WAIT batch2.bat
Hope this helps
Excuse me. I think there is a misunderstanding here. If your master Batch file is this:
call Batch1.bat
call Batch2.bat
call Batch3.bat
then the Batch2.bat is called after Batch1.bat ends, and so on. You may do a small test to confirm this. On the other side, is possible that each BatchN.bat program uses the same variables? If so, then the last values left from Batch1.bat may interfere with Batch2.bat, and so on. In this case, you must add a Setlocal command at beginning of each Batch file.
I had to run a data export program for several files. My solution:
MasterBatch.bat:
#echo off
start /w batch1.bat
start /w batch2.bat
Batch1.bat
#echo off
cmd /c "c: & cd Program Files (x86)/PATH & targetProgram.exe -parametersToExportVideo1"
EXIT
Batch2.bat
#echo off
cmd /c "c: & cd Program Files (x86)/PATH & targetProgram.exe -parametersToExportVideo2"
EXIT
It may be adapted to run programs other problems.
You will have to create a signaling mechanism to aware EXE completation.
I would create a third level batch to run each EXE, creating a temp file before executing EXE and deleting it after.
In sub-batch I would wait until there were no more temp files.
So, initial batch:
call Batch1.bat
call Batch2.bat
call Batch3.bat
Sub-batch:
Set Index=0
Call :Exec exefile1 args ...
Call :Exec exefile2 args ...
...
:WaitAll
If Exist %Temp%\RUNNING_EXE.*.TMP GoTo :WaitAll
GoTo :EOF
:Exec
Set /A Index+=1
Echo %Index% > %Temp%\RUNNING_EXE.%Index%.TMP
Start Batch_3rd.BAT %*
GoTo :EOF
Finally, 3rd level batch, Batch_3rd.BAT:
%*
Del %Temp%\RUNNING_EXE.%Index%.TMP
%* are arguments passed from sub-batch (exe+arguments), %Index% is correct as start copies environment from sub-batch upon creation, and sub-batch don't change this copy.
One final note: you can probably merge all batches into a single batch file, calling it recursively.
My solution:
1)
I have four batch files:
Parent.bat and Batch1.bat, Batch2.bat, Batch3.bat
2)
Parent.bat contains the below lines (take a close note):
call Batch1.bat > result1.log
call Batch2.bat > result2.log
call Batch3.bat > result3.log
3)
Make sure "into the end of Each Child batch file", you have an echo statement.
After this echo statement there shouldn't be any code...
Say content of Batch1.bat file is:
echo begin
robocopy "C:\Users\DD\Documents\A" "C:\Users\DD\Documents\B"
echo end
echo this_is_the_last_line
Just for testing, i will use simple sub-batches like (all of them are the same)
#echo off
for /l %%a in (1 1 5) do start "" notepad.exe
And a master batch file
#echo off
setlocal enableextensions disabledelayedexpansion
set "flagFile=%temp%\%random%%random%%random%.tmp"
for %%a in ( "batch1.cmd" "batch2.cmd" "batch3.cmd" ) do (
call :startBatch %%a "%flagFile%"
)
:retryClean
echo %time% waiting for last batch to end
2>nul ( 9>"%flagFile%" break ) || ( >nul timeout 5 & goto :retryClean )
del /q "%flagFile%"
echo DONE
pause
goto :eof
:startBatch batchFile flagFile
echo %time% waiting to start "%~1"
2>nul ( 9>"%~2" call "%~1" ) || ( >nul timeout 5 & goto :startBatch )
echo %time% [ "%~1" ] STARTED
goto :eof
This code starts each of the sub-batches with an active redirection (user available stream 9 is used) to a temporary flag file. This will lock the flag file until all the processes started from sub-batches have ended as the redirection is inherited during the process creation.
All we have to do is to keep trying start the next batch file with the same redirection:
If the file is still locked (processes are running), the batch file can not be started, wait 5 seconds and retry again
If the file is not locked, the redirection can be created and the next batch file is started.

Resources