서비스가 배치 파일을 통해 실행 중인지 확인하고 실행 중이 아닌 경우 시작하는 방법은 무엇입니까?


90

다음 작업을 수행하는 배치 파일을 작성하고 싶습니다.

  • 서비스가 실행 중인지 확인
    • 실행 중이면 배치를 종료하십시오.
    • 실행 중이 아니면 서비스를 시작하십시오.

지금까지 검색 한 코드 샘플이 작동하지 않는 것으로 밝혀져 게시하지 않기로 결정했습니다.

서비스 시작은 다음을 통해 수행됩니다.

net start "SERVICENAME"
  1. 서비스가 실행 중인지 확인하고 배치 파일에서 if 문을 만드는 방법은 무엇입니까?
  2. 조금 혼란 스러워요. 넷 스타트에 전달해야하는 주장은 무엇입니까? 서비스 이름 또는 표시 이름?

3
더티 프로그래밍 : 서비스가 실행되고 있지 않으면 서비스를 시작하는 것이 유일한 방법 일 때 시작 명령을 실행하면됩니다. 실행 중이 아니면 서비스를 시작합니다. 실행 중이면 오류 메시지가 표시되지만 서비스는 실행 중이며 중지되지 않습니다. 더럽지 만 작동합니다. 그러나 서비스를 시작해야하는 경우에만 다른 주석을 실행하려면 반드시 lc의 클리너 버전을 사용하십시오.
Peter Schuetze

@Peter Schuetze : 예, 서비스를 시작하는 것이 유일한 목적이라면 이의가 맞습니다. 로깅 시작 등도 포함 시켰으므로 lc 솔루션을 고수했습니다.
citronas

답변:


163

서비스 상태를 확인하려면을 사용하십시오 sc query <SERVICE_NAME>. 배치 파일의 if 블록에 대해서는 문서를 확인하십시오 .

다음 코드는 서비스의 상태를 확인하고 MyServiceName실행 중이 아니면 시작합니다 (서비스가 실행 중이 아니면 if 블록이 실행 됨).

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

그것이하는 일에 대한 설명 :

  1. 서비스의 속성을 쿼리합니다.
  2. "STATE"텍스트가 포함 된 줄을 찾습니다.
  3. 해당 라인을 토큰 화하고 서비스 상태를 포함하는 세 번째 토큰을 꺼냅니다.
  4. 문자열 "RUNNING"에 대해 결과 상태를 테스트합니다.

두 번째 질문에 관해서는, 당신이 전달하려는 것 인수는 net start서비스 이름입니다 하지 표시 이름.


대박. 노력해 주셔서 감사합니다. 불행히도 작동하지 않습니까? 어쩌면 내가 너무 멍청 할 수도 있습니다. 테스트로 "MyServiceName"을 "SCardSvr"(이스케이프 됨)로 바꾸고 모든 것을 배치 파일에 넣고 실행했지만 서비스가 시작되지 않습니다. net start를 파일로 인쇄하는 것과 같이 다른 것으로 바꿔도 실행되지 않습니다. 다시 한번 봐주 시겠어요? =)
citronas

죄송합니다. 첫 번째 줄에 추가 항목이 있습니다. 작동하지 않으면 sc query "SCardSvr"명령 줄에서 실행하면 어떻게됩니까 ?
lc.

1
따옴표 안에 "SCardSvr"이 있습니까? 나는 그것이 있어야 생각하지 않는다
LittleBobbyTables을 - 오브 아에게

@LittleBobbyTables : 맞아요. 따옴표 없이는 작동했습니다. 나는 너무 멍청하다 :-| 당신의 도움을 주셔서 감사합니다
citronas

@Mark Good입니다. 해당 문자열을 대상 OS 언어에 필요한 것으로 바꿔야 할 것 같습니다. 나는 또한 "RUNNING"이라고 가정한다.
lc.

34

서비스를 전환하려면 다음을 사용하십시오.

NET START "분산 트랜잭션 코디네이터"|| NET STOP "분산 트랜잭션 코디네이터"


1
시작부터 종료 코드 때문에 작동합니다. 시작 명령이 실패하면 이미 실행 중이기 때문일 수 있습니다 (그리고 나중에 중지해도 문제가되지 않음). 따라서 중지 해보십시오.
lc.

3
명령은 net start가 실패하면 중지 (|는 다른 의미를 의미 함)하지만 net start가 실행되면 net stop이 실행되지 않도록 구성됩니다. 훌륭한!
Doctor DOS

1
이것은 내 의견으로는 가장 좋은 대답이며, 아마도 @citronas는 그것을 받아 들여진 대답으로 표시하는 것을 고려해야합니다 : 간단하고, 똑똑하고, 우아하며, StackOverflow와 같은 사이트에 적합합니다. 간단하게!
Sopalajo de Arrierez

2
간결하지는 않지만 (좋아요, 조금만) ||실제로 OR연산자입니다.이 경우에는 기능적으로ELSE설명입니다. 이것은 미묘하지만 중요한 차이점입니다. 여전히 +1을 얻었습니다. Unix / Linux 쉘 스크립팅에서 항상이 작업을 수행합니다. Windows 일괄 처리에서이 작업을 수행 할 생각이 없었던 이유를 모르겠습니다.
Doug R.

이것은 위험 할 정도로 지나치게 단순화 된 것 같습니다. 일괄 처리를 위해 자동화하거나 다른 사람에게 사용하도록 제공하는 작업에 사용하고 싶지는 않지만 의사가 필요한 서비스를 위해 내 데스크톱에 넣을 수있는 빠른 아이콘을 주문한 것입니다. 이따금 빠르게 전환합니다.
Joel Coehoorn

19

다음 명령을 사용하여 서비스가 실행 중인지 여부를 확인할 수 있습니다.

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

NOD32 Antivirus를 실행하면 다음과 같은 결과가 나타납니다.

STATE                       : 4 RUNNING

중지 된 경우 다음과 같이 표시됩니다.

STATE                       : 1 STOPPED

이를 변수에 사용하여 NET START를 사용할지 여부를 결정할 수 있습니다.

서비스 이름은 표시 이름이 아닌 서비스 이름이어야합니다.


1
도움을 주셔서 감사합니다. 게시 한 내용을 통합하는 동안 배치 기술을 크게 향상
시켰습니다


10

언어 독립적 버전.

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

네! "우주"는 항상 당신의 등에 갑자기 맞습니다!
Dr.eel

2
거의 완벽한 대답입니다. NET START "%의 ServiceName은의 %"> NUL || (: 난 그냥이 라인에 고정 것
세자르

스크립트를 범용으로 만들었으므로 Windows 스케줄러 작업에서 사용할 수 있습니다. 그냥 교체 Set ServiceName=JenkinsSet ServiceName=%~1와 같이 호출watch-service.bat "Jenkins"
Dr.eel

@ Ant_222 언어 의존적 인 'query'대신 'queryex'를 사용합니다. Windows 배치가 아니라고 생각하는 이유는 무엇입니까? 그것을 사용해 보셨습니까?
Dr.eel

5

방금이 스레드를 찾았고 사용자가 배치 파일을 사용하여 서비스를 다시 시작하지 않으려는 경우 토론에 추가하고 싶었습니다. Windows에는 서비스, 서비스 속성, 복구로 이동하는 옵션이 있습니다. 여기에서 서비스에 대한 매개 변수를 설정할 수 있습니다. 서비스가 중지되면 서비스를 다시 시작합니다. 또한 컴퓨터를 다시 시작할 때와 다른 작업을 두 번째 실패로 시도 할 수도 있습니다.


2
이는 유용한 답변이지만, 서비스가 exit (-1)로 중지 된 경우에만 작동한다는 점에 유의해야합니다. 서비스가 정상적으로 종료 된 경우 (오류 메시지 포함) 자동 복구가 트리거되지 않습니다. 또한 사용자가 서비스를 수동으로 종료 한 경우에도 트리거되지 않습니다.
Art Gertner

@sagelightning :이 방법을 시도하려면 관리자 액세스 권한이 필요합니다.
Kumar M

@ArtGertner-(작업 관리자를 통해) 서비스 프로세스를 죽이는 것은 "충돌"로 해석되고 복구를 트리거합니다.
Martin Ba

3

Cuando se는 Windows en Español, el código debe quedar asi를 사용합니다 (스페인어로 Windows를 사용하는 경우 코드는 다음과 같습니다).

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를 처리 할 서비스 이름으로 바꾸십시오. 서비스 속성에서 서비스 이름을 볼 수 있습니다.)


10
영어로 답을 쓰면 모든 사람에게 더 좋을 것입니다.
j0k

2
왜 반대표를 던 졌는지 모르겠습니다. 이것은 가능한 경우 문자열 비교를 피해야하는 중요한 점이자 이유입니다. 이 경우 대상 Windows 설치의 기본 언어에 따라 문자열을 변경해야합니다.
lc.

2
@lc : 각 언어에 대한 답변을 포함하는 것이 합리적입니까? 주어진 언어를 검색 할 문자열을 알려주는 리소스를 참조 (또는 포함)하는 것이 더 유용 할 수 있습니다.
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

아래 Windows Server 2012의 경우 저에게 효과적입니다. "SERVICENAME"만 실제 서비스 이름으로 바꿉니다.

@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

나는 또한 서비스가 이런 식으로 시작되면 이메일을 보내고 싶었으므로 @Ic 코드에 약간을 추가하여 누군가에게 도움이 될 경우 게시 할 것이라고 생각했습니다. SendMail을 사용했지만 다른 명령 줄 옵션이 있습니다 . 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

Powershell 스크립트를 사용하여 서비스를 시작합니다. 이를 작업 스케줄러에 연결하고 간격 또는 필요에 따라 트리거 할 수 있습니다. 이것을 PS1 파일, 즉 확장자가 PS1 인 파일로 생성 한 다음이 파일이 작업 스케줄러에서 트리거되도록합니다.

서비스 중지를 시작하려면

작업 스케줄러에서 서버에서 사용하는 경우 인수에 이것을 사용하십시오.

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

cmd에서 동일하게 실행하여 작동하는지 확인하십시오. 작업 스케줄러에서도 작동해야합니다.

$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의 답변과 관련하여 최근에 sc.exe명령의 현지화 , 즉 스페인어로 조금씩했습니다 . 내 제안은 수치 서비스 상태를 보유하는 라인과 토큰을 정확히 찾아서 해석하는 것입니다. 이는 훨씬 더 강력해야합니다.

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

테스트 대상 :

  • Windows XP (32 비트) 영어
  • Windows 10 (32 비트) 스페인어
  • Windows 10 (64 비트) 영어

0

훨씬 더 간단한 방법일까요? 여기에 답변 목록에 추가하기 만하면됩니다.

@for /f "tokens=1,* delims=: " %%a in ('sc queryex state=Inactive') do net start "%%b"
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.