
Садимся, завариваем кофе погуще. Ежедневная рутина админа — это не только красивые дашборды и сложные IaC-пайплайны. Чаще это война с мелочами: «что слушает 5000-й порт?», «кто сожрал весь диск C:?» и «почему пинг не ходит?».
Вместо того чтобы сто раз в день делать одно и то же руками, напишем себе арсенал быстрых и метких PowerShell-скриптов. Не монстров на 500 строк, а именно инструментов для сиюминутной диагностики. PowerShell Core (7.x) — наш выбор, но всё будет работать и на классической 5.1.
1. Просмотр открытых портов: «Кто здесь слушает без спросу?»
Команда netstat -ano — старый друг, но её вывод просится в структурированный объект. Чтобы не пялиться в столбики текста, сделаем красиво и с пользой.
function Get-OpenPorts {
[CmdletBinding()]
param(
[Parameter(Position = 0)]
[string]$FilterByState = 'LISTENING'
)
Write-Host "Ищем открытые порты (состояние: '$FilterByState')..." -ForegroundColor Cyan
Write-Host "PID Протокол Локальный адрес Внешний адрес Состояние Процесс" -ForegroundColor Yellow
Write-Host "--- -------- ------------- ------------ -------- -------" -ForegroundColor Yellow
try {
$networkData = Get-NetTCPConnection -ErrorAction Stop | Where-Object State -eq $FilterByState
}
catch {
Write-Warning "Get-NetTCPConnection не сработал, возможно, ты на старом PowerShell. Использую netstat."
$netstatResult = netstat -ano -p TCP | Select-String -Pattern '\s+(LISTENING|ESTABLISHED)\s+'
foreach ($line in $netstatResult) {
$parts = $line -split '\s+'
Write-Host ($parts[4..$($parts.Length)] -join ' ') -ForegroundColor Gray
}
return
}
foreach ($conn in $networkData) {
$proc = Get-Process -Id $conn.OwningProcess -ErrorAction SilentlyContinue
$procName = if ($proc) { $proc.ProcessName } else { "N/A" }
$color = if ($conn.LocalPort -lt 1024) { 'Red' } else { 'Green' }
Write-Host ("{0,-5} {1,-8} {2,-22} {3,-20} {4,-10} {5}" -f
$conn.OwningProcess,
'TCP',
"$($conn.LocalAddress):$($conn.LocalPort)",
"$($conn.RemoteAddress):$($conn.RemotePort)",
$conn.State,
$procName) -ForegroundColor $color
}
}
💡 Как использовать:
Просто запусти Get-OpenPorts. Хочешь увидеть установленные соединения? Get-OpenPorts -FilterByState 'ESTABLISHED'. Красным подсветит системные порты (<1024) — часто именно там прячется что-то интересное.
2. Просмотр открытых файлов: «Кто прилепился к файлу как репей?»
Блокировка файла — классика жанра. Особенно весело, когда лог-файл не ротируется, а база не бэкапится. В Windows есть замечательная утилита handle.exe от Sysinternals, но если её под рукой нет, обойдёмся встроенными средствами.
function Get-LockedFile {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[string]$Path
)
process {
Write-Host "Пробуем выяснить, кто мучает файл '$Path'..." -ForegroundColor Cyan
try {
$fileStream = [System.IO.File]::Open($Path, 'Open', 'Read', 'None')
$fileStream.Close()
Write-Host "Файл свободен для деятельности." -ForegroundColor Green
}
catch [System.IO.IOException] {
Write-Host "Файл заблокирован! Ищем виновника..." -ForegroundColor Red
$lockingProcess = Get-CimInstance -ClassName Win32_Process |
Where-Object { $_.CommandLine -like "*$Path*" } |
Select-Object ProcessId, Name, CommandLine
if ($lockingProcess) {
$lockingProcess | Format-Table -AutoSize
Write-Host "Совет: для принудительного закрытия — kill -Id $($lockingProcess.ProcessId)" -ForegroundColor Yellow
}
else {
Write-Host "Не удалось найти процесс через WMI. Рекомендую скачать handle.exe от Sysinternals." -ForegroundColor Yellow
}
}
}
}
💡 Как использовать:
Get-LockedFile -Path "C:\logs\monster.log". Если файл заблокирован, скрипт попытается указать на процесс пальцем. Не идеально, но в 80% случаев работает.
3. Разрешаем ICMP эхо-пакеты: «Вернём пинг в строй!»
«Сервер не пингуется!» — эта фраза будит нас посреди ночи. Часто дело в бесчувственном фаерволе. Включаем ответ на эхо-запросы одной командой, но с проверкой.
function Enable-ICMPEcho {
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[Parameter(Position=0)]
[string]$RuleName = "Allow ICMPv4 Echo Request"
)
Write-Host "Включаем пингование для этого хоста..." -ForegroundColor Cyan
Write-Host "Предупреждение: это правило фаервола Windows. Убедись, что запускаешь от админа." -ForegroundColor Yellow
$existingRule = Get-NetFirewallRule -DisplayName $RuleName -ErrorAction SilentlyContinue
if ($existingRule) {
Write-Host "Правило '$RuleName' уже существует. Включаем его." -ForegroundColor Gray
Set-NetFirewallRule -DisplayName $RuleName -Enabled True
}
else {
Write-Host "Создаём новое правило фаервола: '$RuleName'." -ForegroundColor Gray
New-NetFirewallRule `
-DisplayName $RuleName `
-Description "Allow ICMP Echo Request for daily troubleshooting" `
-Protocol ICMPv4 `
-IcmpType 8 `
-Enabled True `
-Profile Any `
-Action Allow
}
$checkRule = Get-NetFirewallRule -DisplayName $RuleName | Select-Object DisplayName, Enabled, Action
Write-Host "Результат:" -ForegroundColor Green
$checkRule | Format-Table -AutoSize
Write-Host "Готово. Теперь тебя должны пинговать. Проверь с другой машины." -ForegroundColor Green
Write-Host "P.S. Не забудь про соседей по сети." -ForegroundColor DarkGray
}
⚠️ Как использовать:
Просто Enable-ICMPEcho. Скрипт создаст или включит правило в фаерволе. Запускать ОБЯЗАТЕЛЬНО от имени Администратора.
4. Остаток дискового пространства: «Диск C: снова на голодном пайке»
Классика, но с изюминкой. Не просто сухие цифры, а визуализация и предупреждение.
function Get-DiskSpaceReport {
[CmdletBinding()]
param(
[Parameter(Position=0)]
[string]$DriveLetter = "C"
)
Write-Host "Анализируем аппетиты диска $DriveLetter`:\..." -ForegroundColor Cyan
$disk = Get-PSDrive -Name $DriveLetter -ErrorAction SilentlyContinue
if (-not $disk) {
Write-Error "Диск $DriveLetter не найден. Укажи правильную букву, дружище."
return
}
$freePct = ($disk.Free / $disk.Used) * 100
$color = if ($freePct -lt 10) { 'Red' } elseif ($freePct -lt 20) { 'Yellow' } else { 'Green' }
$usedBlocks = [math]::Round(($disk.Used / $disk.Free) * 20)
$bar = '[' + ('#' * $usedBlocks) + ('-' * (20 - $usedBlocks)) + ']'
Write-Host "Диск: $($disk.Root)" -ForegroundColor White
Write-Host "Всего: $([math]::Round($disk.Free / 1GB, 2)) GB" -ForegroundColor Gray
Write-Host "Свободно: $([math]::Round($disk.Free / 1GB, 2)) GB ($([math]::Round($freePct, 1))%)" -ForegroundColor $color
Write-Host "График: $bar" -ForegroundColor $color
if ($freePct -lt 10) {
Write-Host "Тревога! Свободного места меньше 10%!" -ForegroundColor Red -BackgroundColor Black
Write-Host "Совет: проверь папки Temp, Logs и не забывай про "Очистку диска"." -ForegroundColor Yellow
}
}
💡 Как использовать:
Get-DiskSpaceReport -DriveLetter C. Увидишь сразу, пора паниковать или ещё можно жить.
5. Мониторинг событий в журнале событий: «Что там опять натворила система?»
Листать Event Log — как читать детектив. Нужно искать ключевые улики. Сфокусируемся на критических ошибках и предупреждениях за последние сутки.
function Get-RecentEvents {
[CmdletBinding()]
param(
[Parameter(Position=0)]
[int]$HoursBack = 24,
[Parameter(Position=1)]
[ValidateSet('System', 'Application', 'Security')]
[string]$LogName = 'System'
)
Write-Host "Роемся в журнале '$LogName' за последние $HoursBack часов..." -ForegroundColor Cyan
Write-Host "Ищем только ошибки (Error) и предупреждения (Warning)." -ForegroundColor Gray
$startTime = (Get-Date).AddHours(-$HoursBack)
$events = Get-WinEvent -LogName $LogName -MaxEvents 50 -ErrorAction SilentlyContinue |
Where-Object { $_.TimeCreated -ge $startTime -and ($_.Level -eq 2 -or $_.Level -eq 3) } |
Select-Object TimeCreated, LevelDisplayName, ProviderName, Id, Message |
Sort-Object TimeCreated -Descending
if (-not $events) {
Write-Host "Ура! Серьёзных проблем не обнаружено." -ForegroundColor Green
return
}
Write-Host "Найдено подозрительных событий: $($events.Count)" -ForegroundColor Yellow
foreach ($event in $events) {
$levelColor = if ($event.LevelDisplayName -eq 'Error') { 'Red' } else { 'Yellow' }
Write-Host "$($event.TimeCreated) [$($event.LevelDisplayName)] ($($event.ProviderName)) ID: $($event.Id)" -ForegroundColor $levelColor
Write-Host "$($event.Message[0..200] -join '')..." -ForegroundColor Gray
Write-Host "-" * 50 -ForegroundColor DarkGray
}
Write-Host "Совет: для деталей выполни 'eventvwr.msc' или посмотри событие по конкретному ID." -ForegroundColor Cyan
}
💡 Как использовать:
Get-RecentEvents -HoursBack 2 -LogName Application. Часто этого достаточно, чтобы понять, почему в 3 ночи проснулся.
Собираем всё в один набор
Сохрани каждый скрипт в отдельный .ps1 файл или добавь функции в свой профиль PowerShell ($PROFILE). Можно сделать красивый алиас для каждого.
New-Alias -Name ports -Value Get-OpenPorts
New-Alias -Name wholocks -Value Get-LockedFile
New-Alias -Name allowping -Value Enable-ICMPEcho
New-Alias -Name diskdiet -Value Get-DiskSpaceReport
New-Alias -Name whathappened -Value Get-RecentEvents
Итог: PowerShell — это не только для огромных скриптов развёртывания. Это ежедневный швейцарский нож в руках инженера, который предпочитает потратить 10 минут на написание скрипта, чем 100 часов на рутину. Автоматизируй то, что надоело, и останется время на кофе и решение действительно интересных проблем.
Крепких тебе сетей и зелёных статусов!