내 배치 파일이 실행 중인지 어떻게 알 수 있나요?

내 배치 파일이 실행 중인지 어떻게 알 수 있나요?

AT 명령으로 실행되는 배치 스크립트가 있는데 두 번 이상 실행될 수 있습니다. 시작되면 이미 실행 중인지 감지하고, 그렇다면 (두 번째 항목) 즉시 종료해야 합니다.

  1. 견고해야 하며 스크립트가 예기치 않게 종료되는 경우를 처리해야 합니다(즉, 진입 시 플래그를 설정하고 종료 시 지울 수 없습니다).
  2. 원격 데스크톱 세션에서 실행되어야 합니다.
  3. XP에서 Powershell v2를 사용하고 있는데 배치/Powershell 또는 VBS에서 할 수 없다면 약간의 exe를 작성해도 괜찮습니다.
  4. 스크립트는 최소화된 상태로 실행되어야 하므로 Start "NAME" /MIN %COMSPEC% /C "MyScript.bat"로 시작합니다.
  5. 다른 cmd 창이 열려 있을 수 있으므로 실행 중인 스크립트를 확인해야 합니다.
  6. 배치 스크립트는 SYSTEM 사용자로 실행되지만 WMI를 사용할 수 없습니다.

MainWindowTitle을 보기 위해 PowerShell Get-Process를 사용하고 있었지만 스크립트가 실행 중일 수 있지만 이 원격 연결 인스턴스에 표시되지 않기 때문에 컴퓨터에 원격 연결할 때 작동하지 않았습니다. 이 경우 Get-Process에서 cmd 프로세스를 볼 수 있지만 MainWindowTitle은 비어 있습니다.

Get-Process를 시도하고 확장된 StartInfo.EnvironmentVariables 속성을 살펴봤지만 속성에 표시되도록 env var를 만드는 방법을 알 수 없습니다.

시작 명령에 /WAIT를 사용하려고 했는데 AT가 끝날 때까지 열려 있지만 AT가 포함된 스크립트가 최소화되지 않습니다.

어떤 아이디어가 있나요?

답변1

저는 잠금 파일이 가장 간단하고 신뢰할 수 있는 솔루션이라고 생각합니다. 비결은 실행 중인 일괄 처리 프로세스가 종료될 때까지 파일에 대한 단독 쓰기 잠금을 유지하는지 확인하는 것입니다. 이 시스템의 장점은 배치가 종료되는 이유에 관계없이 Windows가 잠금을 해제한다는 것입니다.

잠금 파일이 있으면 해당 파일이 현재 잠겨 있는지 감지할 수 있는 방법이 필요합니다. 이 작업을 수행하는 방법을 설명합니다.특정 파일이나 디렉터리가 잠겨 있는 경우(모든 프로세스에서 사용) 명령줄에서 어떻게 확인하나요?

저는 이 원시적이면서도 효과적인 기술을 사용하여 Windows 배치로 상당히 정교한 작업을 수행했습니다.

배치 파일이 원격 시스템에 있는지, 로컬 시스템에 있는지, 또는 여러 시스템에서 동시에 스크립트를 실행하고 있지만 시스템당 하나의 활성 프로세스만 있는지 명확하지 않습니다.

배치 스크립트가 원격 시스템에 있고 프로세스에 스크립트에 대한 쓰기 권한이 있는 경우 배치 파일 자체를 잠금 파일로 사용할 수 있습니다! 추가 모드를 사용하여 사용되지 않는 파일 핸들을 배치 스크립트로 리디렉션하는 동안 :subroutine을 호출하기만 하면 됩니다. 다른 프로세스에 이미 잠금이 있으면 CALL이 실패합니다. 잠금은 스크립트가 종료되면 자동으로 해제됩니다(종료 방법에 관계없이).

myscript.bat

@echo off
:: Note - this extra call is to avoid a bug with %~f0 when the script
::        is executed with quotes around the script name.
call :getLock
exit /b

:getLock
:: The CALL will fail if another process already has a write lock on the script
call :main 9>>"%~f0"
exit /b

:main
:: Body of your script goes here. Only one process can ever get here
:: at a time. The lock will be released upon return from this routine,
:: or when the script terminates for any reason
exit /b

스크립트가 프로세스와 다른 시스템에 있지만 한 번에 하나의 시스템에서만 프로세스가 실행되는 경우 위의 방법이 여전히 작동할 것이라고 생각합니다.

아마도 더 나은 대안은 배치 스크립트와 별도로 각 원격 시스템에 전용 잠금 파일을 설정하는 것입니다. 그런 다음 원하는 만큼 많은 원격 시스템에서 프로세스를 실행할 수 있습니다.

답변2

도와 주셔서 감사합니다. 나는 다음을 구현했습니다.

Before starting my script (in a wrapper script), check whether the lockfile exists:
  If it does, read the PID out of it.
    If the PID is still a running cmd process, exit my script as another version of it is already running.
    If the PID is not still a running cmd process, delete the lockfile
  Start the script, and create a new lockfile, containing the PID of the started script

When exiting my script, delete the lockfile

정상적으로 작동하는 것 같습니다. 추가 테스트를 통해 알 수 있습니다.

  1. 실행 중인 프로세스를 나열하려면 TASKLIST가 WMI를 사용하기 때문에 POWERSHELL Get-Process를 사용합니다. 앞서 언급했듯이 WMI는 사용할 수 없습니다.
  2. 시작된 스크립트의 PID를 확인하기 위해 현재 cmd PID를 모두 나열하고 스크립트를 시작한 다음 모든 cmd PID를 나열하여 이전에 없었던 PID를 찾습니다.

답변3

여기에서 사용할 수 있는 CMDS라는 자동화된 플러그인을 만들었습니다.특정 배치 파일이 실행 중인지 확인하고 PID를 얻으려면 어떻게 해야 합니까?그러나 이것이 XP에서 작동할지는 확실하지 않습니다.

예제 명령:CMDS /TS "Your Batch File Title"

또한 자체적으로 사용할 수 있는 GUI 모드도 있습니다.

도움말 파일은 다음과 같습니다.

도움말 메시지

관련 정보