티스토리 뷰

반응형

Windows 작업 스케줄러 + PowerShell로 주간 유지보수 자동화

임시파일·휴지통 정리, 폴더 백업(robocopy), 설치 앱 목록 백업(winget/레지스트리), 로그 기록까지 일괄 자동화합니다. 스크립트 전체 복사와 스케줄러 한 줄 명령 복사를 지원합니다.

주간 유지보수를 자동화하면 매주 몇 분으로 안정성과 속도를 확보할 수 있습니다. 아래 스크립트는 TEMP/휴지통 정리, 폴더 백업(robocopy), 앱 목록 백업(winget/레지스트리), 로그 기록을 한 번에 처리합니다.

참고: 에디터 환경에 따라 코드 블록 복사가 제한될 수 있어, 복사 버튼은 **숨김 원본 텍스트**에서 직접 복사합니다.

 

1) PowerShell 스크립트

C:\Scripts\weekly_maintenance.ps1로 저장하세요. 필요 시 경로·옵션을 수정합니다.

# weekly_maintenance.ps1
$ErrorActionPreference = 'SilentlyContinue'
$Host.UI.RawUI.WindowTitle = "Weekly Maintenance"

# === 사용자 설정 =================================================
$LogDir = Join-Path $HOME "MaintenanceLogs"
$BackupJobs = @(
  @{ Source = Join-Path $HOME "Documents"; Dest = "D:\Backups\Documents" },
  @{ Source = Join-Path $HOME "Pictures";  Dest = "D:\Backups\Pictures"  }
)
$IncludeSystemTemp = $false
$CreateRestorePoint = $false
$ResetThumbCache   = $false

# === 준비 =======================================================
if (-not (Test-Path $LogDir)) { New-Item -Path $LogDir -ItemType Directory | Out-Null }
$TimeStamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$LogPath   = Join-Path $LogDir "weekly_$TimeStamp.log"
$TransPath = Join-Path $LogDir "trans_$TimeStamp.txt"

Function Write-Log($msg){ $line = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')  $msg"; $line | Tee-Object -FilePath $LogPath -Append }
Function Get-FreeBytes($drive='C'){ try { (Get-PSDrive -Name $drive).Free } catch { 0 } }

Start-Transcript -Path $TransPath -Append -ErrorAction SilentlyContinue | Out-Null

Function Clear-Temp{
  Write-Log "[Temp] 사용자 TEMP 정리 시작"
  $userTemp = $env:TEMP
  if (Test-Path $userTemp){
    Get-ChildItem -Path $userTemp -Force -Recurse -ErrorAction SilentlyContinue | Remove-Item -Force -Recurse -ErrorAction SilentlyContinue
    Write-Log "[Temp] 사용자 TEMP 정리 완료: $userTemp"
  } else { Write-Log "[Temp] 사용자 TEMP 폴더 없음: $userTemp" }
  if ($IncludeSystemTemp){
    $sysTemp = "C:\Windows\Temp"
    Write-Log "[Temp] 시스템 TEMP 정리 시도: $sysTemp"
    if (Test-Path $sysTemp){
      Get-ChildItem -Path $sysTemp -Force -Recurse -ErrorAction SilentlyContinue | Remove-Item -Force -Recurse -ErrorAction SilentlyContinue
      Write-Log "[Temp] 시스템 TEMP 정리 완료"
    } else { Write-Log "[Temp] 시스템 TEMP 폴더 없음: $sysTemp" }
  }
}

Function Clear-Bin{
  try{
    Write-Log "[Bin] 휴지통 비우기"
    Clear-RecycleBin -Force -Confirm:$false -ErrorAction SilentlyContinue | Out-Null
  } catch { Write-Log "[Bin] 오류: $($_.Exception.Message)" }
}

Function Run-Backups{
  foreach ($job in $BackupJobs){
    $src=$job.Source; $dst=$job.Dest
    if (-not (Test-Path $src)){ Write-Log "[Backup] 원본 없음: $src"; continue }
    if (-not (Test-Path $dst)){ New-Item -Path $dst -ItemType Directory -Force | Out-Null }
    Write-Log "[Backup] 시작: `"$src`" → `"$dst`" (MIR)"
    robocopy $src $dst /MIR /R:2 /W:2 /FFT /XJ /XD ".cache" "node_modules" "temp" "tmp" /NFL /NDL /NP /LOG+:$LogPath | Out-Null
    Write-Log "[Backup] 완료"
  }
}

Function Backup-Apps{
  $appsJson = Join-Path $LogDir "apps_$TimeStamp.json"
  if (Get-Command winget -ErrorAction SilentlyContinue){
    Write-Log "[Apps] winget export"
    winget export -o $appsJson --accept-source-agreements --accept-package-agreements | Out-Null
  } else {
    Write-Log "[Apps] 레지스트리로 대체 수집"
    $keys = @(
      "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*",
      "HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*",
      "HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*"
    )
    $apps = foreach ($k in $keys){
      Get-ItemProperty $k -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName } |
        Select-Object DisplayName, DisplayVersion, Publisher
    }
    $apps | Sort-Object DisplayName | ConvertTo-Json -Depth 3 | Set-Content -Path $appsJson -Encoding UTF8
  }
  Write-Log "[Apps] 저장: $appsJson"
}

Function Make-RestorePoint{
  if ($CreateRestorePoint){
    try{
      Write-Log "[RP] 복원 지점 생성"
      Checkpoint-Computer -Description "WeeklyMaintenance $(Get-Date -Format 'yyyy-MM-dd')" -RestorePointType "MODIFY_SETTINGS"
    } catch { Write-Log "[RP] 실패: $($_.Exception.Message)" }
  }
}

Function Reset-ThumbCache{
  if ($ResetThumbCache){
    try{
      Write-Log "[Thumb] 캐시 초기화"
      Stop-Process -Name "explorer" -Force -ErrorAction SilentlyContinue
      $thumbPath = Join-Path $env:LOCALAPPDATA "Microsoft\Windows\Explorer"
      Get-ChildItem $thumbPath -Filter "thumbcache*.db" -Force -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue
      Start-Process "explorer.exe"
    } catch { Write-Log "[Thumb] 실패: $($_.Exception.Message)" }
  }
}

$before = Get-FreeBytes "C"
Write-Log "=== Weekly Maintenance 시작 ==="
Clear-Temp
Clear-Bin
Run-Backups
Backup-Apps
Make-RestorePoint
Reset-ThumbCache
$after  = Get-FreeBytes "C"
$freed  = [math]::Round(($after - $before)/1GB, 2)
Write-Log ("[Summary] C: 여유 공간 변화: {0} GB" -f $freed)
Write-Log "=== Weekly Maintenance 끝 ==="
Stop-Transcript | Out-Null

실행 테스트

아래 두 줄로 동작과 로그를 확인합니다.

powershell -NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\weekly_maintenance.ps1"
Get-Content "$HOME\MaintenanceLogs\weekly_*.log" -Tail 50

복사 버튼으로 스크립트를 복사한 뒤 파일로 저장하려면 PowerShell에서 다음 한 줄을 실행하세요.

Set-Content -Path "$env:USERPROFILE\Downloads\weekly_maintenance.ps1" -Value (Get-Clipboard) -Encoding UTF8

2) 작업 스케줄러 등록(주간 자동 실행)

한 줄 명령

schtasks /Create /TN "WeeklyMaintenance" /TR "powershell.exe -NoProfile -ExecutionPolicy Bypass -File \"C:\Scripts\weekly_maintenance.ps1\"" /SC WEEKLY /D SUN /ST 03:00 /RL HIGHEST /F
  • /D SUN: 매주 일요일, /ST 03:00: 03:00 KST(로컬 기준)
  • /RL HIGHEST: 높은 권한 실행(옵션). 노트북은 “AC 전원에서만 실행” 권장

weekly_maintenance.zip
0.00MB

반응형
댓글
최근에 올라온 글
최근에 달린 댓글
반응형