В этой записи буду складировать свои (и не только свои) небольшие PowerShell скрипты, которые не настолько велики, чтоб им посвящать отдельную запись.
Скрипты будут достаточно полезны в качестве примеров для создания скриптов со схожим функционалом.
Windows Powershell - оснастка командной строки и скриптовый язык для различной автоматизации задач и администрирования в windows. Официальный сайт - microsoft.com/powershell
Содержание
Удаление всех бекапов кроме трех последних
На сервере локально сохраняются бекапы, где папки именуются таким образом: "klbackup2014-01-22#23-00-00". PowerShell скрипт переносит эти папки на сетевой диск и хранить не более 3-х последних бекапов.
Copy-Item "C:\backups\klbackup*\" "\\Server\Backups\klBackup\" -force -recurse -ErrorAction stop Remove-Item "C:\backups\klbackup*" -force -recurse $folders = Get-ChildItem "\\Server\Backups\klBackup\klbackup*" $i = 0 While ($i -lt $folders.count-3) { Remove-Item $folders[$i] -force -recurse $i++ }
Удаляем файлы старше трех месяцев
$date = (Get-Date).AddMonths(-3) Get-ChildItem -Path D:\Files\Common | where {!$_.PSIsContainer} | foreach { if ($_.LastWriteTime -lt $date) { # в тестовых целях указываем -whatif # когда убедимся что все корректно работает то убираем его Remove-Item $_ -whatif } }
Разрешение скачанного изображения
PowerShell скрипт скачивает изображение из Интернета и отображает ее разрешение
Function Get-Image{ begin{[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") |Out-Null} process{ $fi=[System.IO.FileInfo]$_ if( $fi.Exists){ $img = [System.Drawing.Image]::FromFile($_) $img.Clone() $img.Dispose() }else{Write-Host "File not found: $_" -fore yellow } } end{} } #Скачиваем файл $webclient = New-Object System.Net.WebClient $url = "http://cs418720.userapi.com/v418720852/20d0/DiSlb-_mVBg.jpg" $file = "D:\ImageSize.jpg" $webclient.DownloadFile($url,$file) #Получаем ширину и высоту изображения $image = $file | Get-Image $Width = $image.Width $Height = $image.Height #Вывод на экран write-output “Width:$Width, Height:$Height"
Среднее арифметическое трех последних чисел
Из файла, в котором содержаться в каждой строке по числу, нужно получить три последние числа и выдать их среднее арифметическое.
$date = Get-Date -format yyyy-MM-dd $filename = "C:\Program Files\Zabbix\CheckHost_INET-" + $date + ".res" $file = Get-Content $filename #считываем файл в переменную. В файле каждая строка содержит по числу. $lenght = $file.count #получаем количество строк файла $avg=([int]$file[$lenght-1]+[int]$file[$lenght-2]+[int]$file[$lenght-3])/3 #вычисляем арифметическое среднее трех последних чисел Write-Host([int]$avg) #выводим среднее арифметическое с откидыванием дроби
Количество файлов в папках и размер папок
PowerShell скрипт выводит на экран и в файл D:\CountFiles.csv информацию о том, сколько содержит файлов каждая папка и подпапки в директории D:\Photos, а также размер этих папок и подпапок. csv файл можно импортировать в exel или гугл-таблицы и отсортировать столбцы по возрастанию или спаданию. Скрипт может пригодиться при оптимизации файлового хранилища.
$source="D:\Photos" Get-ChildItem $source -recurse -force | where {$_.psIscontainer} | foreach { $count = Get-ChildItem $_.fullname -recurse | where {$_.length} | Measure-Object -property length -Sum Write-Host($_.FullName) $FilesSize = '{0:F}' -f ((($count.Sum)/1024)/1024) Write-Host("Files: " + $count.count ) Write-Host("Size: " + $FilesSize + " MB") '"' + $_.FullName + '","' + $count.count + '","' + $FilesSize + '"' | Out-File D:\CountFiles.csv -Append }
Случайный афоризм из файла
#Автор скрипта: https://elims.org.ua #читаем содержимое файла в масив построчно и берем случайную строку $file = Get-Content "C:\aphorism.txt" $aphorism = Get-Random -input $file #берем случайный афоризм из массива афоризмов $tag = Get-Random -input " #афоризмы"," #цитаты", " #цитаты" #берем случайный тег $aphorism = $aphorism + $tag Write-Host($aphorism)
Отображение mp3-файлов с низким битрейтом
PowerShell скрипт выводит список mp3-файлов, которые находятся в папке D:\vk-music\ и имеют битрейт мене 320
#скрипт выводит список mp3-файлов, которые находятся в папке D:\vk-music\ и имеют битрейт мене 320 $objShell = New-Object -ComObject Shell.Application $mp3files = Get-ChildItem "D:\vk-music\" -include "*.mp3" -recurse #получили список mp3-файлов foreach($mp3Item in $mp3files){ #для каждого файла из списка $file = split-path $mp3Item -leaf #из полного имени вырезали имя файла $path = split-path $mp3Item #из полного имени вырезали адрес папки $objFolder = $objShell.namespace($path) $objFile = $objFolder.parsename($file) if ($objFolder.getDetailsOf($objFile, 28)) { # 28 - номер свойства файла, в котором хранится информация о битрейте $bitrate = [int]$objFolder.getDetailsOf($objFile, 28).Substring(1,3) #из строки, где хранится битрейт, вырезаем числовое значение битрейта if ($bitrate -lt 320) { #если битрейт меньше 320 "№" + ++$i + ' bitrate: ' + $bitrate + " file: " + [string]$mp3Item #выводим битрейт и полное имя файла } } }
Удаление изображений с плохим качеством
Удаляем в указанных папках (рекурсивно) изображения jpg с худшим качеством чем HD Ready
Function Get-Image{ begin{[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") |Out-Null} process{ $fi=[System.IO.FileInfo]$_ if( $fi.Exists){ $img = [System.Drawing.Image]::FromFile($_) $img.Clone() $img.Dispose() }else{Write-Host "File not found: $_" -fore yellow } } end{} } $paths = @() $paths = $paths + "D:\Folder1\" $paths = $paths + "E:\Folder2" $paths = $paths + "X:\Folder3\" Foreach ($path in $paths) { Get-ChildItem -Path $path -recurse -filter *.jpg | where {!$_.PSIsContainer} | foreach { #Получаем ширину и высоту изображения $image = $_.FullName | Get-Image $Width = $image.Width $Height = $image.Height #Вывод на экран $pixels = $Width*$Height $hd_ready = 1280*720 $string = $_.FullName+' Width:'+$Width+' Height:'+$Height + " Pixels:"+$pixels $image.dispose() if ($pixels -le $hd_ready) { Remove-Item $_.FullName write-host $string } } }
Копирование бекапов на резервную площадку
Если PowerShell скрипт запущен в определенное время и определенный день, то он начинает копировать файлы из указанных папок. Ход процесса записывается в лог файл.
После окончания работы:
- присылается письмо в котором указано:
- свободное место на локальных дисках (до старта и после окончания), объем бекапа
- время старта и окончания, длительность бекапа
- средняя скорость копирования
- компьютер выключается
Компьютер выключается потому, что он в основном выключен. Для резервного копирования он автоматически включается (настройка в биосе).
$StartTimeHour = (Get-Date).Hour #Запоминаем когда запустилась задача $Day_of_week = [int]((Get-Date).DayofWeek) #текущий день недели if ((($Day_of_week -eq 2)-or($Day_of_week -eq 4)-or($Day_of_week -eq 6))-and($StartTimeHour -eq 11)) { #старт копирования если сейчас вторник, среда, суббота и при этом 11 часов $StartTime = Get-Date -Format "yyyy.MM.dd HH:mm:ss" #время старта копирования $Free_Space_Start = Get-WMIObject Win32_LogicalDisk -Filter "DeviceID='D:'" | ForEach-Object {[math]::truncate($_.freespace / 1GB)} #свободное место до бекапа $Free_Space_Start_Bytes = Get-WMIObject Win32_LogicalDisk -Filter "DeviceID='D:'" | ForEach-Object {$_.freespace} #свободное место до бекапа $log_file = "D:\Backups\log.txt" #лог файл скрипта, можно понять на каком этапе работа скрипта $date = "{0:yyyy-MM-dd}" -f (get-date) #текущая дата для имени папки $path = "D:\Backups\" + $date + "\" #имя папки if (-not(Test-Path $path)) { #если папка не существует write-host "создаем папку: " + $path $result = New-Item -ItemType directory -Path $path #создаем папку } #копируем резервные копии медка $time = "{0:yyyy-MM-dd HH:mm:ss}" -f (get-date) $string = $time + " Start Copy \\172.16.13.1\Backups\Medoc" "##################################################" | Out-File -Append $log_file -Encoding UTF8 $string | Out-File -Append $log_file -Encoding UTF8 & robocopy \\172.16.13.1\Backups\Medoc D:\Backups\Medoc /e /log:"D:\Backups\robocopy_log.txt" #копируем резервные копии разных устройств и ПО $time = "{0:yyyy-MM-dd HH:mm:ss}" -f (get-date) $string = $time + " Start Copy \\172.16.13.1\Backups\Other" $string | Out-File -Append $log_file -Encoding UTF8 & robocopy \\172.16.13.1\Backups\Other D:\Backups\Other /e /log:"D:\Backups\robocopy_log.txt" #копируем резервные копии Windows с 1-го сервера $path = $path + "WindowsImageBackup" $time = "{0:yyyy-MM-dd HH:mm:ss}" -f (get-date) $string = $time + " Start Copy \\172.16.13.1\Backups\WindowsImageBackup" $string | Out-File -Append $log_file -Encoding UTF8 & robocopy \\172.16.13.1\Backups\WindowsImageBackup $path /e /log:"D:\Backups\robocopy_log.txt" #копируем резервные копии Windows с 2-го сервера $time = "{0:yyyy-MM-dd HH:mm:ss}" -f (get-date) $string = $time + " Start Copy \\172.16.13.2\Backups\WindowsImageBackup" $string | Out-File -Append $log_file -Encoding UTF8 & robocopy \\172.16.13.2\Backups\WindowsImageBackup $path /e /log:"D:\Backups\robocopy_log.txt" #запись в лог-файл окончания работы $time = "{0:yyyy-MM-dd HH:mm:ss}" -f (get-date) $string = $time + " Finish Backup" $string | Out-File -Append $log_file -Encoding UTF8 "##################################################" | Out-File -Append $log_file -Encoding UTF8 #Формируем данные для письма $EndTime = Get-Date -Format "yyyy.MM.dd HH:mm:ss" $Free_Space_End = Get-WMIObject Win32_LogicalDisk -Filter "DeviceID='D:'" | ForEach-Object {[math]::truncate($_.freespace / 1GB)} #свободное место после бекапа $Free_Space_End_Bytes = Get-WMIObject Win32_LogicalDisk -Filter "DeviceID='D:'" | ForEach-Object {$_.freespace} #свободное место до бекапа $backup_Size = $Free_Space_Start-$Free_Space_End $backup_Size_Bytes = $Free_Space_Start_Bytes-$Free_Space_End_Bytes $Work_time = $(NEW-TIMESPAN –Start $StartTime –End $EndTime) $Work_time_seconds = $Work_time.TotalSeconds $NetworkSpeed = '{0:N1}' -f ((($backup_Size_Bytes / $Work_time_seconds) / (1024*1024)) * 8) $Mail_String = "Свободное место до бекапа: " + $Free_Space_Start + " ГБ | `r`n" $Mail_String = $Mail_String + "Свободное место после бекапа:" + $Free_Space_End + " ГБ | `r`n" $Mail_String = $Mail_String + "Размер бекапа: " + $backup_Size + " ГБ | `r`n" $Mail_String = $Mail_String + "Старт бекапа: " + $StartTime + " | `r`n" $Mail_String = $Mail_String + "Конец бекапа: " + $EndTime + " | `r`n" $Mail_String = $Mail_String + "Время выполнения: " + $Work_time + " | `r`n" $Mail_String = $Mail_String + "Средняя скорость копирования: " + $NetworkSpeed + " Мбит в секунду `r`n" Write-host $Mail_String #Заголовки письма и данные почтового ящика $From = "admin-notify@домен.com.ua" $To = "admin@домен.ком.ua" $SMTPServer = "адрес.сервера.com.ua" $SMTPPort = "25" $Username = "admin-notify@домен.ком.ua" $Password = "тут_пароль" $subject = "Copy Backups to ReserveServer" $body = $Mail_String #формируем сообщение в формате html: $message = New-Object System.Net.Mail.MailMessage $From, $To $message.Subject = $subject $message.IsBodyHTML = $true $message.Body = $body #Отправляем: Write-host "Отправляем письмо" $smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort) $smtp.EnableSSL = $true $smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password) $smtp.Send($message) Write-host "Письмо отправленно" & shutdown -s -t 300 #выключаем компьютер через 5 минут }
Информация об обновлениях WSUS
Этот Powershell скрипт получает информацию со WSUS и показывает:
- количество обновлений по заданных критериям
- краткую сводную информацию об обновлениях
- имена обновлений
- отображает список обновлений по заданным критериям для каждого компьютера по отдельности
$WSUSServer = 'SERVER_NAME' #WSUS-сервер $PortNumber = 8530 #http порт wsus [void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") $wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer($WSUSServer,$False,$PortNumber) $UpdateScope = New-Object Microsoft.UpdateServices.Administration.UpdateScope #$UpdateScope.ApprovedStates = 'NotApproved' #указываем критерии апдейтов: не одобренные #$UpdateScope.IncludedInstallationStates = 'NotInstalled' #указываем критерии апдейтов: не проинсталированные $UpdateScope.IncludedInstallationStates = 'Installed' #указываем критерии апдейтов: проинсталированные $UpdateScope #просматриваем сформированные критерии апдейтов $wsus.GetUpdateCount($updatescope) #получаем и выводим количество апдейтов $wsus.GetUpdateStatus($updatescope,$False) #получаем и выводим краткую информацию об обновлениях $wsus.GetUpdates($updatescope).Title #выводим имена апдейтов $computers = $wsus.GetComputerTargets() #все компьютеры со wsus ForEach ($computer in $computers){ #для каждого компьютера $Computername = $computer.fulldomainname #получаем его имя $updates = $computer.GetUpdateInstallationInfoPerUpdate($updateScope) #получаем апдейты по указаным критериям $UpdateCount = $updates.Count #количество апдейтов для текущего компьютера write-host $Computername $UpdateCount #выводим имя компьютера и количество апдейтов $i = 0 ForEach ($update in $updates) { #для каждого апдейта выводим подробную информацию $i++ $update_info = $update.GetUpdate() #запрашиваем инфо об апдейте $UpdateTitle = $update_info.Title #имя апдейта $IsApproved = $update_info.IsApproved #является ли он одобренным write-host $Computername $i "of" $UpdateCount $IsApproved $UpdateTitle } }
Лочим экран и произносим текст
Задача: если в заббиксе сработал тригер и он не потвержден, то необходимо лочить экран и произность этот тригер.
Тригеры из заббикса запрашиваются утилитой zabbixctl и выводяться в текстовый файл, который опубликован по веб-адресу.
Сам powershell скрипт:
Add-Type -AssemblyName System.speech $speak = New-Object System.Speech.Synthesis.SpeechSynthesizer $request = (New-Object System.Net.WebClient).DownloadString("http://server/status.txt") #получаем тригеры $speak.Rate = -2 #Замедляем скорость произношения $zabbix_message = ($request -split '\n')[0] #первая строка - первый тригер if ($zabbix_message.length -ge 1) { #если строка не пустая cmd /c rundll32.exe user32.dll,LockWorkStation #лочим экран $speak.Speak("zabbix. " + $zabbix_message) #произносим текст $Time = Get-Date -Format "yyyy.MM.dd HH:mm:ss" $log_message = $Time + " " + $zabbix_message $log_message | Out-File -Append "c:\WINDOWS\scripts\log.txt" -Encoding UTF8 #записываем в лог-файл }
Вывод размера какой-либо веб страницы
$web = New-Object System.Net.WebClient "{0} bytes" -f ($web.DownloadString("https://elims.org.ua/")).length.toString("###,###,##0")
Остальные Powershell-скрипты:
- Powershell скрипты для Вконтакте
- Powershell скрипт: Автоответчик болтун для Вконтакте
- Powershell скрипт: Антиспам в коментариях стены и фотоальбомах сообщества во Вконтакте
- Powershell скрипт: Чтение Вконтакте через RSS
- Powershell скрипт: скачиваем фотографии из Вконтакте
- Powershell скрипт для скачивания музыки из Вконтакте
- Powershell скрипт: Отправка писем через gmail
- Powershell скрипт: охрана с помощью вебкамеры
- PowerShell скрипт автопубликации изображений на блог
Об Владимир, спсибо за готовые скрипты. Я вот никогда с PowerShell не работал (как-то надобности не было), но вот сейчас глянул эту статью и пригляделся к скрипту для закачки файлов, и уже нашел ему применение. Это конечно можно было бы и на Perl написать, но его же еще дополнительно ставить нужно.
Владимир, вот-вот) Посему на windows считаю powershell более универсальным средством, ничего не нужно устанавливать и можно быть уверенным что скрипт будет работать на других компьютера с этой ОС
Да мне если честно PowerShell пока не сильно то и нужен, кроме пары готовых скриптов, и кроме того, чтобы в нем себя хорошо чувствовать, нужно им заниматься постоянно, а не время от времени. Но все же поленая он штука.
Владимир, скрипт «Вывод количества файлов в папках и размера папок» пропускает файлы с аттрибутом hidden, возможно и с другими «не стандартными» аттрибутами.
alkash, действительно, нужно тогда вот так: Get-ChildItem $source -recurse -force
Большое спасибо автору блога! Много хороших публикаций у Вас в блоге. Добавила в закладки теперь буду чаще заглядывать.
Большое спасибо автору. Очень познавательно.
Коллеги, нужна помощь.
Начальник поставил задачу написать скрипт по сравнению двух Excel-файлов.
Требования:
1. Сравнение ТОЛЬКО через массив («так быстрее работать будет»). данные из обоих файлов заносятся в массивы и стравниваются
2. Путь к файлам надо запрашивать через отдельное окно
3. Результат работы — третий файл с результатами сравнения
Примеры файлов есть. Если кто-то захочет помочь — пишите в личку: korwin1979@mail.ru