Logic to identify errors logged - batch-file

How can I check for a particular text logged to a file in Win 10 ? There is a SAS daemon that fails occasionally and at which point logs a message to a log file (C:\SAS\logs\daemon_error.log). The message is logged (with timestamp) only when the error occurs. I want to write a program (and schedule to run every 15 mins) which would check the occurrence of any error-message since the last error recognized. For e.g. if the last error was logged on July 15th the file would have looked like :
07-15-2018 13:21:42 : Incorrect parameters
Now if some error gets logged again today, it would look like below, at which point the script should trigger and identify it and send an email to a list of intended recipients. I presume there needs to be a mechanism to store the last timestamp when the error was recognized so that it only identify errors logged after the last one.
07-15-2018 13:21:42 : Incorrect parameters
09-10-2018 04:32:09 : Temp directory full
How can I accomplish this thru a batch file or perhaps any windows event(s). I do not have much knowledge on Win systems as I primarily worked on Unix. Can anyone please help ?
Thanks

When I understood you correctly, you want to check for timestamp only to know, if there are new errors since the last check, but don't necessarily need to know, which errors. For that, I suggest using the "Archive attribute" (Windows sets this attribute at each write access to the file)
#echo off
:loop
timeout 900
dir /aa "C:\SAS\logs\daemon_error.log" >nul 2>&1 || goto :loop
echo The file was changed!
attrib -a "C:\SAS\logs\daemon_error.log"
goto :loop
The dir command will not find the file when the Archive attribute is not set (/aa) (or the file doesn't exist) and || goto :loop will then jump to the :loop label.
>nul 2>&1 will just discard any output of the dir command - we don't need it, just the errorlevel)
If the file was found (the Archive attribute is set, so we know, there was a write access), the code continues. Replace the echo command with the command to write an email (there are several questions/answers about that on SO).
attrib -a unsets the Archive attribute.
Note: Instead of the loop, I would set up a scheduled task, but keep with the loop for troubleshooting until you're sure, it works as intended.

Related

How do I use the if statement with WMIC

this is my first post. I am using a batch command to check if an instance of my program is already running based on its command line argument. I am able to see if it is running by using the following code:
wmic Path win32_process Where "CommandLine Like '%Account A%' AND Caption Like '%Leads Manager.exe%'"
If the process exists, I will get a full break down of the process information, but if the process isn't running i get No Instance(s) Available.
I want to be able to run an If statement, so if the result shows No Instance(s) Available. I want to run a command without displaying the process information and if it does exists, I want to echo Account A is already running
Hopefully someone with more experience can point me in the right direction
Here's a batch-file example, which may help you out:
#Echo Off
For %%A In (A B C D) Do WMIC Process Where^
"Name='Leads Manager.exe' And Not CommandLine Like '%%Account %A%%%'"^
Get Name 2>Nul|Find "Name">Nul && (
Start "" "C:\Leads Manager.exe" -- "C:\Account %%A.ini")
This example uses the outer For loop to choose the Account letters, it is therfore checking to see if Leads Manager.exe is running with a commandline containing the string Account A, Account B, Account C or Account D, and if not it should run Leads Manager specifying the path to the appropriate account. (Please note that your .exe and .ini file paths both contain spaces, so I have doublequoted them, but left the rest of the command as you wrote it in your comment. You may want to consider checking that what you provided was correct and adjust it as necessary before testing, or replace that line entirely with a simple Echo Is Not Running) || Echo Is Running) statement, or perhaps run another batch file instead).

Windows Pre-commit hook to get Log message on Subversion with Tortoise

I have SVN and Tortoise SVN installed in my machine. I have created a Batch file".bat". I am trying to get Log message to validate it that was provided in the UI before commit.
I tried this answer which was failing with following error.
svnlook: E720003: Can't open file 'C:\Users\GOPICH~1\AppData\Local\Temp\svnC891.tmp\format': The system cannot find the path specified.
Can anyone guide me what is the issue is (or) is there anyway to achieve the same.
I had issues with svnlook log as it appends the \format.
Arguments returned from stderr to the commit failed dialog are known as:
path depth messagefile cwd
These arguments are printed from using the code in this answer when commit fails.
The 1st and 3rd are .tmp files located in the temp directory. (The 1st is a list of files to commit).
The 3rd argument is the message file so you can use that to check if a message is used.
#echo off
findstr . "%~3" >nul
if errorlevel 1 echo args: %* >&2 & exit 1
exit 0
This causes commit failure if message file is empty else allows the commit to succeed.
Issues:
Only a single space in message file causes commit failure.
Only a double space in message file allows commit.
Seems findstr pattern could be improved. This could be a personal preference so keeping the linked answer pattern from the question.
Idea aschipfl shared in comments:
#echo off
if %~z3 gtr 0 (exit 0) else exit 1
Any character in message file makes the file not zero in size.
AFAIK, stdout is redirected as being a hook script, thus unavailable,
so #echo off is possibly not needed.
Note: Tested with SVN-client which may be why svnlook log
gave me strange results. Thanks to aschipfl for the information.

Batch - Execute a command IF program output critera is met

Sorry about the lousy title, I don't really know how to fit my question into a few words.
This may probably seem trivial to you guys, but I'm trying to automate a task that goes something like this:
Check if a certain executable exists
If it exists, run the executable, which has two possible outcomes:
Update found.
Update not found.
If outcome A, run a certain command. If outcome B, run another command.
The executable gives an output in the command line window, but I'm stranded on how to make the IF command read the output and use it.
English isn't my first language and my vocabulary regarding this is rather limited, so just let me know if something isn't clear.
if exist path\filename.ext anycommand checks, if a file exists and if yes, executes anycommand
anycommand >temp.txt writes the output of a command to a textfile.
set /p variable=<temp.txt writes the content of the textfile to a variable (well, at least the first line)
if "%variable%"=="Update not found" othercommand runs othercommand, if %variable% is equal to "Update not found"
Something along these lines might be what you're looking for: (This is an example, not the exact program)
set file_path=C:\Users\Atyai\Desktop\ExampleFile.bat
if exist %file_path% echo Update Found. && ::Then put your command right here
if not exist %file_path% echo Update Not Found. && ::Put your other command here
What this does, is when the file exists, it echoes "Update found" then I left some room for your second command. In the case that the file does not exist, it echoes "Update Not Found."
The file path I gave you (first line) needs to be replaced with your own.
This might provide some help:
http://ss64.com/nt/if.html

Input Error: There is no file extension

If this is a rookie mistake I apologize for wasting your time.
As part of a larger batch file to create a directory with today's date, copy and paste files to be backed up, change permissions and delete files older then X days I've run into a problem. Here's where it happens:
echo var D = new Date() > tmp.js
echo D = (D.getFullYear()*100+D.getMonth()+1)*100+D.getDate() >> tmp.js
echo WScript.Echo( 'set YYYYMMDD='+D ) >> tmp.js
echo #echo off > tmp.bat
cscript //nologo tmp.js >> tmp.bat
call tmp.bat
The command prompt spits back this error:
Input Error: There is no file extension in "C:\Users\name\Desktop\Error:".
So obviously the rest of the batch file fails but the weird thing is this works on one machine on the network but not the other.
Any help is greatly appreciated.
EDIT: there is one more line to that code that is returning the error, my mistake.
After I call tmp.bat:
mkdir "\\network\file\%YYYYMMDD%"
This code, as is, will not generate the indicated error
BUT, if the path to the batch file contains spaces, and the code is something like
cscript //nologo %~dp0\tmp.js
you will get the indicated error as the argument to cscript is incorrectly parsed because the space in the path to the js file. If this is the case (or something similar), quotes in the filename should solve it
cscript //nologo "%~dp0\tmp.js"
Also, the temporary batch file is not needed. Output from cscript can be directly read with the help of for command
set "tmpJS=%~dp0\tmp.js"
>"%tmpJS%" echo with(new Date()){WScript.StdOut.WriteLine(getFullYear()*10000+(getMonth()+1)*100+getDate())};
for /f %%D in ('cscript //nologo //B "%tmpJS%"') do set "YYYYMMDD=%%D"
Wow - that is a very convoluted way to get the current date in a variable.
This is not a direct answer to your question, but I think I can make your life much easier :-)
There really is no need for a temporary batch file. FOR /F could process the output of your temporary JS script directly.
But I have an even easier solution - GetTimeStamp.bat is a hybrid JScript/batch utility that can do nearly any date and time computation on a Windows machine.
The utility is pure script that will run on any modern Windows machine from XP forward - no 3rd party executable required.
Assuming getTimestamp.bat is in your current directory, or better yet, somewhere within your PATH, then the following simple call will define a YYYYMMDD variable containing today's date in YYYYMMDD format:
call getTimeStamp -f {yyyy}{mm}{dd} -r YYYYMMDD
There are a great many options for specifying the base date and time, many options for adding positive or negative offsets to the date and time, many options for formatting the result, and an option to capture the result in a variable. Both input and output can be directly expressed as local time, UTC, or any time zone of your choosing. Full documentation is embedded within the script.
Figured it out:
running cscript on tmp.js led to an error begin put into tmp.bat
call tmp.bat then returned the weird input error because of the error message inside of tmp.bat.
tmp.bat looked like this when editing
Cscript Error: Can't find script engine "JScript" for script "C:\Users\name\Desktop\tmp.js".
That's why calling tmp.bat returned this error message:
Input Error: There is no file extension in "C:\Users\name\Desktop\error:".
The problem ended up being with jscript.dll. It needed to be (re)registered.
regsvr32 %systemroot%\system32\jscript.dll
^Fixed my problem. Thank you all for the help.

extract from a file some data to have a specific process to them (in a batch)

I need to extract some data from a file to apply them a specific process. The file structure looks like this
some title information at file header
I001=send login information to the system
connection is OK
A001=System has answered: "you are connected"
I002=press the log out button
A002=system has answered: "You have been disconnected"
disconnection is OK
I003= timeout is 10
If timeout occurs, refresh view and then check if connection is come again
Else retry refreshment until you are connected to the system
My goal is to get I001,I002,I003,... to hold only on a line.
To do that, I write
more +1 %1 | findstr /v /r "^A...=.*"
But I get
I001=send login information to the system
connection is OK
I002=press the log out button
I003= timeout is 10
If timeout occurs, refresh view and then check if connection is come again.
Else retry refreshment until you are connected to the system
instead of
I001=send login information to the system
I002=press the log out button
I003= timeout is 10
On the other hand, Please Let me know how could I pass right away this result through a pipe to a vbs script which uses a file as parameter. When I use
findstr "I[0-9][0-9][0-9]" "%~1"|cscript myscript.vbs,
I get an error at line fsoObj.opentextfile(wscript.arguments(0),1).readall, with fsoObj=createobject("scripting.filesystemobject").
Thank you very much for your help
if you search for I + three numbers, simply use:
findstr "I[0-9][0-9][0-9]" "%~1"
.. no matter, what is before of after the expression, and more is also not needed.
I'm not 100% sure I understand you correctly, but if you just want the lines starting with I...=, then you could just do this:
type %1 | findstr /r "I...=.*"
Given your input, this would print...
I001=send login information to the system
I002=press the log out button
I003= timeout is 10
...which I think is what you want.
First, get rid of the /v option, it does exactly the opposite of what you want.
/V Print only lines that do NOT contain a match.
You're also looking for A at the beginning, but you want I, so change it to
more +1 %1 | findstr /r "^I...=.*"
Note: Your file text above is indented by 6 spaces. In that case use
more +1 %1 | findstr /r "I...=.*"
(without the ^, because it will only match lines that begin with an I, with no spaces before.)

Resources