вторник, 10 октября 2017 г.

PowerShell в администрировании

Несколько важных коммандлетов и скриптов на PowerShell, которые всегда должны быть под рукой.

Общие параметры

Список установленных на сервере модулей Powershell:

get-module -ListAvailable

Произнесение текста системным динамиком:

(new-object -com SAPI.SpVoice).speak("spasibo")

Комментарии в PowerShell

бывают строчные — # и блочные — <#… #>

Запуск скрипта PowerShell из локального файла на других серверах:

invoke-command -computername Server01, Server02 -filepath c:\Scripts\DiskCollect.ps1
invoke-command -filepath c:\scripts\test.ps1 -computerName Server01

Действия при получении ошибки:

Connecting to remote server failed with the following error message : The WS-Management service cannot process the request. This user is allowed a maximum number of 5 concurrent shells, which has been exceeded. Close existing shells or raise the quota for this user. For more information, see the about_Remote_Troubleshooting Help topic.
Ошибка связана с превышением числа сессий, ограниченных пятью подключениями из соображений безопасности.
Для устранения этого ограничения нужно сделать следующее:
cd WSMan:\localhost\Shell
dir
WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Shell
WARNING: column "Type" does not fit into the display and was removed.
Name Value
---- -----
AllowRemoteShellAccess true
IdleTimeout 180000
MaxConcurrentUsers 5
MaxShellRunTime 2147483647
MaxProcessesPerShell 15
MaxMemoryPerShellMB 150
MaxShellsPerUser 5
В приведенной конфигурации в данной ситуации интересен параметр MaxShellsPerUser. Для увеличения его значения, выполняется следующий командлет
Set-Item .\MaxShellsPerUser 10
Данные настройки влияют на количество одновременно открытых окон PowerShell, управляющих данным сервером.
Второй вариант исправления данной проблемы - закрытие одного или более коннектов, которые были открыты раннее. Это делается с помощью коммандлета Remove-PSSession.

Задержка перед исполнением следующей команды

Start-Sleep -s 3 #(3 секунды)

Обработка ошибок в PowerShell

У параметра ErrorAction есть алиас — EA. Кроме того, вместо названия параметра можно указывать числовые значения: 0 (SilentlyContinue), 1 (Stop), 2 (Continue), 3 (Inquire). Так например, вместо:
Get-Service service,spooler -ErrorAction SilentlyContinue
можно написать так:
Get-Service service,spooler -EA 0

Определение времени, затраченного на выполнение команды или скрипта

В PowerShell есть несколько способов решения этой задачи. К примеру в .NET есть специальный класс StopWatch, который можно использовать как секундомер для измерения времени, потраченного на выполнение задачи. Класс StopWatch входит в пространство имен System.Diagnostics и у него есть статический метод StartNew. С помощью этого метода создадим новый экземпляр класса StopWatch, сохраним его в переменную и выведем свойства и методы нашего ″таймера″:
$watch = [System.Diagnostics.Stopwatch]::StartNew()
$watch | Get-Member
Здесь нас интересуют методы Start и Stop, отвечающие за запуск и остановку таймера и свойство Elapsed, показывающее прошедшее время.
$watch = [System.Diagnostics.Stopwatch]::StartNew()
$watch.Start() # Запуск таймера
Get-Childitem -Path C:\Windows -Filter ″*.txt″ -Recurse | Out-File C:\Files\files.txt
$watch.Stop() # Остановка таймера
Write-Host $watch.Elapsed # Время выполнения
$time = Measure-Command -Expression {Get-Childitem -Path C:\Windows` -Filter ″*.txt″ -Recurse | Out-File C:\Files\files.txt}
$time.ToString()

Режимы исполнения скриптов PowerShell

PowerShell обладает рядом режимов исполнения, которые определяют, какой тип кода разрешается выполнять. Все это управляется ключом реестра, живущим в HKLM. Существует 4 различных режима исполнения:
      • Ограниченный (Restricted): Политика исполнения по умолчанию, не допускает работу скриптов и разрешает работу лишь интерактивных команд.
      • Все подписанные (All Signed): Допускает работу всех скриптов. Правда, все скрипты и файлы конфигурации должны быть подписаны издателем, которому вы доверяете; данный режим подвергает вас риску работы подписанных (но вредоносных) скриптов, после получения подтверждения доверия издателю.
      • Неограниченный (Unrestricted): Все скрипты и файлы конфигурации, полученные из коммуникационных приложений, вроде Microsoft Outlook, Internet Explorer, Outlook Express и Windows Messenger работают после подтверждения, что вы понимаете, что файл исходит из Интернета; никакие цифровые подписи не требуются; данный режим подвергает вас риску работу неподписанных, вредоносных скриптов.
Быстрее и удобнее всего разрешить неограниченное исполнение командой
Set-ExecutionPolicy Unrestricted
и после исполнения нужного скрипта вернуть обратно ограниченный режим командой:
Set-ExecutionPolicy Restricted
Кроме того, можно задавать политики выполнения в контексте текущего пользователя:
set-executionpolicy -scope CurrentUser -executionPolicy AllSigned -force
Просмотр политик для всех пользователей:
get-executionpolicy -list
Получить список всех сертификатов в хранилище данного сервера:
Get-ChildItem cert:\LocalMachine\My
dir cert:\LocalMachine\My
Получить список всех сертификатов с подписью в хранилище текущего пользователя:
Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert
Подпись скрипта сертификатом из хранилища:
$file = "C:\Audit\SecurityAudit.ps1"
$cert = Get-ChildItem cert:\CurrentUser\My -CodeSigningCert
Set-AuthenticodeSignature $file $cert
Подпись скрипта сертификатом из файла:
$file = "C:\Audit\SecurityAudit.ps1"
$cert = Get-PfxCertificate C:\PS_Cert.pfx
Set-AuthenticodeSignature $file $cert

Команды для работы со службами в PowerShell

Сбор информации о службах из Windows Server

get-service | where {$_.status -eq "stopped"}
get-service | where {$_.name -eq "UMCS MonitoringD"}| fl
get-service "UMCS MonitoringD"
get-service "UMCS MonitoringD" | select Displayname,Status
get-service "UMCS PurchQueueD1A" -ComputerName MS-UMCS008 | select Displayname,Status 'MS-UMCS008','DR-UMCS008' | foreach {get-service "UMCS PurchQueueD1A" -computername $_} | Format-Table Name,Status,Machinename -AutoSize

Получить информацию в службах с одинаковым именем и разными статусами, расположенными на 2 серверах:

$pc1 = Get-Service -ComputerName COMP1
$pc2 = Get-Service -ComputerName COMP2
Compare-Object $pc1 $pc2 -Property Name, Status -PassThru |
Sort-Object -Property Name |
Select-Object -Property MachineName, Name, Status

Получить информацию в службах с помощью меню.

В соответствии с выбором пользователя выводятся запущенные, остановленные или неактивные службы:
Write-Host "Menu" -BackgroundColor White -ForegroundColor Red
Write-Host
# Затем выводим список пунктов меню:
Write-Host "1. List running services" -ForegroundColor Green
Write-Host "2. List stopped services" -ForegroundColor Green
Write-Host "3. List disabled services" -ForegroundColor Green
Write-Host "4. Exit" -ForegroundColor Green
Write-Host
# Предлагаем пользователю ввести выбранный пункт:
$choice = Read-Host "Select the menu item"
# И обрабатываем его выбор с помощью оператора switch:
Switch($choice){
1{Get-WmiObject win32_service | where {$_.state -eq "running"} | ft Name, DisplayName -a}
2{Get-WmiObject win32_service | where {$_.state -eq "stopped"} | ft Name, DisplayName -a}
3{Get-WmiObject win32_service | where {$_.startmode -eq "disabled"} | ft Name, DisplayName -a}
4{Write-Host "Exit"; exit}
default {Write-Host "Wrong choice, try again." -ForegroundColor Red}
}

Перезапуск службы в Windows Server

restart-service -name DNS
restart-service -InputObject $(Get-Service -Computer MS-UMCSTEST010 -Name UMCSSMSGWD)
set-service UMCSSMSGWD -ComputerName ms-umcstest010 -Status Stopped -PassThru | set-service -PassThru -Status Running

Изменение конфигурации службы

set-service -name DNS -startuptype "manual"

Остановка службы

stop-service -name DNS
stop-service -inputobject $(get-service -ComputerName MS-UMCSTEST010 -Name UMCSSMSGWD)
(get-service -ComputerName MS-UMCSTEST010 -Name UMCSSMSGWD).Stop()
Invoke-Command -comp ms-umcstest010 {stop-service UMCSSMSGWD -passthru}|
Status   Name               DisplayName                            PSComputerName
------   ----               -----------                            --------------
Stopped  UMCSSMSGWD         UMCSSMSGWD                             ms-umcstest010
set-service UMCSSMSGWD -ComputerName ms-umcstest010 -Status stopped
(Get-WmiObject Win32_Service -filter "name='UMCSSMSGWD'" -ComputerName MS-UMCSTEST010).StopService()
Get-Service -Name bits | Stop-service
Get-Service -Name bits -ComputerName RSLAPTOP01 | Set-Service -Status Stopped

Запуск службы

start-service -name DNS -pass | fl
start-service -inputobject $(get-service -ComputerName MS-UMCSTEST010 -Name UMCSSMSGWD)
(get-service -ComputerName MS-UMCSTEST010 -Name UMCSSMSGWD).Start()
Invoke-Command -comp ms-umcstest010 {start-service UMCSSMSGWD -passthru}

WARNING: Waiting for service 'UMCSSMSGWD (UMCSSMSGWD)' to finish starting...

Status   Name               DisplayName                            PSComputerName
------   ----               -----------                            --------------
Running  UMCSSMSGWD         UMCSSMSGWD                             ms-umcstest010
set-service UMCSSMSGWD -ComputerName ms-umcstest010 -Status running
(Get-WmiObject Win32_Service -filter "name='UMCSSMSGWD'" -ComputerName MS-UMCSTEST010).StartService()
Get-Service -Name bits | Start-service
Get-Service -Name bits -ComputerName RSLAPTOP01 | Set-Service -Status Running

Команды для администрирования элементов веб-сервера IIS

Статус пула приложения

Вывод статуса запуска пула приложения

Get-WebAppPoolState DefaultAppPool
Value
-----
Started

Рестарт пула приложения

Restart-WebItem "IIS:\Apppools\DefaultAppPool"

Статус веб-сайта

Вывод статуса запуска веб-сайта

Get-WebSiteState "Default Web Site"
Value
-----
Started

Старт веб-сайта

appcmd start sites "UMCSCore2"
"UMCSCore2" successfully started.

Остановка веб-сайта

appcmd stop sites "UMCSCore2"
"UMCSCore2" successfully stopped.

Рестарт веб-сайта

Restart-WebItem "IIS:\Sites\Default Web Site"

Общая информация о веб-сайтах сервера

Получить список развернутых на сервере веб-сайтов с их статусом

Get-WebSite | Select -Property Name, State

Получение информации об URL данного веб-сайта:

get-weburl "IIS:\Sites\Default Web Site" | Select ResponseUri
ResponseUri
-----------
http://localhost:8050/

Конфигурация веб-сайтов сервера

Вывод имени конфигурационного файла веб-сайта и даты/времени последнего редактирования конфига

Get-WebConfigFile "IIS:\Sites\UMCSCore1"

Получение значения элемента конфигурации веб-сайта

(Get-WebConfiguration -PSPath "IIS:\Sites\Default Web Site" -Filter /appsettings/* | where {$_.key -eq "key"}).value

Получение параметров и значений веб-конфигурации данного веб-сайта с учётом фильтра:

Get-WebConfiguration /appsettings/* 'IIS:\sites\UMCSCore' -Recurse

Изменение значения определённого параметра веб-конфигурации данного веб-сайта с учётом фильтра:

Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST/UMCSCore' -filter "appSettings/add[@key='shopFatalRequestPause']" -name value -value 999

Биндинги веб-сайта

Получение информации о биндингах данного веб-сайта:

Get-WebBinding "Default Web Site"
protocol bindingInformation
-------- ------------------
http *:8050:

Добавление SSL-биндинга для Default Web Site:

New-WebBinding -Name "Default Web Site" -IP "*" -Port 443 -Protocol https

Получение информации о SSL-биндингах:

cd IIS:\SslBindings

Применить сертификат с данным хешем к заданному SSL-биндингу:

get-item cert:\LocalMachine\MY\7ABF581E134280162AFFFC81E62011787B3B19B5 | new-item 0.0.0.0!443

Добавление нового дефолтного документа для веб-сайта на верхнюю позицию по приоритету использования:

Add-WebConfiguration //defaultDocument/files "IIS:\sites\Default Web Site" -atIndex 0 -Value @{value="new_index.html"}

Запуск Powershell-скрипта через задание в планировщике задач Windows

        1. На вкладке General вводим название задания, установить галочки в пунктах "Run whether user is logged on or not", "Run with the highest privileges".
        2. Далее идем на вкладку Triggers и создаем новый триггер, в котором будет храниться расписание запуска нашего задания. В поле Start указываем дату и время запуска, а в поле Expire — дату и время завершения задания. Указываем выполнять задание ежедневно (Daily) и задаем период повтора (Recur every) 1 день. Можно также выбрать одноразовое выполнение (One time), а в разделе Advanced settings отметить пункт Repeat task every и указать время повторения, минимум 5 минут, максимум 1 час.
        3. Переходим на вкладку Action и указываем действие для запланированного задания. Напомню, что в целях безопасности PowerShell скрипты могут выполняться только интерактивно, то есть сначала надо запустить оболочку PowerShell и уже в ней указать путь к скрипту. Поэтому в поле «Action» указываем Start a program, запуск C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe, а в поле «Add Arguments» параметр -File и путь к нашему скрипту, вот так:
          -File C:\Scripts\start.ps1 Также в поле аргументы можно указать:
          -Command — выполняет указанные команды и любые другие параметры. Этот параметр тоже можно использовать для запуска скрипта, например: -Command {C:\Scripts\start.ps1}. Кроме того, с его помощью можно передавать в скрипт параметры: -Command {C:\Scripts\start.ps1 -a 1 -b 3};
          -ExecutionPolicy — задает политику выполнения скриптов для текущего сеанса, может принимать значения Unrestricted, RemoteSigned, AllSigned и Restricted. Заданная политика будет действовать только в текущем сеансе и имеет приоритет над любыми ранее созданными политиками;
          -NonInteractive — отключить вывод интерактивных запросов к пользователю;
          -WindowStyle Hidden — запуск окна PowerShell в скрытом режиме, незаметно для пользователя;
          -NoProfile — предотвращает загрузку профиля, что может несколько ускорить выполнение скрипта;
          -Version - использует указанную версию PowerShell;
          -NoExit — оставить оболочку открытой после отработки скрипта. Это может понадобиться при проверке и отладке скрипта.
В PowerShell 3.0 появился новый функционал Sheduled Job, дающий возможность создавать запланированные задания прямо из консоли, не пользуясь оснасткой планировщика. Воспользуемся им для планового запуска нашего скрипта.
        1. Сначала создаем расписание запуска (ежедневно в полпятого вечера, в течении 10 дней):
          $t = New-JobTrigger -Daily -At 4:30PM -DaysInterval 10
        2. Затем сохраняем в переменной учетные данные:
          $cred = Get-Credential Domain\Login
        3. В качестве опции указываем запуск задания с повышенными привилегиями:
          $o = New-ScheduledJobOption -RunElevated
        4. И регистрируем задание с именем Start:
          Register-ScheduledJob -Name Start -FilePath C:\Scripts\start.ps1 -Trigger $t -Credential $cred -ScheduledJobOption $o
        5. Чтобы убедится в том, что задание создано, можно открыть планировщик и найти наше задание в разделе Microsoft\Windows\PowerShell\SheduledJobs.
Примечание. Для каждого запланированного задания PowerShell в директории %systemdrive%\Users\%username%\AppData\Local\Microsoft\Windows\PowerShell\ScheduledJobs создается одноименная папка. В этой папке находится само задание в XML-файле и папка Output, в которой, в подпапках по времени выполнения, хранится история выполнения задания — результат выполнения (файлs Result.xml) и статус задания (Status.xml). Эти файлы могут пригодиться для отладки и диагностики в том случае, если задание не отрабатывает должным образом.

Информация, получаемая из ОС Windows

Получение имени ОС сервера

(Gwmi win32_operatingsystem).caption

Получение имени сервера

2.1 Без имени домена:
Write-Host "$env:COMPUTERNAME"
2.2 С именем домена:
"{0}.{1}" -f (Get-WmiObject -Class Win32_ComputerSystem).DNSHostName, (Get-WmiObject -Class Win32_ComputerSystem).Domain
([System.Net.Dns]::GetHostByName("localhost")).HostName

Информаци о CPU сервера

Get-WmiObject -Class Win32_Processor | Select-Object -Property Name, Number*

Дата установки операционной системы и сколько времени прошло с этого момента

$system = Get-WmiObject -Class Win32_OperatingSystem
# Получаем дату установки ОС
$InstallDate = [Management.ManagementDateTimeconverter]::ToDateTime($system.installdate)
# Вычисляем количество дней, прошедших с момента установки
$AfterInstallDays = ((Get-Date) — $Installdate).Days
# Переводим дату установки в короткий формат
$ShortInstallDate = "{0:dd.MM.yyyy HH:MM}" -f ($InstallDate)
# Выводим результаты
$InstallDateString = "Система установлена: $ShortInstallDate (Прошло дней: $AfterInstalldays)"
$InstallDateString
$computernames = @(
"SERVER1"
, "SERVER2"
);
$installdate = @();
foreach ($name in $computernames){
$system = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $name
$installdate += [Management.ManagementDateTimeconverter]::ToDateTime($system.installdate)
}
for ($i = 0; $i -le ($computernames.length - 1); $i += 1) {
Write-Host $computernames[$i], $installdate[$i]
}

Вывести все переменные окружения:

Get-ChildItem Env:

Вывести конкретную переменную окружения:

$Env:path

Данные о свободном дисковом пространстве серверов

$machines = @("comp1", "comp1")
$(foreach ($machine in $machines)
{
Get-WmiObject Win32_LogicalDisk -ComputerName $machine | Select-Object -Property FreeSpace | Export-CSV c:\disks.csv
})

Вывести дату установки ОС по списку серверов

$computernames = @(
"SERVER1"
, "SERVER2"
, "SERVER3"
, "SERVER4"
, "SERVER5"
);
$installdate = @();
foreach ($name in $computernames){
$system = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $name
$installdate += [Management.ManagementDateTimeconverter]::ToDateTime($system.installdate)
}
for ($i = 0; $i -le ($computernames.length - 1); $i += 1) {
Write-Host $computernames[$i], $installdate[$i]
}

Вывести список установленных на машину программ:

Get-WmiObject win32_product -computer $env:computername |
Sort Vendor,InstallDate |
Format-Table -GroupBy Vendor Name,`
@{Label="InstallDate";Expression={
"$($_.InstallDate.substring(4,2))/$($_.InstallDate.substring(6,2))/$($_.InstallDate.substring(0,4))"}},`
InstallLocation,InstallSource,PackageName,Version -wrap |
Out-File productreport.txt

Поиск ошибок при установке обновлений Windows

get—childitem C:\Windows\kb*.log | select—string —pattern error | Format—table Path, LineNumber, Line —wrap —AutoSize

Получение данных счётчиков производительности сервера

$Counter = "\Process(Idle)\% Processor Time"
$Counter = "\LogicalDisk(D:)\Avg. Disk Queue Length"
$Counter = "\LogicalDisk(D:)\% Free Space"
$Counter = "\Memory\Available Mbytes"
Get-Counter -Counter $Counter -ComputerName $Servers
$Counter | Get-Counter -ComputerName $Servers
Дополнительные параметры: -SampleInterval (интервал сбора данных в секундах , по умочанию 1 сек) -MaxSamples (количество проб сбора данных).

Запись информации о средней загрузке CPU, использовании RAM и даты/времени сбора данных в файл:

# Current Load as a percentage
$Average_CPU_load = (Get-WmiObject win32_processor | Measure-Object -property LoadPercentage -Average).Average
# Memory Usage as a percentage
$Memory_usage = (Get-WmiObject win32_operatingsystem | Foreach {"{0:N0}" -f ((($_.TotalVisibleMemorySize - $_.FreePhysicalMemory)*100)/ $_.TotalVisibleMemorySize)})
# Current date and time
$timestamp = Get-Date -Format "dd.MM.yyyy HH:mm"
$d = "$timestamp, $Average_CPU_load, $Memory_usage"
$comp = $env:COMPUTERNAME
$file = "P:\Collector_$comp.csv"
$isfile = Test-Path $file
if($isfile -eq "True") {
$d | Out-File $file -Append default
}
else {
New-Item $file -ItemType "file"
$d | Out-File $file -Append default
}

Получение событий логов Windows сервера

Get-EventLog SYSTEM -Newest 5 -Entry ERROR -Comp COMP1, COMP2 | Sort Machinename | ft -GroupBy MachineName -prop TimeWritten, Source, Message -wrap -auto

Получить 100 последних записей из журнала Security с ID 529

Get-EventLog -Newest 100 -LogName security | Where-Object {$_.EventID -eq "529"} | FL

Получить 100 последних записей из журнала Security только за сегодня

Get-EventLog -Newest 100 -LogName security | Where-Object {$_.TimeGenerated.Date -eq (Get-Date).Date} | FL

Получить 100 записей из журнала Security за последние 7 дней с кодом 529

Get-EventLog -Newest 100 -LogName security | Where-Object {{$_.TimeGenerated.Date -eq (Get-Date).AddDays(—7)} -and {$_.EventID -eq "529"}}

Различные полезные советы при работе в PowerShell

Передача переменной в удалённую сессию PowerShell

$path = "C:\Users\VVP"
$session = New-PSSession -ComputerName Comp1, Comp2
Invoke-Command -Session $session - ScriptBlock {param($path) Get-ChildItem $path} -Arg $path

Отображение даты и времени

Получить текущую дату и время:

Get-Date
22 апреля 2015 г. 17:03:01
Get-Date -Format "dd.MM.yyyy HH:mm:ss"
22.04.2015 17:03:01
Get-Date -Format "ddd"
Пн
Get-Date -Format "dddd dd.MM.yyyy"
понедельник 28.03.2016
Get-Date -Format "d"
28.03.2016
Get-Date -Format "D"
28 марта 2016 г.
Get-Date -Format "g"
28.03.2016 15:24
Get-Date -Format "G"
28.03.2016 15:24:40
Get-Date -Format "f"
28 марта 2016 г. 15:27
Get-Date -Format "F"
28 марта 2016 г. 15:27:13
Get-Date -Format "s"
2016-03-28T15:30:10
Get-Date -Format "t"
15:32
Get-Date -Format "T"
15:32:21
Get-Date -Format "Y"
Март 2016

Порядковый номер дня в текущем месяце:

Get-Date -UFormat %d

Порядковый номер текущего месяца:

Get-Date -UFormat %m

Порядковый номер текущей недели в году:

Get-Date -UFormat %V

Порядковый номер дня в текущей неделе:

Get-Date -UFormat %w

Порядковый номер дня в текущем году:

Get-Date -UFormat %j

Как рассчитать разницу (количество дней, часов, минут или секунд) между двумя датами с помощью PowerShell?

(New-TimeSpan -Start $dateStart -End $dateEnd).Days
(New-TimeSpan -Start $dateStart -End $dateEnd).Hours
(New-TimeSpan -Start $dateStart -End $dateEnd).Minutes
(New-TimeSpan -Start $dateStart -End $dateEnd).Seconds

Получить все даты между 2 датами:

$startdate = Get-Date -Date '2016-01-01'
$enddate = Get-Date -Date '2016-02-01'
$difference = New-TimeSpan -Start $startdate -End $enddate
$days = [Math]::Ceiling($difference.TotalDays)+1
1..$days | ForEach-Object {
$startdate
$startdate = $startdate.AddDays(1)
}

Получить все даты диапазона, являющиеся рабочими днями:

$startdate = Get-Date -Date '2017-01-01'
$enddate = Get-Date -Date '2017-02-01'
$difference = New-TimeSpan -Start $startdate -End $enddate
$difference.Days
$days = [Math]::Ceiling($difference.TotalDays)+1
1..$days | ForEach-Object {
$startdate
$startdate = $startdate.AddDays(1)
} |
Where-Object { $_.DayOfWeek -gt 0 -and $_.DayOfWeek -lt 6
}

Отнять 3 дня от текущей даты:

(Get-Date).AddDays(-3)

Active Directory

Импорт модуля AD:

import-module ActiveDirectory

Получить список всех пользователей AD-группы:

Get-ADGroupMember Group_Name | Select name

Получить список всех пользователей AD-группы (рекурсивно):

Get-ADGroupMember Group_Name -Recursive | Select Name

Получить список всех AD-групп, в которых состоит указанный пользователь:

Get-ADUser User -Property MemberOf | Select -ExpandProperty MemberOf

Получить спиcок всех AD-групп, в которых состоит пользователь, под который запускается скрипт:

([System.Security.Principal.WindowsIdentity]::GetCurrent()).Groups |
Foreach-Object { $_.Translate([System.Security.Principal.NTAccount])}

Дата последней смены пароля пользователем:

Get-ADUser User -properties PasswordLastSet | Select Name, PasswordLastSet

Строки

Если в строку, заключенную в кавычки, надо вставить значение переменной, то необходимо использовать двойные кавычки. При использовании одинарных кавычек все, что находится внутри кавычек обрабатывается как тест, вне зависимости от содержимого. Только при наличии двойных кавычек PowerShell ищет внутри текста знак $ и подставляет вместо имени переменной ее значение.
Только двойные кавычки дают возможность использовать специальные символы внутри текста. В тексте, ограниченном двойными кавычками, PowerShell ищет управляющий символ — обратную одинарную кавычку (`) и выполняет следующий за ней спец. символ.
Специальный символ (кавычка, знак $ и пр.), следующий за обратной кавычкой (`), экранируется — воспринимается не как специальный, а как обычный строковый символ. Поэтому при использовании кавычек внутри кавычек внутреннюю пару кавычек можно экранировать:
$a = ″Кавычки `″внутри`″ кавычек″
Тогда они будут выведены как обычный текст.
Как удалить одинаковые строки из файла с помощью PowerShell?
Get-Content -Path .\file.txt | Select-Object -Unique | Set-Content -Path .\testing.txt # Save

Получить флаг вхождения подстроки 2 в строку 1:

("1").Contains("2")
Результатом данного метода будет булевое значение, которое будет равно 0 если строка 2 будет являтся подстрокой строки 1

Получить хэш-код строки:

("Hello World!").GetHashCode()

Вставить в строку подстроку после определённой позиции:

("Hello World!").Insert(11," of Warcraft")
Результатом выполнения данного скрипта будет строка : "Hello World of Warcraft!"

Дополнить строку символами слева:

"Hello World!".PadLeft(20,".")
Результатом данной команды будет строка: "........Hello World!"

Дополнить строку символами справа:

"Hello World!".PadRight(20,".")
Результат данной команды будет строка : "Hello World!........"

Удаление из строки подстроки:

("Hello World!").Remove(2)
Результатом будет строка: "He"
Если же воспользоваться синтаксисом:
("Hello World!").Remove(4,2)
Результат: "HellWorld!"

Получить подстроку из строки:

"Hello World!".Substring(3)
Результатом данной команды будет строка: "lo World!"
Так же существует другой синтаксис:
"Hello World!".Substring(6,5)
Результатом будет строка "World"

Найти подстроку и заменить на свою:

("Hello World!").Replace("Hello","Goodbye")
Результат "Goodbye World!"

Разбить строку на массив строк:

("Hello World !").Split(" ")
Результатом будет массив строк"Hello","World,!"
Если нужно указать не один разделитель а несколько, можно указать перечисление:
"Hello World!".Split(@("o","e"))
Результатом будет массив строк :"H","ll"," W","rld!"

Удаление одинаковых символов по бокам строки:

Для удаления пробелов можно использовать метод:
[String]=[строка 1].Trim()
[String]=[строка 1].TrimLeft()
[String]=[строка 1].TrimRight()
Если надо удалить не пробел, а определённый символ, то этот символ надо ввести в параметр метода. Синтаксис:
[String]=[строка 1].Trim([удаляемый символ])
[String]=[строка 1].TrimLeft([удаляемый символ])
[String]=[строка 1].TrimRight([удаляемый символ])

Определение размера строки:

"Hello World!".Length
Результатом команды будет число 12

Преобразования строк в различные типы

У строки так же имеется ряд методов, которые конвертируют данные из строки в различные типы. Эти свойства ToBoolean, ToByte, ToChar, ToCharArray, ToDateTime, ToDecimal, ToDouble, ToInt16, ToInt32, ToInt64, ToLower, ToLowerInvariant, ToSByte, ToSingle, ToString, ToType, ToUInt16, ToUInt32, ToUInt64, ToUpper, ToUpperInvariant

Операции сравнения:

      • -lt – Меньше, чем
      • -le – Меньше или равно
      • -gt – Больше, чем
      • -ge – Больше или равно
      • -eq – Равно
      • -ne – Не равно
      • -like – оператор подобия
      • -notlike – оператор не-подобия
Логические операции:
      • -and – Оба условия должны быть истины, чтобы выражение было истинно
      • -or – Одно или оба условия должны быть истины, чтобы выражение было истинно
      • -xor – Одно условие должно быть истинно, а второе должно иметь значение “ложь”, чтобы выражение было истинно
      • -not – Указанные условия должны иметь значение “ложь”, чтобы выражение было истинно
      • ! – Указанное условие должно иметь значение “ложь”, чтобы выражение было истинно

Чтение части файла (от индекса начала до индекса конца):

# Читаем файл как одну строку $file = [System.IO.File]::ReadAllText("file.txt")
# Индекс начала
$start = $file.IndexOf("начало")
# Индекс конца
$end = $file.IndexOf("конец")
# Читаем выделенный текст
$file.Substring($start, $end-$start)

Работа с текстовыми файлами

Чтение лог-файла онлайн

Get-Content PATH_TO_FILE.txt -wait -tail 0

Добавление в текстовый файл определённой информации:

Add-Content -Path "D:\test\test.txt" -Value (Get-Content P:\MigrationFile.txt)

Замена текста в файле:

(Get-Content c:\somefile.txt) |
Foreach-Object { $_ -replace 'old', 'new' } |
Set-Content c:\somefile.txt

Очистка файла (без его удаления):

Clear-Content -Path "D:\test\test_ip.txt"

Сравнение содержимого 2 файлов с выводом найденных различий

Compare-Object -referenceobject $(get-content \\MS-UMCS010\D$\WWW\UMCSCore2\Web.config) -differenceobject $(get-content \\DR-UMCS010\D$\WWW\UMCSCore2\Web.config)

Файловая система

Вывод список объектов файловой системы:

dir .\test | select -ExpandProperty name

Вывести список все файлов в текущем каталоге и переименовать каждый файл, заменяя все пробелы в файловых именах на подчеркивания:

Get-ChildItem * |
Where-Object {! $_.PSIsContainer } |
Rename-Item -NewName { $_.name -replace ' ','_' }

Вывести на экран список папок:

Get-Item C:\* | Where-Object { $_.PSIsContainer }
В папке C:\temp\results\ находятся файлы с названием COMPXXX.txt. Можно ли их сгенерировать в один текстовой файл, чтобы он содержал информацию по принципу:
COMP001
content
COMP002
content
COMP003
content
и т.д.?
ls C:\temp\results\COMP*.txt |%{
$_.fullname >> C:\temp\results\result.txt
get-content -totalcount 10 $_ >> C:\temp\results\result.txt
}

Создание файла произвольного размера

fsutil file createnew F:\File.txt 1024
То же самое можно сделать с помощью PowerShell, хотя команды будут немного сложнее:
$file = New-Object -TypeName System.IO.FileStream -ArgumentList E:\File.txt,Create,ReadWrite
$file.SetLength(1Mb)
$file.Close()
Здесь мы сначала создаем объект типа файл, а затем с помощью метода SetLength присваиваем ему необходимый размер.
Все описанные способы создают пустые файлы (точнее файлы, заполненные символом NUL). Если надо создать файл заданного размера и заполнить его каким либо произвольным содержимым, то можно немного изменить предыдущий способ и воспользоваться такими командами:
$array = New-Object -TypeName Byte[] -ArgumentList 1Mb
$obj = New-Object -TypeName System.Random
$obj.NextBytes($array)
Set-Content -Path E:\File.txt -Value $array -Encoding Byte
Ну и для генерации большого количества файлов (напр. 1000) можно воспользоваться таким скриптом:
$array = New-Object -TypeName Byte[] -ArgumentList 1Mb
$obj = New-Object -TypeName System.Random
$obj.NextBytes($array)
for ($i=1; $i -le 1000; $i++) {
Set-Content -Path E:\File.txt$i -Value $array -Encoding Byte
}
Получение списка файлов в директории с группировкой и группировкой по расширению файла.
get-childitem | sort-object -property extension | group-object -property extension

Скрипт для копирования файлов из одной папки в другую:

Запуск скрипта через alias.
copy-data c:\test d:\test
function copy-data {
param($source, $dest)
$counter = 0
$files = Get-ChildItem $source -Force -Recurse
foreach($file in $files)
{
$status = "Copying file {0} of {1}: {2}" -f $counter, $files.count, $file.name
Write-Progress -Activity "Copyng Files" -Status $status -PercentComplete ($counter/$files.count * 100)
Copy-Item $file.pspath $dest -Force
$counter++
}
}

Создание бэкапов файлов с заданным расширением:

$ExtensionToBackup = '*.ps1'
$BackupExtension = '.ps1_old'
$FolderToProcess = 'D:\Useful_Scripts\'
$Recurse = $false
Get-ChildItem -Path $FolderToProcess -Filter $ExtensionToBackup -Recurse:$Recurse |
ForEach-Object {
$newpath = [System.IO.Path]::ChangeExtension($_.FullName, $BackupExtension)
Copy-Item -Path $_.FullName -Destination $newpath
}

Замена имени файла:

get-childitem c:\temp | rename-item -newname {$_.name -replace 'Nautilus Pompilius', 'Наутилус Помпилиус'}
Как найти пустые папки с помощью PowerShell?
Get-ChildItem -Path C:\scripts -Recurse -Directory | Where-Object -FilterScript {$_.GetFiles().Count -eq 0} | Select-Object -Property FullName

Удаление файла(-ов)

Remove-Item -Recurse C:\Ecommerce\UMCSPurchQueueD\* -Exclude *.config

Копирование файла(-ов)

Copy-Item C:\Ecommerce\UMCSPurchQueueD\* C:\Ecommerce\Backup\UMCSPurchQueueD_4.19
Copy-Item \\ms-umcs008\d$\4.20\Install\Applications\UMCSPurchQueueD\* C:\Ecommerce\UMCSPurchQueueD
Для копирования из C:\Files в C:\Temp всех файлов с именем pic воспользуемся следующей конструкцией:
$query = ″SELECT * FROM CIM_Datafile WHERE Drive=′C:′ AND Path=′\\Files\\′ AND Name LIKE ′%pic%′″
$files = Get-CimInstance -Query $query
foreach ($file in $files) {$name=″C:\Temp\$($file.FileName).$(Sfile.Extension)″; Invoke-CimMethod -InputObject $file -MethodName Copy -Arguments @{FileName=$name}}

Получить MD5-сумму файла

Get-MD5 "C:\TestFrontEnd1-Site\bin\site.dll"

Создание файловой шары на локальном сервере:

$ShareName = 'Releases'
$Path = 'D:\Releases'
If (!(Get-WmiObject -Class Win32_Share -Filter "name='$ShareName'"))
{
$Shares=[WMICLASS]"WIN32_Share"
$Shares.Create($Path,$ShareName,0).ReturnValue
}
else
{
Write-Warning "Share $ShareName exists already."
}
То же, но на удалённом сервере:
$ShareName = 'NewShare'
$Path = 'c:\123'
$Server = 'MyServer'
If (!(Get-WmiObject -Class Win32_Share -Filter "name='$ShareName'" -ComputerName $Server))
{
$Shares=[WMICLASS]"\\$Server\root\cimv2:WIN32_Share"
$Shares.Create($Path,$ShareName,0).ReturnValue
}
else
{
Write-Warning "Share $ShareName exists already."
}

Регулярные выражения

Регистрозависимость

В общем случае регулярные выражения регистрозависимы, однако в PowerShell по умолчанию это не так. Если необходимо учитывать регистр символов, то можно приставить к оператору сравнения букву С (от Case Sensitive). Получившийся оператор cmatch регистрозависим, соответственно при его использовании выражение уже не будет соответствовать действительности:
″PowerShell″ -cmatch ″power″ -> False
Кроме того, есть возможность включать регистрозависимость средствами самих регулярных выражений, где в качестве переключателей используются конструкции (?i) и (?-i). При использовании оператора match (?-i) включает зависимость от регистра, а (?i) отключает. Например:
″PowerShell″ -match ″(?-i)power″ -> False
″PowerShell″ -match ″(?i)power″ -> True
Плюс использования (?i) и (?-i) в том, что с их помощью можно задавать регистрозависимость не для всего выражения, а для его части. Например:
″PowerShell″ -match ″power(?-i)Shell″ -> True
″PowerShell″ -match ″power(?-i)shell″ -> False

Якоря

Для положительного результата регулярному выражению требуется лишь наличие подходящих символов, независимо от их расположения в тексте. Это поведение по умолчанию, но его можно изменить с помощью специальных метасимволов, называемых якорями (anchors). Якоря позволяют точно указать на позицию в строке, в которой должны находиться искомые символы. Метасимволы крышка ^ и \A совпадают с началом строки, перед первым символом. Для примера выведем список служб, начинающихся с символа ″b″:
Get-Service | where {$_.name -match ″^b″}
Метасимволы доллар $, \Z или \z совпадают с окончанием строки. Для примера выведем список служб, заканчивающихся на ″s″:
Get-Service | where {$_.name -match ″s$″}

Границы

Как уже было сказано, для регулярного выражения нет необходимости в точном совпадении, достаточно наличия искомых символов в тексте. Так например слово ″cat″ будет найдено не только в ″My cat is fat″, но и в ″bobcat″, ″category″, ″staccato″ и прочих, которые не имеют ни малейшего отношения к кошачьим. Поэтому, если необходимо только целое слово, можно обозначить его границы (boundaries) с помощью метасимвола \b.
Для примера выведем список файлов в директории, содержащих в названии слово power:
Get-ChildItem ′C:\Files\PS Books′ | where {$_.Name -match ″power″}
А теперь предположим, что мне нужно, чтобы слово power в названии присутствовало отдельно от прочих. Изменим команду, обозначив границы слова:
Get-ChildItem ′C:\Files\PS Books′ | where {$_.Name -match ″\bpower\b″}
Возможен и обратный случай, когда необходимо найти слово не целиком, а именно в составе с другим — например найти ″cat″ в ″bobcat″, ″category″ или ″staccato″, но не в ″My cat is fat″. Для этого есть специальный метасимвол \B, который называется ″не граница″ (nonboundaries). Возьмем пример с файлами и изменим его таким образом, чтобы слово power нашлось только в составе других слов:
Get-ChildItem ′C:\Files\PS Books′ | where {$_.Name -match ″\Bpower\B″}

Отрицательные классы

Иногда проще пойти от обратного, т.е. не перечислять все символы, которые должны присутствовать в строке, а указать только те, которых там быть не должно. Сделать это можно с помощью уже знакомого нам символа крышка (^). Так выражение [^adf] означает ″любой символ кроме a,d или f″. Крышка, поставленная в качестве первого символа в классе, означает отрицание, а сам класс называется отрицательным (или инвертированным).
Для примера выведем все файлы в директории, кроме файлов с расширением pdf:
Get-ChildItem ′C:\Files\PS Books′ | where {$_.Name -match ″[^pdf]$″}
Для основных классов (\w,\d,\s) есть альтернативный вариант отрицания. Для того, чтобы включить в них отрицание, достаточно перевести их в верхний регистр:
      • \W — все кроме буквы, цифры или нижнего подчеркивания, эквивалентно [^\s];
      • \D — все кроме цифр, эквивалентно [^\d];
      • \S — все кроме символов пропуска, эквивалентно [^\s].
"Жадные" и "ленивые" квантификаторы
″Greedy and Lazy Quantifiers″ -replace ″L.*?\s″
″Greedy and Quantifiers″

Получение всех IP-адресов из файла и запись их в отдельный файл:

$input_path = ‘c:\log_file.txt’
$output_file = ‘c:\extracted_ip_addresses.txt’
$regex = ‘\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b’
select-string -Path $input_path -Pattern $regex -AllMatches | % { $_.Matches } | % { $_.Value } > $output_file

Поиск подряд идущих параметров и их значений по регулярному выражению в файле:

$file="C:\TestFile.log"
$shablon="request,\sstart=\d{2}\/\d{2}\/\d{4}\s\d{2}:\d{2}:\d{2},\send=\d{2}/\d{2}\/\d{4}\s\d{2}:\d{2}:\d{2}"
(Get-Content $file | ?{$_ -match $shablon} | %{$Matches[0]} ) -replace "request,",""

Поиск строк по рег. выражению и вывод в отдельный файл

$logfiles = @(
'D:\File1.txt'
, 'D:\File2.txt'
);
$output_file = ‘D:\Extracted.txt’
$regex = ‘(?<ctn>\d{10}) CI2 result:-2’
foreach ($logfile in $logfiles) {
select-string -Path $logfile -Pattern $regex -AllMatches | % { $_.Matches["ctn"] } | % { $_.Value } > $output_file
}

Эквиваленты родным сетевым командам в PowerShell

# ipconfig
Get-NetIPConfiguration
Get-NetIPAddress
# ping
Test-NetConnection
# tracert
Test-NetConnection -TraceRoute
# route
Get-NetRoute
# nslookup
Resolve-DnsName
([System.Net.Dns]::GetHostEntry($IP)).Hostname # IP > PC
([System.Net.Dns]::GetHostAddresses($computer)).IPAddressToString # PC > IP

Как проверить, открыт/закрыт ли порт, с помощью PowerShell?

New-Object -TypeName Net.Sockets.TcpClient -ArgumentList $computer, 135

Математические действия в PowerShell

Как вернуть абсолютное значение с помощью PowerShell?

[Math]::Abs(-12) #Returns 12
[Math]::Abs(-12.5) # Returns 12.5

Как округлить число в большую сторону с помощью PowerShell?

[Math]::Ceiling(1.4) #Returns 2
[Math]::Ceiling(1.9) #Returns 2

Как округлить число в меньшую сторону с помощью PowerShell?

[Math]::Floor(1.4) #Returns 1
[Math]::Floor(1.9) #Returns 1

Как вернуть максимум/минимум из двух значений с помощью PowerShell?

[Math]::Max(2,4) #Returns 4
[Math]::Max(-2,-4) #Returns -2
Как округлить десятичное значение до ближайшего целого значения с помощью PowerShell?
[Math]::Round(3.111,2) #Returns 3,11
[Math]::Round(3.999,2) #Returns 4

Как получить целое с округлением до меньшего по модулю с помощью PowerShell?

[Math]::Truncate(3.111) #Returns 3
[Math]::Truncate(3.999) #Returns 3

Как определить, является ли число чётным или нечётным, с помощью PowerShell?

[bool]($number%2)

Массивы

Для поиска минимального и максимального числа в списке необходимо использовать Measure-Object:

$list = 1,4,35,564,8,12,990
$result = $list | Measure-Object -Minimum -Maximum
$result.Minimum
$result.Maximum

Как создать массив с элементами, начинающимися с определенного префикса (“user01”, “user02”, …, “user10”), с помощью PowerShell?

$array = 1..10 | ForEach-Object -Process { "user$_" }

Как добавить новый путь (например: C:\SysinternalsSuite) к переменной среды Path с помощью PowerShell?

$env:Path += ';C:\SysinternalsSuite'
$env:Path = $env:Path + ';C:\SysinternalsSuite'

Сгенерировать 100 случайных чисел:

$numbers = for ($x = 1; $x -le 100; $x++)
{
Get-Random -Minimum 1 -Maximum 23
}

Как перечислить RDP-сессии с помощью PowerShell?

# Solution 1
Import-Module -Name Remotedesktopservices
Get-RDUserSession
# Solution 2
qwinsta.exe /server:$computer

Как перечислить удалённые RDP-сессии с помощью PowerShell?

Get-WSManInstance -ConnectionURI ('http://{0}:5985/wsman' -f $env:computername) shell -Enumerate | Select-Object -Property Owner, ClientIP

Как выйти из своей учётной записи с помощью PowerShell?

(Get-WmiObject -Class win32_operatingsystem -ComputerName $computer).Win32Shutdown(0)

Как скачать файл с помощью PowerShell?

Invoke-WebRequest -Uri 'http://www.nirsoft.net/utils/searchmyfiles.zip' -OutFile 'C:\tools\searchmyfiles.zip'

Комментариев нет:

Отправить комментарий