
В этой записи буду складировать свои (и не только свои) небольшие 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