BAT: Parse Output File For Error Handling - error-handling

I have a process that is kicked off by a scheduled batch file daily. I need to have error handling built in to restart the process if there is an error. All works great most days but I get a time out error once a month or so that is unavoidable. The process does not output an errorlevel to the bat file so I need to be able to parse the output file to determine if the process needs to restart.
I tried using the FOR /F function to pass the contents of line 12 as a variable to use in an IF statement but I have been unsuccessful. I can obviously skip to line 12 but then I am left dealing with the tokens of the remaining lines. Does anyone have any suggestions that I could try?
Output file when all is well:
(Line Numbers Added for Readability)
1 Pricing Script
2
3 ________________________________________________________________________
4
5 Retrieve Prices
6
7 Date of price file: 070912
8 Regular only
9 Connecting to server intdata.com
10 TCP/IP connection established
11
12 TySymb Interactive Data
+400 more lines
Output file when there is an error:
1 Pricing Script
2
3 ________________________________________________________________________
4
5 Retrieve Prices
6
7 Date of price file: 071012
8 Regular only
9 Connecting to server intdata.com
10 TCP/IP connection established
11 Time Out
12 General Time Out. The User ID and/or Password might be incorrect.

I would simply look for the error message in the output using FIND or FINDSTR. I wouldn't worry about the line number.
find "General Time Out. The User ID and/or Password might be incorrect." "yourFile.log" && (
echo Timeout occurred, you must put code here to restart
)
or
findstr /c:"General Time Out. The User ID and/or Password might be incorrect." "yourFile.log" && (
echo Timeout occurred, you must put code here to restart
)

This will test only line 12 of your file for a given string:
#echo off
for /f "skip=11 tokens=*" %%i in (your_log_filename) do (
echo %%i | find "General Time Out" >nul
goto check
)
:check
if errorlevel 1 (echo No Timeout occured!) else (echo Timeout occured)

Related

How to Rollback DB2 Ingest statement for malformed data

I have a Bash Shell Script that runs a DB2 sql file. The job of this sql file is to completely replace the contents of a database table with whatever are the contents of this sql file.
However, I also need that database table to have its contents preserved if errors are discovered in the ingested file. For example, supposing my table currently looks like this:
MY_TABLE
C1
C2
row0
15
27
row1
19
20
And supposing I have an input file that looks like this:
15,28
34,90
"a string that's obviously not supposed to be here"
54,23
If I run the script with this input file, the table should stay exactly the same as it was before, not using the contents of the file at all.
However, when I run my script, this isn't the behavior I observe: instead, the contents of MY_TABLE do get replaced with all of the valid rows of the input file so the new contents of the table become:
MY_TABLE
C1
C2
row0
15
28
row1
34
90
row2
54
23
In my script logic, I explicitly disable autocommit for the part of the script that ingests the file, and I only call commit after I've checked that the sql execution returned no errors; if it did cause errors, I call rollback instead. Nonetheless, the contents of the table get replaced when errors occur, as though the rollback command wasn't called at all, and a commit was called instead.
Where is the problem in my script?
script.ksh
SQL_FILE=/app/scripts/script.db2
LOG=/app/logs/script.log
# ...
# Boilerplate to setup the connection to the database server
# ...
# +c: autocommit off
# -v: echo commands
# -s: Stop if errors occur
# -p: Show prompt for interactivity (for debugging)
# -td#: use '#' as the statement delimiter in the file
db2 +c -s -v -td# -p < $SQL_FILE >> $LOG
if [ $? -gt 2 ];
then echo "An Error occurred; rolling back the data" >> $LOG
db2 "ROLLBACK" >> $LOG
exit 1
fi
# No errors, commit the changes
db2 "COMMIT" >> $LOG
script.db2
ingest from file '/app/temp/values.csv'
format delimited by ','
(
$C1 INTEGER EXTERNAL,
$C2 INTEGER EXTERNAL
)
restart new 'SCRIPT_JOB'
replace into DATA.MY_TABLE
(
C1,
C2
)
values
(
$C1,
$C2
)#
Adding as answer per OP's suggestion:
Per the db2 documentation for the ingest command It appears that the +c: autocommit off will not function:
Updates from the INGEST command are committed at the end of an ingest
operation. The INGEST command issues commits based on the commit_period
and commit_count configuration parameters. As a result of this, the
following do not affect the INGEST command: the CLP -c or +c options, which
normally affect whether the CLP automatically commits the NOT LOGGED
INITIALLY option on the CREATE TABLE statement
You probably want to set the warningcount 1 option, which will cause the command to terminate after the first error or warning. The default behaviour is to continue processing while ignoring all errors (warningcount 0).

Windows server 2008: schedule task to start at startup IF hour >= x

I am working on Windows server 2008 r2; I scheduled a task that starts each day at 10:00 and runs for 8 hours.
If the server is restarted AND time is between 10-18 THEN the task should start as soon as possible, otherwise it should not run.
If I set a trigger at startup it starts at any time.
If I set the option "run as soon as possible" and the server was not working at start time then the task is started when the server is up, if instead the task was already lauched "today" it is not restarted automatically.
So I ask your advice: is it possible to force the start of the task in the correct timeframe using just task scheduler? I'd rather avoid an approach based on "run anyway but TSKILL if time is not correct".
I don't think this ALL can be accomplished with just a scheduled task. You would need to create a scrip file and then schedule that. I added Day of week also because I think you might be looking for M-F (it can be removed if not needed)
REM skip if not Mon-Fri
for /f %%a in ('wmic path win32_localtime get dayofweek /format:list ^| findstr "="') do (set %%a)
IF %dayofweek% LSS 1 goto skip
IF %dayofweek% GTR 5 goto skip
REM skip if no 10am-6pm
IF %time:~0,2% LSS 10 goto skip
IF %time:~0,2% GTR 18 goto skip
echo pass
REM skip if already run today source:https://groups.google.com/forum/#!topic/alt.msdos.batch.nt/uIzJ-rmx3PA
set Semaphore=%temp%\Semaphore.bat
if not exist "%Semaphore%" goto notRunToday
call "%Semaphore%"
if "%lastrun%" equ "%date%" (
echo %~nx0 already ran once today.
goto skip)
:notRunToday
echo set lastrun=%date%>"%Semaphore%"
REM run the command
MyProgram.exe
:skip

Error testing and control from DOS

I'm running DOS 6.0.6002 on a windows server enterprise system, SP2.
SQL Server 2008 R2 (10.50.4000)
I have a main control program in DOS.
I'm invoking an sql program through sqlcmd.
A simplified version looks like this:
set sqlsvr=myServer
set logfile=logfile.txt
sqlcmd -S %sqlsvr% -d myDB -i import_some_stuff.sql > "%logfile%" 2>&1
echo error level = %ERRORLEVEL%
I need this program to be pretty robust. It has to run every day against a lot of files and tables. If it fails, I need to catch it and notify sysadmin. For now, just catch it.
So to test this, I've tried the following tests:
1) Renaming the file to one that does not exist.
Result: it returns and errorlevel of 1 (that is it caught the error!) bravo!
2) typing in some syntactical rubbish at the front of the sql program.
Result: it prints the error message in the log file, BUT it DOES NOT return an error (so the return value in %ERRORLEVEL% is zero. This seems incredible to me. What am I missing?
Try the -b option to sqlcmd:
-b
Specifies that sqlcmd exits and returns a DOS ERRORLEVEL value when an
error occurs.
The value that is returned to the DOS ERRORLEVEL
variable is 1 when the SQL Server error message has a severity level
greater than 10; otherwise, the value returned is 0. If the -V option
has been set in addition to -b, sqlcmd will not report an error if the
severity level is lower than the values set using -V. Command prompt
batch files can test the value of ERRORLEVEL and handle the error
appropriately. sqlcmd does not report errors for severity level 10
(informational messages).
If the sqlcmd script contains an incorrect comment, syntax error,
or is missing a scripting variable, ERRORLEVEL returned is 1.
Here is the documentation

I need to count how many .zip files in a folder and transfer to a variable. Then compare with successful 226 transfers in a txt log file

I found this site using a search which was a great help. I was able to modify part of a previous solution to do what I need but I still need some help. I need to do this in a batch file and was hoping to get a solution or two.
What I need to do is Transfer 1 to 10 zip files from my PC to multiple FTP Servers. I then need to check to make sure they are transferred successfully. On my PC I'm using regular MS FTP and the servers are using IndiFTPD. I have everything done except for the checking part. Some of the FTP Servers are Dial up and wireless and they get disconnected from time to time. So if I'm transferring say 3 files and the first one fails but the other two are successful my script lists it as successful.
I have was able to get a count of how many zip files are in the transfer folder and put it into a variable. The code for that is:
#echo off
for /f %%A in ('dir *.zip ^| find "File(s)"') do set cnt=%%A
echo Zip File count = %cnt%
What I'm having trouble with is getting the same information from the text log file of the FTP transfer and then comparing the two to make sure they are the same. Here is an example of a log of an FTP transfer I would make:
ftp> Connected to Host1.
open Host1 21
220 Connected to IndiFTPD
ftp> Username user
user1
331 Password required for Folder1.
230 User user1 logged in.
ftp> Hash mark printing On ftp: (2048 bytes/hash mark) .
ftp> hash
binary
200 Type is set to I.
ftp> mput *.zip
200 PORT command successful.
150 Opening BINARY mode data connection for 2012_07_01_03_40_1_3_TESTFTPs.zip.
###############################################################################################
226 [Bytes: 195046][Time: 1.13 s][Speed: 168.26 K/s]
ftp: 195046 bytes sent in Seconds Kbytes/sec.
0.78251.67200 PORT command successful.
150 Opening BINARY mode data connection for 2012_07_01_03_40_2_3_TESTFTPs.zip.
###############################################################################################
226 [Bytes: 195046][Time: 1.13 s][Speed: 168.41 K/s]
ftp: 195046 bytes sent in Seconds Kbytes/sec.
0.77253.31200 PORT command successful.
150 Opening BINARY mode data connection for 2012_07_01_03_40_3_3_TESTFTPs.zip.
###############################################################################################
226 [Bytes: 195046][Time: 1.14 s][Speed: 166.79 K/s]
ftp: 195046 bytes sent in Seconds Kbytes/sec.
ftp> 0.78249.42bye
221 Exit.
I would like to be able to use the %cnt% variable from the first part of the script to get the count of zip files I have. Then I would like to get able to count the number of "226 [Bytes" in the log file which is named terminal-ftp.txt. Then once I have both values in variable form I need to compare them to ensure I have 3 FTP files and 3 Successful 226 transfers. If they don't match then I would need to flag it up for a retry.
Get the 226 results:
for /f "usebackq tokens=3 delims=: " %%A in (`find /c "226 [Bytes" "terminal-ftp.txt"`) do set "xTTS=%%A"
echo Successful 226 Transfers = %xTTS%
Compare the results:
if "%xTTS%" EQU "%cnt%" echo The counts match
if "%xTTS%" NEQ "%cnt%" echo The counts do not match
For great Batch references:
command /?, Technet, Rob van de Woude, DosTips, and SS64

table==1 was unexpected at this time batch file

I am trying to apply multiple SQL scripts to an Ingres database (using a vnode setup). The testing phase will require it done to four databases. Trying to nip this annoyance in the bud I've started a batch file but receive the error above.
Many of the solutions found suggest that the batch file will evaluate everything within a block when it starts but I cannot see the forest for the trees. I have a suspicion that the parts in :1ST and :2ND are causing the problems but they need to be done.
SQL, Batch and command window output are below
UPDATE core SET sysflag='O'
#ECHO off
SET VN1=dave
SET DB1=dbtest1
SET DB2=dbtest2
SET SQL1=open.sql
SET SQL2=open.sql
:MENU
CLS
ECHO 1 - Leave
ECHO 2 - Database1
ECHO 3 - Database2
SET /P M=Choose then press ENTER:
IF "%M%"=="1" GOTO EOF
IF "%M%"=="2" GOTO 1ST
IF "%M%"=="3" GOTO 2ND
GOTO MENU
:1ST
SET DATABASE=%VN1%::%DB1%
GOTO RUNSQL
:2ND
SET DATABASE=%VN1%::%DB2%
GOTO RUNSQL
:RUNSQL
ECHO Applying SQLs to %DATABASE%
SQL %DATABASE% < %SQL1% > log_%SQL1%.txt
PAUSE
SQL %DATABASE% < %SQL2% > log_%SQL2%.txt
PAUSE
GOTO MENU
:EOF
C:\Users\me\BUILD>IF UPDATE core SET sysflag='O'==1 GOTO EOF
You are expecting the value of %M% to have 1, 2, or 3. But somehow the value is UPDATE core. The IF statement fails because there is a space in the middle of the left value. Token delimiters like space must be escaped, or the entire string on each side should be quoted. You could change your statement to IF "%M%"=="1" GOTO EOF to eliminate the error, but it still will not give the results you want.
The SET /P statement reads the value from stdin. I assume you have not typed the value UPDATE core, but instead your input was either redirected or piped. You are feeding your script the wrong value.
You should add error handling so that the code does not fall through to :1ST if the input is not 1, 2, or 3.
You can explicitly redirect input to the console for your SET /P statement. That way it will ignore the redirected input or piped input that was provided for the batch script.
<con: SET /P "M=Choose then press ENTER: "
But something seems wrong with your whole design. If you are piping or redirecting input for the script, then it doesn't make sense to present an interactive menu of choices in a loop. What happens if the user never presses 1 to quit? Eventually the piped or redirected input will be exhausted, and then you have problems.