안녕하세요.
chatGTP와 함께라면 마냥 쉬울 것만 같았는데,윈도우파워쉘스크립트를윈도우서비스로만들기클리앙 아니였습니다.
그래서 기록도 남기고 다른 분들에게 도움이 되었으면 하는 바람으로 글을 적습니다.
무엇을 하려 했는가?
원격에서 제가 관리해야 하는 컴퓨터가 갑자기 접속이 안되더라구요.
팀뷰어, VPN을 통한 RDP 등 모든 방법이 통하지 않았습니다.
현장에 계신 분에게 부탁하여 재시작하니 모든 문제가 해결되었습니다.
다음에 또 부탁드리기 죄송스러워 특정 IP로 PING을 주기적으로 보내고 연결이 한 시간 이상 동안 되지 않으면, 컴퓨터를 재시작 시켜봐야 겠다는 간단한 생각으로 시작했습니다.
왜 쉽지 않았는가?
python 스크립트를 만들고 그 python 스크립트를 서비스로 만들면 될 것 같았는데,
윈도우에서 python 설치부터가 Microsft Store 에서 하냐, Install 파일을 구해서 하냐, 글로벌 버젼으로 까냐 아니냐 혼란이 많았고...
스크립트에서 필요한 모듈도 설치해 주고 문제를 하나둘씩 다 해결했음에도 불구하고
pywin32라는 윈도우의 서비스와 연동시켜주는 패키지가 python 가장 최신 버젼과 오류가 있는지 이유모를 이유로 에러가납니다.
서비스 설치까지 했으나, start 하면 계속 에러나서 이 방법은 포기
Shell Script... 윈도우에서는 PowerShell Script로 하면 될 것 같아서 해보았는데,
PowerShell Script를 서비스로 하려니 보안 문제 때문에 또 안되더군요.
삽질 끝에 모든 방법을 찾아내었고, 이제 작동 합니다.
큰 흐름
1. PowerShell Script(.ps1 파일)를 작성하고
2. WinSW 라는 오픈소스 프로젝트의 exe파일을 다운로드 한 후
3. WinSW 설정 파일인 .xml을 간단하게 수정 후
4. WinWS 파일을 실행하여 서비스 설치, 서비스 작동, 서비스 중지, 서비스 삭제 등을 실행
자세한 사항
1 - PowerShell Script
Script를 작성하여 저장하는데, 서비스하라서 개인폴더에 저장하기 보다 c:\Tools 이런 식의 폴더를 하나 만들어 저장해줍니다.
C:\Tools\PingMonitorService\PingMonitor.ps1 이라는 이름으로 저장했다고 합시다.
아래는 스크립트의 내용입니다.
Param으로 IP, ServiceName 등을 받을 수 있습니다.
param( [string]$TargetIP = "111.255.255.0", # Target IP ADDRESS [string]$ServiceName = "myPingService", # Service Name [int]$CheckInterval = 300, # Ping every n seconds by default [int]$FailureThreshold = 3600, # Reboot after n seconds (60 minutes x 60 seconds) [int]$WarningThreshold = 2400, # Warning after n seconds (40 minutes x 60 seconds) [switch]$Verbose = $false)$FailureCount = 0$WarningShown = $falsefunction Add-Log { param ( [string]$Message, [string]$EventType = "Information" ) $EventID = switch ($EventType) { "Information" { 1000 } "Warning" { 1001 } "Error" { 1002 } default { 1000 } } Write-EventLog -LogName "Application" -Source "pingmoni" -EventID $EventID -EntryType $EventType -Message $Message}function Restart-Machine { Restart-Computer -Force}# Log service startAdd-Log "Ping Monitor Service started. Monitoring $TargetIP every $CheckInterval seconds." "Information"while ($true) { $pingResult = Test-Connection -ComputerName $TargetIP -Count 1 -TimeoutSeconds 5 -Quiet if ($pingResult) { $FailureCount = 0 $WarningShown = $false if ($Verbose) { Write-Host "Ping to $TargetIP successful." } } else { $FailureCount += $CheckInterval if ($Verbose) { Write-Host "Ping to $TargetIP failed. Failure count: $FailureCount seconds." } if ($FailureCount -ge $WarningThreshold -and !$WarningShown) { Add-Log "Ping to $TargetIP has failed for more than $([math]::Round($WarningThreshold / 60)) minutes." "Warning" $WarningShown = $true } if ($FailureCount -ge $FailureThreshold) { Add-Log "Ping to $TargetIP has failed for more than $([math]::Round($FailureThreshold / 60)) minutes. Rebooting machine." "Error" Restart-Machine } } Start-Sleep -Seconds $CheckInterval}
2 - WinSW
WinSW를 다운로드하고 C:\Tools\PingMonitorService\ 폴더 아래 WinWS.exe 파일을 넣은 후, 이름은 바꿔줍니다. pingMonitorService.exe 요렇네요.
- WinSW Github: https://github.com/winsw/winsw
- WinSW Download: https://github.com/winsw/winsw/releases/tag/v2.12.0
3 - WinSW Config XML
pingMonitorService.xml 파일을 같은 폴더 안에 만들어 줍니다.
다운로드 링크에서 보시면 sample xml이 있는데 service에 관련된 세부 사항들을 설정할 수 있게 해 줍니다.
서비스 디펜던시라던가 등등 말이죠.
XML파일 내용은 아래와 같이 넣으시면 됩니다.
---
<service>
<!-- ID of the service. It should be unique across the Windows system-->
<id>myPingMonitorService</id>
<!-- Display name of the service -->
<name>Ping Monitor Service</name>
<!-- Service description -->
<description>Description</description>
<executable>powershell</executable>
<!--
ServiceName: Must match with <id> value in this file for logs to appear in Event Viewer.
-->
<arguments>-ExecutionPolicy Bypass -File C:\Tools\PingMonitorService\PingMonitor.ps1 -ServiceName "myPingMonitorService"</arguments>
</service>
---
id 값이 arguments의 ServiceName 값과 같아야 로깅이 정상적으로 작동합니다.
ExecutionPolicy Bypass 저 플래그가 없어서 보안때문에 start할 때 fail하더군요.
저걸 넣으니 작동됩니다. 참 별거 아닌데 많은 시간을 잡아먹었습니다.
4 - 서비스 설치 및 실행
PowerShell을 admin 모드로 작동 시킵니다.
해당 폴더로 이동 후
cd C:\Tools\PingMonitorService\
아까 이름 바꾸기 한 winsw를 실행 시키는데 install 을 더해서 실행시킵니다.
pingMonitorService.exe install
성공했다는 메세지가 나와야 하구요.
이제부터는 Windows의 services 도구를 띄우시면 거기서 보여야 합니다. 거기서 확인하신 후 시작하셔도 되고,
pingMonitorService.exe start 명령어를 넣어서 작동시키셔도 됩니다.
StartUp은 Automatic (delayed)로 해두었구요.
보니 메모리는 14MB정도 잡아 먹네요.
시간을 줄여서 테스트 해보니 재시작 잘합니다.
응용하여 다른 서비스도 만들 수 있는데... 뭐 윈도우는 할게 있나 모르겠네요.
기타 몇몇가지 사항
Powershell이 기본으로 깔려 있는건 v5구 v7이 있습니다.
winget과 같은 명령어로 v7을 설치할 수 있고
v7은 윈도우즈에 종속된 것이 아니라 모든 플랫폼에서 사용가능하다고 합니다.
Windows Subsystem 에서 Bash Script를 작동 시켜도 디지만
PowerShell Script로 만들면 오히려 호환성 측면에서는 미래에 괜찮을 수도 있지 않을까 기대해 봅니다.
서비스가 아니라 task scheduler로 해결 가능하면 그걸로 먼저해 보십시요.