how to check the windows taks services through unix batch - windows

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

Related

Is there a way to run a batch of asynchronous commands a few at a time? [duplicate]

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.

How to wait all batch files to finish before exiting?

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.

Windows batch file for services

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%
)

Determine if Tomcat is running in Windows using the command prompt

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

How to test whether a service is running from the command line

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)

Resources