Bir hizmetin toplu iş dosyası aracılığıyla çalışıp çalışmadığını kontrol etmek ve çalışmıyorsa onu başlatmak nasıl?


92

Aşağıdaki işlemleri gerçekleştiren bir toplu iş dosyası yazmak istiyorum:

  • Bir hizmetin çalışıp çalışmadığını kontrol edin
    • Çalışıyorsa, partiden çıkın
    • Çalışmıyorsa servisi başlatın

Şu ana kadar Google'da araştırdığım kod örneklerinin çalışmadığı ortaya çıktı, bu yüzden onları göndermemeye karar verdim.

Bir hizmetin başlatılması şu şekilde yapılır:

net start "SERVICENAME"
  1. Bir hizmetin çalışıp çalışmadığını nasıl kontrol edebilirim ve bir toplu iş dosyasında nasıl if ifadesi oluşturabilirim?
  2. Biraz kafam karıştı. Net başlangıca aktarmam gereken argüman nedir? Hizmet adı mı yoksa görünen adı mı?

3
Kirli programlama: Yapmak istediğiniz tek şey, çalışmıyorsa servisi başlatmak olduğunda, sadece başlatma komutunu verin. Çalışmıyorsa servisi başlatacaktır. Çalışıyorsa bir hata mesajı alırsınız ancak hizmet çalışıyordur (ve durmuyordur). Kirli ama işe yarıyor. Bununla birlikte, yalnızca hizmeti başlatmanız gerektiğinde diğer yorumları yürütmek istediğinizde, o zaman kesinlikle lc'nin daha temiz sürümünü kullanın.
Peter Schuetze

@Peter Schuetze: Evet, hizmeti başlatmak tek amaçsa itirazınız doğrudur. Ayrıca loglama başlangıcı vb. Dahil ettim, bu yüzden lc'nin çözümüne sadık kaldım.
citronas

Yanıtlar:


165

Bir hizmetin durumunu kontrol etmek için kullanın sc query <SERVICE_NAME>. Toplu iş dosyalarındaki bloklar için belgelere bakın .

Aşağıdaki kod, hizmetin durumunu kontrol edecek MyServiceNameve çalışmıyorsa başlatacaktır (hizmet çalışmıyorsa if bloğu yürütülecektir):

for /F "tokens=3 delims=: " %%H in ('sc query "MyServiceName" ^| findstr "        STATE"') do (
  if /I "%%H" NEQ "RUNNING" (
   REM Put your code you want to execute here
   REM For example, the following line
   net start "MyServiceName"
  )
)

Ne yaptığının açıklaması:

  1. Hizmetin özelliklerini sorgular.
  2. "STATE" metnini içeren satırı arar
  3. Bu hattı jetonize eder ve hizmetin durumunu içeren 3. jetonu çıkarır.
  4. Ortaya çıkan durumu "ÇALIŞIYOR" dizesine göre test eder

İkinci sorunuza gelince, geçmek isteyeceğiniz bağımsız değişken görünen ad değil , net starthizmet adıdır.


Harika. Çaban için teşekkürler. Maalesef çalışmıyor mu? Belki bunun için çok aptalım. "MyServiceName" 'i test olarak "SCardSvr" (kaçtı) ile değiştirdim, her şeyi bir toplu iş dosyasına koydum, çalıştırdım, ancak hizmet başlamıyor. Net start'ı bir dosyaya yazdırma gibi başka bir şeyle değiştirsem bile, çalıştırılmayacaktır. İkinci kez bakar mısın lütfen? =)
citronas

Oops, orada ilk satırda fazladan bazı şeyler vardı ... Bunu dene. Ve işe yaramazsa, sc query "SCardSvr"bir komut satırından çalıştırdığınızda ne olur ?
lc.

1
Alıntılarda "SCardSvr" var mı? Olması gerektiğine inanmıyorum,
LittleBobbyTables - Au Revoir

@LittleBobbyTables: Haklısınız. Tırnak işaretleri olmadan işe yaradı. Ben çok aptalım: - | Yardımınız için teşekkürler
citronas

@ Mark İyi not alın. Sanırım bu dizeyi hedef işletim sistemi dili için olması gereken şeyle değiştirmeniz gerekecek. Ben de "ÇALIŞIYOR" varsayıyorum.
lc.

34

Bir hizmeti değiştirmek için aşağıdakileri kullanın;

NET START "Dağıtılmış İşlem Koordinatörü" || NET STOP "Dağıtılmış İşlem Koordinatörü"


1
Başlangıçtan itibaren çıkış kodu nedeniyle çalışır. Başlatma komutu başarısız olursa, muhtemelen zaten çalıştığı içindir (ve her iki durumda da daha sonra durdurmak zarar vermez), bu yüzden onu durdurmayı deneyin.
lc.

3
komut, net start başarısız olursa, onu durduracak (|| nedeniyle başka bir anlama gelir), ancak net start çalışıyorsa, net stop çalışmayacak şekilde yapılandırılmıştır. parlak!
Doctor DOS

1
Bence en iyi cevap bu ve belki @citronas bunu kabul edilen cevap olarak işaretlemelidir: basit, akıllı ve zarif ve StackOverflow gibi bir siteye uyuyor. Basitleştir!
Sopalajo de Arrierez

2
Nitekim değil (Tamam, belki birazcık), ama ||aslında bir ORoperatördür, ancak bu durumda işlevsel olarak bir ELSEifadedir. Bu ince ama önemli bir farktır. Hala + 1'im var - Bunu her zaman Unix / Linux kabuk komut dosyasıyla yapıyorum, bunu neden Windows toplu işinde yapmayı hiç düşünmediğimi bilmiyorum.
Doug R.

Bu, tehlikeli derecede basitleştirilmiş görünüyor. Bunu, toplu işleme için otomatikleştirdiğim veya kullanması için bir başkasına verdiğim bir şey için asla kullanmak istemem ... ama ihtiyacım olan bir hizmet için kendi masaüstüme koyabileceğim hızlı bir simge için doktorun sipariş ettiği şey bu ara sıra hızlıca geçiş yapın.
Joel Coehoorn

20

Bir hizmetin çalışıp çalışmadığını görmek için aşağıdaki komutu kullanabilirsiniz:

sc query [ServiceName] | findstr /i "STATE"

NOD32 Antivirüsüm için çalıştırdığımda şunu elde ederim:

STATE                       : 4 RUNNING

Durdurulsaydı, alırdım:

STATE                       : 1 STOPPED

NET START kullanıp kullanmadığınızı belirlemek için bunu bir değişkende kullanabilirsiniz.

Hizmet adı, görünen ad değil, hizmet adı olmalıdır.


1
Yardımınız için teşekkürler, gönderdiklerinizi bütünleştirmeye çalışırken, toplu becerilerimi çok geliştiriyorum;)
citronas

14

Bunu yapmalı:

FOR %%a IN (%Svcs%) DO (SC query %%a | FIND /i "RUNNING"
IF ERRORLEVEL 1 SC start %%a)

13

Dilden bağımsız versiyon.

@Echo Off
Set ServiceName=Jenkins


SC queryex "%ServiceName%"|Find "STATE"|Find /v "RUNNING">Nul&&(
    echo %ServiceName% not running 
    echo Start %ServiceName%

    Net start "%ServiceName%">nul||(
        Echo "%ServiceName%" wont start 
        exit /b 1
    )
    echo "%ServiceName%" started
    exit /b 0
)||(
    echo "%ServiceName%" working
    exit /b 0
)

Evet! "Uzay" her zaman aniden sırtınıza çarpar!
Dr.eel

2
Neredeyse mükemmel cevap. Bu satırı düzeltmek isterim: Net başlangıç ​​"% ServiceName%"> boş || (
Cesar,

Komut dosyasını evrensel yaptım, böylece Windows Zamanlayıcı görevlerinde kullanmama izin veriyor. Sadece yerini Set ServiceName=Jenkinsile Set ServiceName=%~1ve benzeri diyoruzwatch-service.bat "Jenkins"
Dr.eel

@ Ant_222 Dile bağlı olan 'sorgu' yerine 'queryex' kullanır. Ve neden bunun Windows grubu olmadığını düşünüyorsunuz? Kullanmayı denedin mi?
Dr.eel

Komut dosyanızda / v ne anlama geliyor? Belki de tüm bu komut dosyası komutlarına bağlantınız vardır?
FrenkyB

5

Bu konuyu yeni buldum ve kişi hizmetleri yeniden başlatmak için bir toplu iş dosyası kullanmak istemiyorsa tartışmaya eklemek istedim. Windows'ta Hizmetler'e, hizmet özelliklerine ve ardından kurtarmaya giderseniz bir seçenek vardır. Burada servis için parametreleri ayarlayabilirsiniz. Servis durursa servisi yeniden başlatmak gibi. Ayrıca, bilgisayarı yeniden başlatırken olduğu gibi ikinci bir başarısızlık girişiminde bile farklı bir şey yapabilirsiniz.


2
Bu yararlı bir cevaptır, ancak unutulmamalıdır ki, bu sadece servis çıkış (-1) ile durduğunda çalışacaktır. Hizmetten sorunsuz bir şekilde çıkılırsa (hata mesajıyla bile) Otomatik Kurtarma tetiklenmez. Ayrıca hizmet kullanıcı tarafından manuel olarak öldürülürse tetiklenmez.
Sanat Gertner

@sagelightning: Bu yolu denemek için yönetici erişimine ihtiyacımız var.
Kumar M

@ArtGertner - Bir hizmet sürecinin öldürülmesi (görev yöneticisi aracılığıyla) "kilitlenme" olarak yorumlanacak ve bir kurtarmayı tetikleyecektir.
Martin Ba

3

Cuando se, Windows en Español, el código debe quedar asi'yi kullanır (Windows İspanyolca'yı kullanırken kod:

for /F "tokens=3 delims=: " %%H in ('sc query MYSERVICE ^| findstr "        ESTADO"') do (
  if /I "%%H" NEQ "RUNNING" (
    REM Put your code you want to execute here
    REM For example, the following line
    net start MYSERVICE
  )
)

Reemplazar MYSERVICE con el nombre del servicio que se desea procesar. Puedes ver el nombre del servicio viendo las propiedades del servicio. (MYSERVICE'i işlenecek hizmetin adıyla değiştirin. Hizmetin adını hizmet özelliklerinde görebilirsiniz.)


11
Cevabınızı İngilizce yazarsanız her biri için daha iyi olacaktır.
j0k

2
Neden olumsuz oy kullandığından emin değilim. Bu önemli bir nokta ve mümkünse dizi karşılaştırmalarından kaçınmak için bir nedendir. Bu durumda, hedef Windows kurulumunun varsayılan diline bağlı olarak dizeyi değiştirmeniz gerekir.
lc.

2
@lc: Her dil için bir yanıt eklemek mantıklı olur mu? Belirli bir dil için hangi dizenin aranacağını söyleyen bir kaynağa başvurmak (veya dahil etmek) daha yararlı olabilir.
Mike Bailey

3

Windows sunucusu 2012 için aşağıdaki benim için çalıştı. Yalnızca "SERVICENAME" öğesini gerçek hizmet adıyla değiştirin:

@ECHO OFF
SET SvcName=SERVICENAME

SC QUERYEX "%SvcName%" | FIND "STATE" | FIND /v "RUNNING" > NUL && (
    ECHO %SvcName% is not running 
    ECHO START %SvcName%

    NET START "%SvcName%" > NUL || (
        ECHO "%SvcName%" wont start 
        EXIT /B 1
    )
    ECHO "%SvcName%" is started
    EXIT /B 0
) || (
    ECHO "%SvcName%" is running
    EXIT /B 0
)

2
@echo off

color 1F


@sc query >%COMPUTERNAME%_START.TXT


find /I "AcPrfMgrSvc" %COMPUTERNAME%_START.TXT >nul

IF ERRORLEVEL 0 EXIT

IF ERRORLEVEL 1 NET START "AcPrfMgrSvc"

1

Ayrıca, hizmetin bu şekilde başlatılması durumunda bir e-posta gönderilmesini istedim, bu yüzden @Ic koduna biraz eklendi, sadece birine yardım etmesi durumunda onu göndereceğimi düşündüm. SendMail'i kullandım ancak başka komut satırı seçenekleri var Bir Windows toplu iş dosyasından basit bir e-posta nasıl gönderilir?

set service=MyServiceName

for /F "tokens=3 delims=: " %%H in ('sc query %service% ^| findstr "        STATE"') do (
  if /I "%%H" NEQ "RUNNING" (

    net start %service%

    for /F "tokens=3 delims=: " %%H in ('sc query %service% ^| findstr "        STATE"') do (
      if /I "%%H" EQ "RUNNING" (
        SendMail /smtpserver localhost /to me@mydomain.com /from watchdog@mydomain.com /subject Service Autostart Notification /body Autostart on service %service% succeded.
      ) else (
        SendMail /smtpserver localhost /to me@mydomain.com /from watchdog@mydomain.com /subject Service Autostart Notification /body Autostart on service %service% failed.
      )
    )

  )
)

1

Powershell komut dosyası kullanarak Hizmetin Başlatılması. Bunu görev zamanlayıcıya bağlayabilir ve aralıklarla veya gerektiğinde tetikleyebilirsiniz. Bunu bir PS1 dosyası, yani PS1 uzantılı bir dosya olarak oluşturun ve ardından bu dosyanın görev zamanlayıcı tarafından tetiklenmesine izin verin.

Hizmeti durdurmaya başlamak için

görev zamanlayıcıda, sunucuda kullanıyorsanız, bunu bağımsız değişkenlerde kullanın

-noprofile -executionpolicy bypass -file "C: \ Service Restart Scripts \ StopService.PS1"

aynı şeyi cmd üzerinde çalıştırarak doğrulayın, eğer çalışırsa, görev zamanlayıcı üzerinde de çalışması gerekir

$Password = "Enter_Your_Password"
$UserAccount = "Enter_Your_AccountInfor"
$MachineName = "Enter_Your_Machine_Name"
$ServiceList = @("test.SocketService","test.WcfServices","testDesktopService","testService")
$PasswordSecure = $Password | ConvertTo-SecureString -AsPlainText -Force
$Credential = new-object -typename System.Management.Automation.PSCredential -argumentlist $UserAccount, $PasswordSecure 

$LogStartTime = Get-Date -Format "MM-dd-yyyy hh:mm:ss tt"
$FileDateTimeStamp = Get-Date -Format "MM-dd-yyyy_hh"
$LogFileName = "C:\Users\krakhil\Desktop\Powershell\Logs\StartService_$FileDateTimeStamp.txt" 


#code to start the service

"`n####################################################################" > $LogFileName
"####################################################################" >> $LogFileName
"######################  STARTING SERVICE  ##########################" >> $LogFileName

for($i=0;$i -le 3; $i++)
{
"`n`n" >> $LogFileName
$ServiceName = $ServiceList[$i]
"$LogStartTime => Service Name: $ServiceName" >> $LogFileName

Write-Output "`n####################################"
Write-Output "Starting Service - " $ServiceList[$i]

"$LogStartTime => Starting Service: $ServiceName" >> $LogFileName
Start-Service $ServiceList[$i]

$ServiceState = Get-Service | Where-Object {$_.Name -eq $ServiceList[$i]}

if($ServiceState.Status -eq "Running")
{
"$LogStartTime => Started Service Successfully: $ServiceName" >> $LogFileName
Write-Host "`n Service " $ServiceList[$i] " Started Successfully"
}
else
{
"$LogStartTime => Unable to Stop Service: $ServiceName" >> $LogFileName
Write-Output "`n Service didn't Start. Current State is - "
Write-Host $ServiceState.Status
}
}

#code to stop the service

"`n####################################################################" > $LogFileName
"####################################################################" >> $LogFileName
"######################  STOPPING SERVICE  ##########################" >> $LogFileName

for($i=0;$i -le 3; $i++)
{
"`n`n" >> $LogFileName
$ServiceName = $ServiceList[$i]
"$LogStartTime => Service Name: $ServiceName" >> $LogFileName

Write-Output "`n####################################"
Write-Output "Stopping Service - " $ServiceList[$i]

"$LogStartTime => Stopping Service: $ServiceName" >> $LogFileName
Stop-Service $ServiceList[$i]

$ServiceState = Get-Service | Where-Object {$_.Name -eq $ServiceList[$i]}

if($ServiceState.Status -eq "Stopped")
{
"$LogStartTime => Stopped Service Successfully: $ServiceName" >> $LogFileName
Write-Host "`n Service " $ServiceList[$i] " Stopped Successfully"
}
else
{
"$LogStartTime => Unable to Stop Service: $ServiceName" >> $LogFileName
Write-Output "`nService didn't Stop. Current State is - "
Write-Host $ServiceState.Status
}
}

0
@Echo off

Set ServiceName=wampapache64

SC queryex "%ServiceName%"|Find "STATE"|Find /v "RUNNING">Nul&&(

echo %ServiceName% not running
echo  

Net start "%ServiceName%"


    SC queryex "%ServiceName%"|Find "STATE"|Find /v "RUNNING">Nul&&(
        Echo "%ServiceName%" wont start
    )
        echo "%ServiceName%" started

)||(
    echo "%ServiceName%" was working and stopping
    echo  

    Net stop "%ServiceName%"

)


pause

0

@DanielSerrano'nun cevabıyla ilgili olarak, son zamanlarda sc.exekomutun, yani İspanyolca yerelleştirilmesiyle ısırıldım . Benim önerim, sayısal hizmet durumunu tutan çizgiyi ve jetonu saptamak ve onu yorumlamak, ki bu çok daha sağlam olmalı:

@echo off

rem TODO: change to the desired service name
set TARGET_SERVICE=w32time

set SERVICE_STATE=
rem Surgically target third line, as some locales (such as Spanish) translated the utility's output
for /F "skip=3 tokens=3" %%i in ('""%windir%\system32\sc.exe" query "%TARGET_SERVICE%" 2>nul"') do (
  if not defined SERVICE_STATE set SERVICE_STATE=%%i
)
rem Process result
if not defined SERVICE_STATE (
  echo ERROR: could not obtain service state!
) else (
  rem NOTE: values correspond to "SERVICE_STATUS.dwCurrentState"
  rem https://msdn.microsoft.com/en-us/library/windows/desktop/ms685996(v=vs.85).aspx
  if not %SERVICE_STATE%==4 (
    echo WARNING: service is not running
    rem TODO: perform desired operation
    rem net start "%TARGET_SERVICE%"
  ) else (
    echo INFORMATION: service is running
  )
)

Şunlarla test edildi:

  • Windows XP (32-bit) İngilizce
  • Windows 10 (32-bit) İspanyolca
  • Windows 10 (64-bit) İngilizce

0

Belki çok daha basit bir yol? Buradaki cevaplar listesine eklemeniz yeterli:

@for /f "tokens=1,* delims=: " %%a in ('sc queryex state=Inactive') do net start "%%b"
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.