So, this file is supposed to check the status of 2 services and start them if they are found to be not running. It works well for the first service but how do I make it work for more than one services? Also, I want to be able to perform status check after it's started. Please let me know your thoughts.
net start | find "spooler" > nul 2>&1
if not .%errorlevel%.==.0. goto spoolersvc
goto nextSvc
:nextSvc
net start | find "BITS" > nul 2>&1
if not .%errorlevel%.==.0. goto BITSsvc
goto quit
:spoolersvc
net start "spooler"
echo spooler Service restarted at %TIME::=-% on %DATE:/=-% >> C:\scripts\isa\logs\spooler.log
echo
:BITSsvc
net start "BITS"
echo Microsoft BITS Service restarted at %TIME::=-% on %DATE:/=-% >> C:\scripts\isa\logs\BITS.log
echo
:quit
exit
What you want is a batch file subroutine using call. Once you call a subroutine you can jump to the end of the file and the batch fill will pickup right where it left off. With this you can write a batch file that allows you to monitor and start any number of services.
set LOG_FILE=C:\scripts\isa\logs\spooler.log
call :CheckService spooler
call :CheckService BITS
goto :EOF
:CheckService
set SERVICE_NAME=%1
net start | find "%SERVICE_NAME%" > nul 2>&1
if not .%errorlevel%.==.0. goto :EOF
net start "%SERVICE_NAME%"
echo %SERVICE_NAME% Service restarted at %TIME::=-% on %DATE:/=-% >> %LOG_FILE%
net start | find "%SERVICE_NAME%" > nul 2>&1
if .%errorlevel%.==.0. (
%SERVICE_NAME% Service started successfully at %TIME::=-% on %DATE:/=-% >> %LOG_FILE%
) else (
%SERVICE_NAME% Service failed to start at %TIME::=-% on %DATE:/=-% >> %LOG_FILE%
)
Related
I have a main batch file than calls 4 other batch files so we can run in parallel.
Example:
Main.bat
start call batch1.bat
start call batch2.bat
start call batch3.bat
start call batch4.bat
exit
I want the Main.bat to exit after all the batch1 to batch 4 has stopped executing. In this way, I can get the total run time of the batch file. Problem is Main.bat exits even before batch1 to batch4 finishes executing.
I tried to compute for %errorlevel% for each batch file, but it always return 0 even though the 4 .bat files are still running.
Hoping someone could help me!
Thank you! :)
I think this is the simplest and most efficient way:
#echo off
echo %time%
(
start call batch1.bat
start call batch2.bat
start call batch3.bat
start call batch4.bat
) | set /P "="
echo %time%
In this method the waiting state in the main file is event driven, so it does not consume any CPU time!
EDIT: Some explanations added
The set /P command would terminate when anyone of the commands in the ( block ) outputs a line, but start commands don't show any line in this cmd.exe. This way, set /P keeps waiting for input until all processes started by start commands ends. At that point the pipe line associated to the ( block ) is closed, so the set /P Stdin is closed and set /P command is terminated by the OS.
give a unique title string to the new processes, then check if any processes with this string in the title are running:
start "+++batch+++" batch1.bat
start "+++batch+++" batch2.bat
start "+++batch+++" batch3.bat
start "+++batch+++" batch4.bat
:loop
timeout /t 1 >nul
tasklist /fi "windowtitle eq +++batch+++*" |find "cmd.exe" >nul && goto :loop
echo all tasks finished
(find is used, because tasklist does not return a helpful errorlevel)
Give this a try.
#echo off
echo %time%
start "" /wait cmd /c bat1.bat |start "" /wait cmd /c bat2.bat |start "" /wait cmd /c bat3.bat
echo %time%
pause
You could have batch1..batchn4 create flag files when they finish running.
e.g echo y > flag1 in batch1.bat
Then in the main batch file check for the existence of the flag files before exiting. You would need some sort of sleep utility to do something like this at the end of the main batch file:
IF EXIST flag1 GOTO check2
sleep <for a short amount of time>
goto check1
:check2
IF EXIST flag2 GOTO check3
sleep <for a short amount of time>
goto check2
:check3
IF EXIST flag3 GOTO check4
sleep <for a short amount of time>
goto check3
:check4
IF EXIST flag4 GOTO xit
sleep <for a short amount of time>
goto check4
:xit
The downside of this technique is that your timing is going to be off a little because you're polling for the flag files instead of being event driven. This may or may not be a problem in your situation. Batch files are pretty limited in this way. You might be better off trying to do it in PowerShell or python or some other more capable scripting language.
No one mentioned this solution, which I find to be the best. Put this at the end of your script, modify your process name if needed and the search strings.
This includes modifications necessary to have this work remotely too which was a headache. Originally I used tasklist instead of WMIC and checked named window titles defined when START is called, but windowName is N/A in tasklist when using it remotely. The powershell command worked better than timeout in our circumstances, which required us to run from this from a Jenkins agent.
:WAIT_FOR_FINISH
ECHO Waiting...
powershell -command "Start-Sleep -Milliseconds 5000" > nul
WMIC PROCESS WHERE Name="cmd.exe" GET commandline | findstr "searchString1 searchString 2" > nul && goto :WAIT_FOR_FINISH
ECHO.
ECHO Processes are Complete!
ECHO.
I am trying to create a batch file that will sort 7 windows services into a list then check one by one if they're running, and if they aren't, start them.
What I have doesn't seem to be wokring and seems to echo set i=o. I am trying to find out how to properly execute the two for loops and if anybody has any suggestions for syntax that would be awesome
I was able to create a very primitive version but wanted to learn more about batch file "programming". This is what I've come up with so far:
::Enter in CC number
set /p CC=Enter The Site's CC:
#echo off
setlocal EnableDelayedExpansion
::Create vector with names of services
set i=0
for %%s in
("Apache Tomcat"
"OracleServicePD"
"OracleXETNSListener_bqw"
"System Audit Service"
"RPOS ScemComms Service"
"RPOS debit credit service"
"RPOS Remote Device Service"
"RPOS Messaging Service"
) do (
set /A i=i+1
set services[!i!]=%%s
)
::Check if all services are running, if not go to it's respective net start method
::After all is checked, it goes to :check to show services are running
set n=0
:loop
for /L %%G in (0,1,7) do (
net start | find !services[%n%]! > nul 2>&1
if not "%errorlevel%"=="0"
set pathname=!services[%n%]!
set /A n=n+1
goto %pathname%
)
goto check
:"Apache Tomcat"
net start tomcat6
goto loop
:"OracleServicePD"
net start "OracleServicePD%CC%"
goto loop
:"OracleXETNSListener_bqw"
net start "OracleXETNSListener_bqw"
goto loop
:"System Audit Service"
net start "System Audit Service"
goto loop
:"RPOS ScemComms Service"
net start "RPOS ScemComms Service"
goto loop
:"RPOS debit credit service"
net start "RPOS debit credit service"
goto loop
:"RPOS Remote Device Service"
net start "RPOS Remote Device Service"
goto loop
:"RPOS Messaging Service"
net start "RPOS Messaging Service"
goto loop
:check
echo Apache Tomcat && sc query tomcat6 | find "STATE"
echo OracleServicePD%CC% && sc query "OracleServicePD%CC%" | find "STATE"
echo OracleXETNSListener_bqw && sc query "OracleXETNSListener_bqw" | find "STATE"
echo System Audit Service && sc query "System Audit Service" | find "STATE"
echo RPOS ScemComms Service && sc query "RPOS ScemComms Service" | find "STATE"
echo RPOS debit credit service && sc query "RPOS debit credit service" | find "STATE"
echo RPOS Remote Device Service && sc query "RPOS Remote Device Service" | find "STATE"
echo RPOS Messaging Service && sc query "RPOS Messaging Service" | find "STATE"
first, your first service is services[1], but your loop starts with 0.
more importantly, where does %n% come from? you mean %%G here.
sc start AeLookupSvc&&echo Started||(sc start AeLookupSvc|Findstr /c:"1056"&&Echo Already Running||Echo Error starting service)
Your pattern of testing then doing is not a good programming technique. You do and test if it worked.
The above does one service and reports if already running, if it was started, or what error prevents it starting. All in one line.
From MSDos 6.22 Help File.
│The following list shows each exit code and a brief description of its
│meaning:
│
│0
│ The search was completed successfully and at least one match was found.
│
│1
│ The search was completed successfully, but no matches were found.
│
│2
│ The search was not completed successfully. In this case, an error
│ occurred during the search, and FIND cannot report whether any matches
│ were found.
│
│You can use the ERRORLEVEL parameter on the command line in a batch
│program to process exit codes returned by FIND.
A list of command line things.
& seperates commands on a line.
&& executes this command only if previous command's errorlevel is 0.
|| (not used above) executes this command only if previous command's errorlevel is NOT 0
> output to a file
>> append output to a file
< input from a file
| output of one command into the input of another command
^ escapes any of the above, including itself, if needed to be passed to a program
" parameters with spaces must be enclosed in quotes
+ used with copy to concatinate files. E.G. copy file1+file2 newfile
, used with copy to indicate missing parameters. This updates the files modified date. E.G. copy /b file1,,
%variablename% a inbuilt or user set environmental variable
!variablename! a user set environmental variable expanded at execution time, turned with SelLocal EnableDelayedExpansion command
%<number> (%1) the nth command line parameter passed to a batch file. %0 is the batchfile's name.
%* (%*) the entire command line.
%<a letter> or %%<a letter> (%A or %%A) the variable in a for loop. Single % sign at command prompt and double % sign in a batch file.
.
Daily I am checking windows services by manualy (start -> run ->services.msc).
But i want to automat it through scripts.
How can I check the status (started or stopped) of the particular window service (eg.tomcat) using UNIX script(.bat)?
You can use sc query or net start to do this.
For eg.
#echo off
sc query "ServiceName" | findstr RUNNING
if %ERRORLEVEL% == 0 goto working
echo Not Running
:working
echo Running
goto end
:end
or
#echo off
net start | findstr "ServiceName"
if %ERRORLEVEL% == 0 goto working
echo Not Running
goto end
:working
echo Running
:end
Quite simply, how does one determine whether or not Tomcat is running in Windows, using the command prompt?
I am writing a batch script that must do this. This is the Bash version:
RESULT=`netstat -na | grep $2 | awk '{print $7}' | wc -l`
Where $2 is the port.
I am looking for something similar to that. Using Cygwin is out of the question, of necessity this script must be able to run on machines that only have Tomcat.
Test the status of the Tomcat Service with the SC command. MJB already suggested to test the service status with SC, yet another batch script (without FOR loop) for testing the status:
#ECHO OFF
SC query tomcat5 | FIND "STATE" | FIND "RUNNING" > NUL
IF ERRORLEVEL 1 (
ECHO Stopped
) ELSE (
ECHO Running
)
If you are not sure if the service name is tomcat5 you can list all service names with
SC query state= all | FIND "SERVICE_NAME"
You could use tasklist to check if the tomcat executable is running. For example:
#echo off
tasklist /FI "IMAGENAME eq tomcat.exe" | find /C /I ".exe" > NUL
if %errorlevel%==0 goto :running
echo tomcat is not running
goto :eof
:running
echo tomcat is running
:eof
It is also possible to check a remove server using the options /S, /U and /P. See tasklist /? for details.
Using WMIC
#echo off
wmic process list brief | find /i "tomcat.exe"
set result=%ERRORLEVEL%
if "%result%"=="1" echo "not running"
if "%result%"=="0" echo "running"
note : /i is to make the find operation case-insensitive.
This is the Windows version of the netstat based UNIX/LINUX solution asked in the question:
#echo off
netstat -na | find "LISTENING" | find /C /I ":8080" > NUL
if %errorlevel%==0 goto :running
echo tomcat is not running
goto :eof
:running
echo tomcat is running
:eof
Well, I am not very good with scripts but perhaps you could use this as a starting point:
netstat -a -n | findstr :8005
To get if someone is listening in port 8005. That is Tomcat's default port for remote administration, i.e. startup or shutdown.
Alternatively you could use the port that the http server listens to.
Hope this helps
use netstat -a in command prompt.
You'll find 8080 port listed there.
If you run Tomcat for Windows not like a service and don't want to exploit JMX the best way is
for /F %%I in ('tasklist /FI "WINDOWTITLE eq Tomcat" /NH') do if %%I==java.exe goto alreadyRun
where:
Tomcat - the window title of the Tomcat's terminal window by default
java.exe - the name of the Tomcat's processe. NOT tomcat.exe.
Yet another option, since this is probably running as a service
FOR /F "tokens=4 delims= " %%A IN ('SC QUERY tomcat5 ^| FIND "STATE"') DO SET status=%%A
echo "%status%"
status can be things like STOPPED, RUNNING ...
I check it by calling a vb script from command line
cscript //nologo checkurl.vbs | findstr "200"
IF errorlevel 1 GOTO :not_running
Save the below script as checkurl.vbs and replace the ip with machines ip
' Create an HTTP object
myURL = "http://10.1.1.1:8080/"
Set objHTTP = CreateObject( "WinHttp.WinHttpRequest.5.1" )
' Download the specified URL
objHTTP.Open "GET", myURL, False
On Error Resume Next
objHTTP.Send
intStatus = objHTTP.Status
If intStatus = 200 Then
WScript.Echo intStatus
Else
WScript.Echo "Error Connecting"
End If
I had problems with using sc query command, because even if tomcat crashed, the service would still be shown as running where in actual the port was not accessible
You can try searching for the process and extracting the line
For example:
ps|grep tomcat
I would like to be able to query whether or not a service is running from a windows batch file. I know I can use:
sc query "ServiceName"
but, this dumps out some text. What I really want is for it to set the errorlevel environment variable so that I can take action on that.
Do you know a simple way I can do this?
UPDATE
Thanks for the answers so far. I'm worried the solutions that parse the text may not work on non English operating systems. Does anybody know a way around this, or am I going to have to bite the bullet and write a console program to get this right.
sc query "ServiceName" | find "RUNNING"
Let's go back to the old school of batch programing on windows
net start | find "Service Name"
This will work everywhere...
if you don't mind to combine the net command with grep you can use the following script.
#echo off
net start | grep -x "Service"
if %ERRORLEVEL% == 2 goto trouble
if %ERRORLEVEL% == 1 goto stopped
if %ERRORLEVEL% == 0 goto started
echo unknown status
goto end
:trouble
echo trouble
goto end
:started
echo started
goto end
:stopped
echo stopped
goto end
:end
You could use wmic with the /locale option
call wmic /locale:ms_409 service where (name="wsearch") get state /value | findstr State=Running
if %ErrorLevel% EQU 0 (
echo Running
) else (
echo Not running
)
Thinking a little bit outside the box here I'm going to propose that powershell may be an answer on up-to-date XP/2003 machines and certainly on Vista/2008 and newer (instead of .bat/.cmd). Anyone who has some Perl in their background should feel at-home pretty quickly.
$serviceName = "ServiceName";
$serviceStatus = (get-service "$serviceName").Status;
if ($serviceStatus -eq "Running") {
echo "Service is Running";
}
else {
#Could be Stopped, Stopping, Paused, or even Starting...
echo "Service is $serviceStatus";
}
Another way, if you have significant investment in batch is to run the PS script as a one-liner, returning an exit code.
#ECHO off
SET PS=powershell -nologo -command
%PS% "& {if((get-service SvcName).Status -eq 'Running'){exit 1}}"
ECHO.%ERRORLEVEL%
Running as a one-liner also gets around the default PS code signing policy at the expense of messiness. To put the PS commands in a .ps1 file and run like powershell myCode.ps1 you may find signing your powershell scripts is neccessary to run them in an automated way (depends on your environment). See http://www.hanselman.com/blog/SigningPowerShellScripts.aspx for details
#ECHO OFF
REM testing at cmd : sc query "MSSQLSERVER" | findstr RUNNING
REM "MSSQLSERVER" is the name of Service for sample
sc query "MSSQLSERVER" %1 | findstr RUNNING
if %ERRORLEVEL% == 2 goto trouble
if %ERRORLEVEL% == 1 goto stopped
if %ERRORLEVEL% == 0 goto started
echo unknown status
goto end
:trouble
echo Oh noooo.. trouble mas bro
goto end
:started
echo "SQL Server (MSSQLSERVER)" is started
goto end
:stopped
echo "SQL Server (MSSQLSERVER)" is stopped
echo Starting service
net start "MSSQLSERVER"
goto end
:erro
echo Error please check your command.. mas bro
goto end
:end
I would suggest
WMIC Service WHERE "Name = 'SericeName'" GET Started
or WMIC Service WHERE "Name = 'ServiceName'" GET ProcessId (ProcessId will be zero if service isn't started)
You can set the error level based on whether the former returns "TRUE" or the latter returns nonzero
sc query "servicename" | findstr STATE
for example:
sc query "wuauserv" | findstr STATE
To report what the Windows update service is doing, running/paused etc.This is also for Windows 10. Thank me later.
Try
sc query state= all
for a list of services and whether they are running or not.
I've found this:
sc query "ServiceName" | findstr RUNNING
seems to do roughly the right thing. But, I'm worried that's not generalized enough to work on non-english operating systems.
Just to add on to the list if you are using Powershell.
sc.exe query "ServiceName" | findstr RUNNING
The command below does not work because sc is an alias to Set-Content within Powershell.
sc query "ServiceName" | findstr RUNNING
find also does not work on Powershell for some reason unknown to me.
sc.exe query "ServiceName" | find RUNNING
SERVICO.BAT
#echo off
echo Servico: %1
if "%1"=="" goto erro
sc query %1 | findstr RUNNING
if %ERRORLEVEL% == 2 goto trouble
if %ERRORLEVEL% == 1 goto stopped
if %ERRORLEVEL% == 0 goto started
echo unknown status
goto end
:trouble
echo trouble
goto end
:started
echo started
goto end
:stopped
echo stopped
goto end
:erro
echo sintaxe: servico NOMESERVICO
goto end
:end
I noticed no one mentioned the use of regular expressions when using find/findstr-based Answers. That can be problematic for similarly named services.
Lets say you have two services, CDPUserSvc and CDPUserSvc_54530
If you use most of the find/findstr-based Answers here so far, you'll get false-positives for CDPUserSvc queries when only CDPUserSvc_54530 is running.
The /r and /c switches for findstr can help us handle that use-case, as well as the special character that indicates the end of the line, $
This query will only verify the running of the CDPUserSvc service and ignore CDPUserSvc_54530
sc query|findstr /r /c:"CDPUserSvc$"
Use Cygwin Bash with:
sc query "SomeService" |grep -qo RUNNING && echo "SomeService is running." || echo "SomeService is not running!"
(Make sure you have sc.exe in your PATH.)
I have created one based from above but will show if the service is installed first then get whether it is running or not.
sc query "YourService" | find /i "failed" 2>&1>nul && echo.'YourService Not Installed' || (sc query "YourService"| find /i "running" 2>&1>nul && echo.Yes || echo.No)