Bagaimana cara memeriksa apakah layanan berjalan melalui file batch dan memulainya, jika tidak berjalan?


91

Saya ingin menulis file batch yang melakukan operasi berikut:

  • Periksa apakah layanan sedang berjalan
    • Jika sedang berjalan, keluar dari batch
    • Jika tidak berjalan, mulai layanan

Sampel kode yang saya cari di Google sejauh ini ternyata tidak berfungsi, jadi saya memutuskan untuk tidak mempostingnya.

Memulai layanan dilakukan oleh:

net start "SERVICENAME"
  1. Bagaimana saya bisa memeriksa apakah sebuah layanan sedang berjalan, dan bagaimana membuat pernyataan if di batchfile?
  2. Saya sedikit bingung. Apa argumen yang harus saya sampaikan ke net start? Nama layanan atau nama tampilannya?

3
Pemrograman kotor: ketika satu-satunya hal yang ingin Anda lakukan adalah memulai layanan jika tidak berjalan, cukup jalankan perintah start. Jika tidak berjalan itu akan memulai layanan. Jika berjalan dari Anda mendapatkan pesan kesalahan tetapi layanan sedang berjalan (dan tidak berhenti). Kotor tapi berhasil. Namun, jika Anda ingin menjalankan komentar lain hanya jika Anda harus memulai layanan, maka gunakan versi yang lebih bersih dari lc.
Peter Schuetze

@ Peter Schuetze: Ya, keberatan Anda benar jika memulai layanan adalah satu-satunya tujuan. Saya juga menyertakan logging mulai dan sebagainya, jadi saya tetap menggunakan solusi lc.
citronas

Jawaban:


164

Untuk memeriksa status layanan, gunakan sc query <SERVICE_NAME>. Untuk if memblokir dalam file batch, periksa dokumentasi .

Kode berikut akan memeriksa status layanan MyServiceNamedan memulainya jika tidak berjalan (blok if akan dijalankan jika layanan tidak berjalan):

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

Penjelasan tentang apa yang dilakukannya:

  1. Menanyakan properti layanan.
  2. Mencari baris yang berisi teks "STATE"
  3. Tokenisasi baris itu, dan mengeluarkan token ke-3, yang merupakan salah satu yang berisi status layanan.
  4. Menguji status yang dihasilkan terhadap string "RUNNING"

Adapun pertanyaan kedua Anda, argumen yang ingin Anda sampaikan net startadalah nama layanan, bukan nama tampilan.


Hebat. Terima kasih atas usahamu. Sayangnya tidak berhasil? Mungkin aku terlalu bodoh untuk ini. Saya mengganti "MyServiceName" dengan "SCardSvr" (lolos) sebagai pengujian, memasukkan semuanya ke dalam batchfile, menjalankannya, tetapi layanan tidak memulai. Bahkan jika saya mengganti net start dengan yang lain, seperti mencetak ke dalam file, itu tidak akan dijalankan. Maukah Anda melihat kedua kalinya? =)
citronas

Ups, saya punya beberapa barang ekstra di baris pertama di sana ... Coba ini. Dan jika tidak berhasil, apa yang terjadi saat Anda menjalankan sc query "SCardSvr"dari baris perintah?
lc.

1
Apakah Anda memiliki "SCardSvr" dalam tanda kutip? Saya tidak percaya itu seharusnya,
LittleBobbyTables - Au Revoir

@LittleBobbyTables: Anda benar. Tanpa tanda kutip membuatnya berhasil. Saya sangat bodoh: - | Terima kasih atas bantuan Anda
citronas

@Mark Baik untuk diperhatikan. Saya kira Anda harus mengganti string itu dengan apa pun yang diperlukan untuk bahasa OS target. Saya berasumsi "MENJALANKAN" juga.
lc.

34

Untuk beralih layanan gunakan yang berikut ini;

NET START "Koordinator Transaksi Terdistribusi" || NET STOP "Koordinator Transaksi Terdistribusi"


1
Ini berfungsi karena kode keluar dari awal. Jika perintah start gagal, itu mungkin karena sudah berjalan (dan menghentikannya setelah itu tidak akan merugikan), jadi Anda coba menghentikannya.
lc.

3
perintah ini disusun sedemikian rupa sehingga jika net start gagal, ia kemudian menghentikannya (karena || yang artinya lain), tetapi jika net start berjalan, maka net stop tidak dijalankan. cemerlang!
Dokter DOS

1
Ini adalah jawaban terbaik menurut saya, dan mungkin @citronas harus mempertimbangkan untuk menandainya sebagai jawaban yang diterima: sederhana, cerdas dan elegan, dan cocok untuk situs seperti StackOverflow. Sederhanakan!
Sopalajo de Arrierez

2
Tidak menjadi rewel (OK, mungkin hanya sedikit), tetapi ||sebenarnya adalah ORoperator, meskipun dalam hal ini secara fungsional merupakan ELSEpernyataan. Ini adalah perbedaan yang halus, tetapi penting. Masih mendapat +1 saya - Saya melakukan ini sepanjang waktu di skrip shell Unix / Linux, tidak tahu mengapa saya tidak pernah berpikir untuk melakukan ini di batch Windows.
Doug R.

Ini tampaknya terlalu disederhanakan dan berbahaya. Saya tidak pernah ingin menggunakannya untuk sesuatu yang saya otomatisasi untuk pemrosesan batch atau diberikan kepada orang lain untuk digunakan ... tetapi itu hanya yang diperintahkan dokter untuk ikon cepat yang dapat saya letakkan di desktop saya sendiri untuk layanan yang saya perlukan cepat beralih sekarang dan nanti.
Joel Coehoorn

20

Anda dapat menggunakan perintah berikut untuk melihat apakah layanan sedang berjalan atau tidak:

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

Ketika saya menjalankannya untuk NOD32 Antivirus saya, saya mendapatkan:

STATE                       : 4 RUNNING

Jika dihentikan, saya akan mendapatkan:

STATE                       : 1 STOPPED

Anda dapat menggunakan ini dalam variabel untuk kemudian menentukan apakah Anda menggunakan NET START atau tidak.

Nama layanan harus nama layanan, bukan nama tampilan.


1
Terima kasih atas bantuan Anda, saat mencoba mengintegrasikan apa yang Anda posting, saya meningkatkan keterampilan batch saya;)
citronas

14

Itu harus melakukannya:

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

12

Versi bahasa independen.

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

Ya! "Space" selalu muncul tiba-tiba di punggung Anda!
Dr.eel

2
Jawaban yang hampir sempurna. Saya hanya akan memperbaiki baris ini: Mulai bersih "% ServiceName%"> nul || (
Cesar

Saya telah membuat skrip universal sehingga memungkinkan saya untuk digunakan dalam tugas Penjadwal Windows. Cukup ganti Set ServiceName=Jenkinsdengan Set ServiceName=%~1dan sebut saja sepertiwatch-service.bat "Jenkins"
Dr.eel

@ Ant_222 Ini menggunakan 'queryex' bukan 'query' yang bergantung pada bahasa. Dan mengapa menurut Anda itu bukan batch Windows? Sudahkah Anda mencoba menggunakannya?
Dr.eel

5

Saya baru saja menemukan utas ini dan ingin menambahkan ke diskusi jika orang tersebut tidak ingin menggunakan file batch untuk memulai ulang layanan. Di Windows ada opsi jika Anda pergi ke Layanan, properti layanan, lalu pemulihan. Di sini Anda dapat mengatur parameter untuk layanan. Ingin memulai ulang layanan jika layanan berhenti. Selain itu, Anda bahkan dapat melakukan upaya gagal kedua untuk melakukan sesuatu yang berbeda seperti saat memulai ulang komputer.


2
Itu adalah jawaban yang berguna, namun penting untuk diperhatikan, itu hanya akan berfungsi jika layanan telah berhenti dengan exit (-1). Jika layanan keluar dengan anggun (bahkan dengan pesan kesalahan) Pemulihan Otomatis tidak akan memicu. Ini juga tidak akan memicu jika layanan dibunuh secara manual oleh pengguna.
Art Gertner

@sagelightning: Kami membutuhkan akses admin untuk mencoba cara ini.
Kumar M

@ArtGertner - Membunuh (melalui pengelola tugas) proses layanan akan diartikan sebagai "crash" dan akan memicu pemulihan.
Martin Ba

3

Gunakan Windows en Español, el código debe quedar asi (bila menggunakan Windows dalam bahasa Spanyol, kodenya adalah):

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. (Ganti MYSERVICE dengan nama layanan yang akan diproses. Anda dapat melihat nama layanan pada properti layanan.)


10
Akan lebih baik untuk setiap orang jika Anda menulis jawaban Anda dalam bahasa Inggris.
j0k

2
Tidak yakin mengapa suara negatifnya. Ini adalah poin penting dan alasan untuk menghindari perbandingan string jika memungkinkan. Dalam hal ini Anda harus mengubah string tergantung pada bahasa default dari instalasi Windows target.
lc.

2
@lc: Apakah masuk akal untuk menyertakan jawaban untuk setiap bahasa? Mungkin lebih berguna untuk mereferensikan (atau menyertakan) sumber daya yang mengatakan string apa yang akan dicari untuk bahasa tertentu.
Mike Bailey

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"

2

Untuk Windows server 2012 di bawah ini yang berhasil untuk saya. Ganti hanya "SERVICENAME" dengan nama layanan yang sebenarnya:

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

1

Saya juga ingin email dikirim jika layanan dimulai dengan cara ini jadi tambahkan sedikit ke kode @Ic hanya berpikir saya akan mempostingnya jika itu membantu siapa pun. Saya menggunakan SendMail tetapi ada opsi baris perintah lain Bagaimana cara mengirim email sederhana dari file batch Windows?

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

Memulai Layanan menggunakan skrip Powershell. Anda dapat menautkan ini ke penjadwal tugas dan memicunya pada interval atau sesuai kebutuhan. Buat ini sebagai file yaitu file PS1 dengan ekstensi PS1 dan kemudian biarkan file ini dipicu dari penjadwal tugas.

Untuk memulai menghentikan layanan

di penjadwal tugas jika Anda menggunakannya di server, gunakan ini dalam argumen

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

verifikasi dengan menjalankan yang sama pada cmd jika berhasil, itu harus bekerja pada penjadwal tugas juga

$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

Terkait jawaban oleh @DanielSerrano, saya baru-baru ini digigit oleh lokalisasi sc.exeperintahnya, yaitu dalam bahasa Spanyol. Proposal saya adalah untuk menunjukkan dengan tepat garis dan token yang memegang status layanan numerik dan menafsirkannya, yang seharusnya jauh lebih kuat:

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

Diuji dengan:

  • Windows XP (32-bit) Bahasa Inggris
  • Windows 10 (32-bit) Spanyol
  • Windows 10 (64-bit) Bahasa Inggris

0

Mungkin cara yang lebih sederhana? Hanya menambah daftar jawaban di sini:

@for /f "tokens=1,* delims=: " %%a in ('sc queryex state=Inactive') do net start "%%b"
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.