Windows PowerShell(PS1) 스크립트 작성 가이드

PowerShell이란?

PowerShell은 Microsoft가 개발한 객체 지향 셸 및 스크립팅 언어입니다. CMD의 텍스트 기반 출력과 달리, PowerShell은 .NET 객체를 파이프라인으로 전달합니다. 스크립트 파일 확장자는 .ps1이며, Windows 관리, CI/CD 자동화, 시스템 모니터링 등에 사용됩니다.

이 글에서는 PowerShell의 기본 문법, 변수, 함수, 파이프라인, 그리고 실전 자동화 스크립트까지 다룹니다.

BAT vs PowerShell 비교

항목BAT (CMD)PowerShell
출력 방식텍스트 문자열.NET 객체
변수%VAR%$VAR
파이프라인텍스트 전달객체 전달 (속성 접근 가능)
에러 처리%ERRORLEVEL%try/catch/finally
함수라벨 + gotofunction 키워드
모듈 시스템없음PowerShell Gallery
크로스 플랫폼Windows 전용Windows, macOS, Linux

기본 문법

PowerShell은 동사-명사 형태의 Cmdlet(커맨드렛)을 사용합니다. 변수는 $로 시작하며, 타입이 자동 추론됩니다.

# 출력
Write-Host "안녕하세요, PowerShell입니다!" -ForegroundColor Green

# 변수 선언 (타입 자동 추론)
$name = "PowerShell"
$version = 7.4
$today = Get-Date

Write-Host "이름: $name, 버전: $version"
Write-Host "오늘 날짜: $($today.ToString('yyyy-MM-dd HH:mm'))"

# 배열과 해시테이블
$fruits = @("사과", "바나나", "포도")
$config = @{
    Host   = "localhost"
    Port   = 8080
    Debug  = $true
}

Write-Host "첫 번째 과일: $($fruits[0])"  # 사과
Write-Host "포트: $($config.Port)"          # 8080

문자열 안에서 변수를 참조할 때 큰따옴표(")를 사용합니다. 작은따옴표(')는 변수를 해석하지 않고 그대로 출력합니다. 복잡한 표현식은 $()로 감쌉니다.

파이프라인과 객체

PowerShell의 가장 강력한 기능은 객체 파이프라인입니다. | 연산자로 Cmdlet을 연결하면, 텍스트가 아닌 객체가 전달되어 속성에 직접 접근할 수 있습니다.

# 프로세스 목록에서 메모리 사용량 상위 5개 조회
Get-Process |
    Sort-Object WorkingSet64 -Descending |
    Select-Object -First 5 Name, @{N='메모리(MB)'; E={[math]::Round($_.WorkingSet64/1MB, 1)}} |
    Format-Table -AutoSize
# 출력 예시:
# Name           메모리(MB)
# ----           ----------
# chrome            1024.3
# code               512.7
# explorer           256.1

# 특정 확장자 파일 검색 + 크기 합계
$totalSize = Get-ChildItem -Path "C:\Projects" -Recurse -Filter "*.log" |
    Measure-Object -Property Length -Sum
Write-Host "로그 파일 총 크기: $([math]::Round($totalSize.Sum/1MB, 2)) MB"

Get-Process는 프로세스 객체를 반환하고, Sort-ObjectWorkingSet64 속성으로 정렬합니다. BAT에서는 텍스트 파싱이 필요한 작업이 PowerShell에서는 속성 접근만으로 해결됩니다.

조건문, 반복문, 함수

PowerShell은 C# 계열 문법과 유사한 제어 구조를 제공합니다.

# === 조건문 ===
$score = 85

if ($score -ge 90) {
    Write-Host "A등급"
} elseif ($score -ge 80) {
    Write-Host "B등급"  # B등급
} else {
    Write-Host "C등급 이하"
}

# switch 문
$os = "Windows"
switch ($os) {
    "Windows" { Write-Host "Windows 감지" }
    "Linux"   { Write-Host "Linux 감지" }
    default   { Write-Host "알 수 없는 OS" }
}

# === 반복문 ===
# foreach: 배열 순회
$servers = @("web01", "web02", "db01")
foreach ($server in $servers) {
    Write-Host "서버 점검: $server"
}

# for: 숫자 범위
for ($i = 1; $i -le 5; $i++) {
    Write-Host "카운트: $i"
}

# === 함수 ===
function Get-DiskUsage {
    param(
        [string]$DriveLetter = "C"  # 기본값
    )
    $disk = Get-PSDrive -Name $DriveLetter
    $usedGB = [math]::Round($disk.Used / 1GB, 1)
    $freeGB = [math]::Round($disk.Free / 1GB, 1)
    return @{ Used = $usedGB; Free = $freeGB }
}

$usage = Get-DiskUsage -DriveLetter "C"
Write-Host "C: 사용 $($usage.Used)GB / 여유 $($usage.Free)GB"

비교 연산자는 -eq(같다), -ne(다르다), -gt(크다), -ge(크거나 같다), -lt(작다), -le(작거나 같다)를 사용합니다. BAT의 EQU/NEQ와 유사하지만 하이픈 접두사가 특징입니다.

PowerShell의미BAT 등가
-eq같다EQU
-ne다르다NEQ
-gt크다GTR
-ge크거나 같다GEQ
-lt작다LSS
-le작거나 같다LEQ
-like와일드카드 매칭없음
-match정규표현식 매칭없음

실전 스크립트: 서비스 모니터링

지정된 서비스의 상태를 점검하고, 중지된 서비스를 자동 재시작하는 스크립트입니다.

# service-monitor.ps1 — 서비스 상태 점검 및 자동 재시작
param(
    [string[]]$ServiceNames = @("W32Time", "Spooler"),
    [string]$LogPath = ".\service-monitor.log"
)

function Write-Log {
    param([string]$Message)
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $entry = "[$timestamp] $Message"
    Add-Content -Path $LogPath -Value $entry
    Write-Host $entry
}

Write-Log "=== 서비스 모니터링 시작 ==="

foreach ($svcName in $ServiceNames) {
    try {
        $service = Get-Service -Name $svcName -ErrorAction Stop

        if ($service.Status -eq "Running") {
            Write-Log "[OK] $svcName — 정상 실행 중"
        } else {
            Write-Log "[경고] $svcName — 상태: $($service.Status). 재시작 시도..."
            Start-Service -Name $svcName -ErrorAction Stop
            Write-Log "[복구] $svcName — 재시작 완료"
        }
    } catch {
        Write-Log "[오류] $svcName$($_.Exception.Message)"
    }
}

Write-Log "=== 모니터링 완료 ==="

try/catch로 에러를 처리하고, -ErrorAction Stop으로 비종료 에러도 catch 블록에서 잡을 수 있게 합니다. param() 블록으로 스크립트 매개변수를 정의하면 .\service-monitor.ps1 -ServiceNames "W32Time","Spooler"처럼 호출할 수 있습니다.

실행 정책 설정

PowerShell은 보안을 위해 기본적으로 스크립트 실행이 차단되어 있습니다. PS1 파일을 실행하려면 실행 정책을 변경해야 합니다.

# 현재 실행 정책 확인
Get-ExecutionPolicy
# Restricted (기본값 — 스크립트 실행 차단)

# 현재 사용자에 대해 스크립트 실행 허용
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
# RemoteSigned: 로컬 스크립트 허용, 원격 스크립트는 서명 필요
정책설명
Restricted스크립트 실행 차단 (기본값)
RemoteSigned로컬 스크립트 허용, 원격은 서명 필요 (권장)
Unrestricted모든 스크립트 허용 (비권장)
Bypass제한 없음, 경고 없음 (CI/CD용)

정리

PowerShell은 BAT의 한계를 넘어서는 강력한 자동화 도구입니다. 핵심 포인트를 정리하면 다음과 같습니다.

  • 객체 파이프라인이 핵심 — 텍스트 파싱 대신 .속성으로 데이터 접근
  • 변수는 $로 시작, 비교는 -eq/-ne/-gt 등 하이픈 접두사
  • try/catch/finally로 체계적 에러 처리
  • param() 블록으로 스크립트 매개변수 정의
  • 실행 전 Set-ExecutionPolicy RemoteSigned 설정 필수
  • PowerShell 7+는 Windows, macOS, Linux 크로스 플랫폼 지원

이 글이 도움이 되었나요?