$string.Substring($string.IndexOf(".txt")-4, 4) # 2-й вариант (IndexOf)
### Группировка
if ((($1 -eq 1) -and ($2 -eq 2)) -or ($1 -ne 3)) {"$true"} else {"$false"} # два условия: (если $1 = 1 и $2 = 2) или $1 не равно 3. Если хотя бы одно из выражений равно True, то все условие относится к True и наоборот
-and # логическое И
-or # логическое ИЛИ
!(Test-Path $path) # логическое НЕТ (-not), если путь недоступен, вернет True
### Специальные символы
\d # число от 0 до 9 (20-07-2022 эквивалент: "\d\d-\d\d-\d\d\d\d")
\w # буква от "a" до "z" и от "A" до "Z" или число от 0 до 9
\s # пробел, эквивалент: " "
\n # новая строка
\b # маска, определяет начало и конец целого словосочетания для поиска
. # обозначает любой символ, кроме новой строки
\ # экранирует любой специальны символ (метасимвол). Используется, если нужно указать конкретный символ, вместо специального ({ } [ ] / \ + * . $ ^ | ?)
+ # повторяется 1 и более раз (\s+)
{1,25} # квантификатор, указывает количество повторений символа слева на право (от 1 до 25 раз)
[] # поиск совпадения любой буквы, например, [A-z0-9] от A до z и цифры от 0 до 9 ("192.168.1.1" -match "192.1[6-7][0-9]")
### Якори
^ или \A # определяет начало строки. $url -replace '^','https:' # добавить в начало;
$ или \Z # обозначают конец строки. $ip -replace "\d{1,3}$","0"
(?=text) # поиск слова слева. Пишем слева на право от искомого (ищет только целые словосочетания) "Server:\s(.{1,30})\s(?=$username)"
(?<=text) # поиск слова справа. $in_time -replace ".+(?<=Last)" # удалить все до слова Last
(?!text) # не совпадает со словом слева
(?<!text) # не совпадает со словом справа
### Группы захвата
$date = '12.31.2021'
$date -replace '^(\d{2}).(\d{2})','$2.$1' # поменять местами
$1 # содержимое первой группы в скобках
$2 # содержимое второй группы
### GetType
$srv.GetType() # узнать тип данных
$srv -is [string] # проверка на соответствие типа данных
$srv -isnot [System.Object] # проверка на несоответствие
$char = $srv.ToCharArray() # разбить строку [string] на массив [System.Array] из букв
$char.GetType() # тип данных: Char[]
[Object] # массив (BaseType:System.Array)
[DateTime] # формат времени (BaseType:System.ValueType)
$srv.Length # содержит количество символом строки переменной [string] или количество значений (строк) объекта
$srv.Chars(2) # отобразить 3-й символ в строке
$srv[2] # отобразить 3-ю строку в массиве
### Method
$srv.Insert(0,"https://") # добавить значение перед первым символом
$srv.Substring(4) # удалить (из всего массива) первые 4 символа
$srv.Remove(3) # удалить из всего массива все после 3 символа
$string = "123" # создать строку
$int = [convert]::ToInt32($string) # преобразовать строку в тип данных число
[string]::Concat($text,$num) # объеденить переменные в одну строку
[string]::Join(":",$text,$num) # объеденить используя разделитель
[string]::Compare($text,$num,$true) # выдает 0 при совпадении или 1/-1 при несовпадении, $true (без учета регистра) или $false (с учетом регистра)
[string]::Equals($text,$num) # производит сравнение двух строк и выдает $true при их совпадении или $false при несовпадении
[string]::IsNullOrEmpty($text) # проверяет наличие строки, если строка пуста $true, если нет $false
[string]::IsNullOrWhiteSpace($text2) # проверяет на наличие только символов пробел, табуляция или символ новой строки
### Date
(Get-Date).AddHours(-3)
$Date = (Get-Date -Format "dd/MM/yyyy hh:mm:ss")
$Date = Get-Date -f "dd/MM/yyyy" # получаем тип данных [string]
[DateTime]$gDate = Get-Date "$Date" # преобразовать в тип [DateTime]
[int32]$days=($fDate-$gDate).Days # получить разницу в днях
"5/7/07" -as [DateTime] # преобразовать входные данные в тип данных [DateTime]
New-TimeSpan -Start $VBRRP.CreationTimeUTC -End $VBRRP.CompletionTimeUTC # получить разницу во времени
### Time
(Measure-Command {ping ya.ru}).TotalSeconds # узнать только время выполнения
(Get-History)[-1] | select @{Name="RunTime"; Expression={$_.EndExecutionTime - $_.StartExecutionTime}},ExecutionStatus,CommandLine # посчитать время работы последней [-1] (select -Last 1) выполненной команды и ее узнать статус
$start_time = Get-Date # зафиксировать время до выполнения команды
$end_time = Get-Date # зафиксировать время по завершению
$time = $end_time - $start_time # высчитать время работы скрипта
Если условие if () является истенным ($True), выполнить действие в {}
Если условие if () является ложным ($False), выполнить действие не обязательного оператора else
Условие Elseif идёт после условия if для проверки дополнительных условий перед выполнение оператора else. Оператор, который первый вернет $True, отменит выполнение следующих дополнительных условий
Если передать переменную в условие без оператора, то будет проверяться наличие значения у переменной на $True/$False
if ((tnc $srv -Port 80).TcpTestSucceeded) {"Opened port"} else {"Closed port"}
### Операторы
-eq # равно (equal)
-ceq # учитывать регистр
-ne # не равно (not equal)
-gt # больше (greater)
-ge # больше или равно
-lt # меньше (less)
-le # меньше или равно
### Foreach
$list = 100..110 # создать массив из цифр от 100 до 110
foreach ($srv in $list) {ping 192.168.3.$srv -n 1 -w 50} # $srv хранит текущий элемент из $list и повторяет команду до последнего элемента в массиве
$foreach.Current # текущий элемент в цикле
$foreach.Reset() # обнуляет итерацию, перебор начнется заново, что приводит к бесконечному циклу
$foreach.MoveNext() # переход к следующему элементу в цикле
### ForEach-Object (%)
100..110 | %{ping -n 1 -w 50 192.168.3.$_ > $null
if ($LastExitCode -eq 0) {Write-Host "192.168.3.$_" -ForegroundColor green
} else {
Write-Host "192.168.3.$_"-ForegroundColor Red}}
% # передать цикл через конвеер (ForEach-Object)
$_ # переменная цикла и конвеера ($PSItem)
gwmi Win32_QuickFixEngineering | where {$_.InstalledOn.ToString() -match "2022"} | %{($_.HotFixID.Substring(2))} # gwmi создает массив, вывод команды передается where для поиска подходящих под критерии объектов. По конвееру передается в цикл для удаления первых (2) символов методом Substring из всех объектов HotFixID.
### While
$srv = "yandex.ru"
$out2 = "Есть пинг"
$out3 = "Нет пинга"
$out = $false # предварительно сбросить переменную, While проверяет условие до запуска цикла
While ($out -eq $false){ # пока условие является $true, цикл будет повторяться
Get-ItemProperty -Path $path\* | select FullName,CreationTime,LastWriteTime # свойства файлов содержимого директории, дата их создания и последнего изменения
New-Item -Path "C:\test\" -ItemType "Directory" # создать директорию (Alias: mkdir/md)
New-Item -Path "C:\test\file.txt" -ItemType "File" -Value "Добавить текст в файл" # создать файл
"test" > "C:\test\file.txt" # заменить содержимое
"test" >> "C:\test\file.txt" # добавить строку в файл
New-Item -Path "C:\test\test\file.txt" -Force # ключ используется для создания отсутствующих в пути директорий или перезаписи файла если он уже существует
Move-Item # перемещение объектов (Alias: mv/move)
Remove-Item "$path\" -Recurse # удаление всех файлов внутри каталога, без запроса подверждения (Alias: rm/del)
Remove-Item $path -Recurse -Include "*.txt","*.temp" -Exclude "log.txt" # удалить все файлы с расширением txt и temp ([Array]), кроме log.txt
Rename-Item "C:\test\*.*" "*.jpg" # переименовать файлы по маске (Alias: ren)
Copy-Item # копирование файлов и каталогов (Alias: cp/copy)
Copy-Item -Path "C:\*.txt" -Destination "C:\test\" # знак '\' в конце Destination используется для переноса папки внутрь указанной, отсутствие, что это новое имя директории
Copy-Item -Path "C:\*" -Destination "C:\test\" -Include '*.txt','*.jpg' # копировать объекты с указанным расширением (Include)
Copy-Item -Path "C:\*" -Destination "C:\test\" -Exclude '*.jpeg' # копировать объекты, за исключением файлов с расширением (Exclude)
$log = Copy-Item "C:\*.txt" "C:\test\" -PassThru # вывести результат копирования (логирование) в переменную, можно забирать строки с помощью индексов $log[0].FullName
$size = "{0:N1} Mb" -f ((ls $_.FullName -Recurse -Force | Measure-Object -Property Length -Sum).Sum / 1Mb) # посчитать размер всех дочерних директория в Mb (округлить до одного символа после запятой)
cmdkey /generic:"TERMSRV/$srv" /user:"$username" /pass:"$password" # добавить указанные креды аудентификации на на терминальный сервер для подключения без пароля
mstsc /admin /v:$srv # авторизоваться
cmdkey /delete:"TERMSRV/$srv" # удалить добавленные креды аудентификации из системы
rundll32.exe keymgr.dll,KRShowKeyMgr # хранилище Stored User Names and Password
Get-Service VaultSvc # служба для работы Credential Manager
Install-Module CredentialManager # установить модуль управления Credential Manager к хранилищу PasswordVault из PowerShell
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]'Tls11,Tls12' # для устаноки модуля
Get-StoredCredential # получить учетные данные из хранилища Windows Vault
Get-StrongPassword # генератор пароля
New-StoredCredential -UserName test -Password "123456" # добавить учетную запись
Remove-StoredCredential # удалить учетную запись
$Cred = Get-StoredCredential | where {$_.username -match "admin"}
Get-Service -cn $srv | Out-GridView -Title "Service $srv" -OutputMode Single –PassThru | Restart-Service # перезапустить выбранную службу
### Out-File
Read-Host –AsSecureString | ConvertFrom-SecureString | Out-File "$env:userprofile\desktop\password.txt" # писать в файл. Преобразовать пароль в формат SecureString с использованием шифрования Windows Data Protection API (DPAPI)
### Get-Content (gc/cat/type)
$password = gc "$env:userprofile\desktop\password.txt" | ConvertTo-SecureString # читать хэш пароля из файла с помощью ключей, хранящихся в профиле текущего пользователя, который невозможно прочитать на другом копьютере
(Get-ItemProperty HKCU:\SOFTWARE\Microsoft\Office\16.0\Outlook\Profiles\Outlook\9375CFF0413111d3B88A00104B2A6676\00000002)."New Signature" # отобразить значение (Value) свойства (Property) Items
Set-ItemProperty -Path $reg_path -Name "New Signature" -Value $sig_name # изменить или добавить в корне ветки (Path) свойство (Name) со значением (Value)
Get-SmbConnection # список активных сессий и используемая версия SMB (Dialect)
Get-SmbOpenFile | select ClientUserName,ClientComputerName,Path,SessionID # список открытых файлов
Get-SmbShare # список сетевых папок
New-SmbShare -Name xl-share -Path E:\test # создать новую общую сетевую папку (расшарить)
-EncryptData $True # включить шифрование SMB
-Description # имя в сетевом окружении
-ReadAccess "domain\username" # доступ на чтение
-ChangeAccess # доступ на запись
-FullAccess # полный доступ
-NoAccess ALL # нет прав
-FolderEnumerationMode [AccessBased | Unrestricted] # позволяет скрыть в сетевой папке объекты, на которых у пользователя нет доступа с помощью Access-Based Enumeration (ABE)
Get-SmbShare xl-share | Set-SmbShare -FolderEnumerationMode AccessBased # ключить ABE для всех расшаренных папок
Remove-SmbShare xl-share -force # удалить сетевой доступ (шару)
Get-SmbShareAccess xl-share # вывести список доступов безопасности к шаре
Revoke-SmbShareAccess xl-share -AccountName Everyone –Force # удалить группу из списка доступов
Grant-SmbShareAccess -Name xl-share -AccountName "domain\XL-Share" -AccessRight Change –force # изменить/добавить разрешения на запись (Full,Read)
Get-WmiObject -List # отобразить все классы пространства имен "root\cimv2" (по умолчанию), свойства (описывают конфигурацию и текущее состояние управляемого ресурса) и их методы (какие действия позволяет выполнить над этим ресурсом)
Get-WmiObject -List | Where-Object {$_.name -match "video"} # поиск класса по имени, его свойств и методов
Get-WmiObject -ComputerName localhost -Class Win32_VideoController # отобразить содержимое свойств класса
gwmi -List | where name -match "service" | ft -auto # если в таблице присутствуют Methods, то можно взаимодействовать {StartService, StopService}
gwmi -Class win32_service | select * # отобразить список всех служб и всех их свойств
Get-CimInstance Win32_service # обращается на прямую к "root\cimv2"
Get-CimInstance -ComputerName $srv Win32_OperatingSystem | select LastBootUpTime # время последнего включения
gwmi -ComputerName $srv -Class Win32_OperatingSystem | select LocalDateTime,LastBootUpTime # текущее время и время последнего включения
gwmi win32_service -Filter "name='Zabbix Agent'" # отфильтровать вывод по имени
REG ADD HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\CredSSP\Parameters /v AllowEncryptionOracle /t REG_DWORD /d 2 # отключить на клиентском компьютере проверку версии CredSSP, если на целевом комьютере-сервере не установлены обновления KB4512509 от мая 2018 года
OU (Organizational Unit) - организационные подразделения (type), используются для упорядочения объектов
Container - так же используется для упорядочения объектов, контейнеры в отличии от подраделений не могут быть переименованы, удалены, созданы или связаны с объектом групповой политики (Computers, Domain Controllers, Users)
DN (Distinguished Name) — уникальное имя объекта и местоположение в лесу AD. В DN описывается содержимое атрибутов в дереве (путь навигации), требуемое для доступа к конкретной записи или ее поиска
CN (Common Name) - общее имя
(Get-ADObject (Get-ADRootDSE).DefaultNamingContext -Properties wellKnownObjects).wellKnownObjects # отобразить отобразить контейнеры по умолчанию
redircmp OU=Client Computers,DC=root,DC=domain,DC=local # изменить контейнер компьютеров по умолчанию
redirusr # изменить контейнер пользователей по умолчанию
Удаленные объекты хранятся в корзине AD в течении времени захоронения (определяется в атрибуте домена msDS-deletedObjectLifetime), заданном для леса. По умолчанию это 180 дней. Если данный срок прошел, объект все еще остается в контейнере Deleted Objects, но большинство его атрибутов и связей очищаются (Recycled Object). После истечения периода tombstoneLifetime (по умолчанию также 180 дней, но можно увеличить) объект полностью удаляется из AD автоматическим процессом очистки.
Get-ADForest domain.local # отобразить уровень работы леса
Set-ADForestMode -Identity domain.local -ForestMode Windows2008R2Forest -force # увеличить уровень работы леса
Get-ADOptionalFeature "Recycle Bin Feature" | select-object name,EnabledScopes # если значение EnabledScopes не пустое, значит в домене корзина Active Directory включена
Get-ADObject -Filter 'Name -like "*tnas*"' -IncludeDeletedObjects # найти удаленную (Deleted: True) УЗ (ObjectClass: user) в AD
Get-ADObject -Filter 'Name -like "*tnas*"' –IncludeDeletedObjects -Properties *| select-object Name, sAMAccountName, LastKnownParent, memberOf, IsDeleted | fl # проверить значение атрибута IsDeleted, контейнер, в котором находился пользователе перед удалением (LastKnownParent) и список групп, в которых он состоял
Restore-ADObject -Identity "3dc33c7c-b912-4a19-b1b7-415c1395a34e" # восстановить по значению атрибута ObjectGUID
Get-ADObject -Filter 'SAMAccountName -eq "tnas-01"' –IncludeDeletedObjects | Restore-ADObject # восстановить по SAMAccountName
Get-ADObject -Filter {Deleted -eq $True -and ObjectClass -eq 'group' -and Name -like '*Allow*'} –IncludeDeletedObjects | Restore-ADObject –Verbose # восстановить группу или компьютер
### thumbnailPhoto
$photo = [byte[]](Get-Content C:\Install\adm.jpg -Encoding byte) # преобразовать файл картинки в массив байтов (jpeg/bmp файл, размером фото до 100 Кб и разрешением 96×96)
Set-ADUser support4 -Replace @{thumbnailPhoto=$photo} # задать значение атрибута thumbnailPhoto
Get-ADDomainController # выводит информацию о текущем контроллере домена (LogonServer), который используется данным компьютером для аутентификации (DC выбирается при загрузке в соответствии с топологией сайтов AD)
Get-ADDomainController -Discover -Service PrimaryDC # найти контроллер с ролью PDC в домене
Get-ADDomainController -Filter * | ft HostName,IPv4Address,Name,Site,OperatingSystem,IsGlobalCatalog # список все DC, принадлежность к сайту, версии ОС и GC
При загрузке ОС служба NetLogon делает DNS запрос со списком контроллеров домена (к SRV записи _ldap._tcp.dc._msdcs.domain_), DNS возвращает список DC в домене с записью Service Location (SRV). Клиент делает LDAP запрос к DC для определения сайта AD по своему IP адресу. Клиент через DNS запрашивает список контроллеров домена в сайте (в разделе _tcp.sitename._sites...).
USN (Update Sequence Numbers) - счетчик номера последовательного обновления, который существует у каждого объекта AD. При репликации контроллеры обмениваются значениями USN, объект с более низким USN будет при репликации перезаписан объектом с более высоким USN. Находится в свойствах - Object (включить View - Advanced Features). Каждый контроллер домена содержит отдельный счетчик USN, который начинает отсчет в момент запуска процесса Dcpromo и продолжает увеличивать значения в течение всего времени существования контроллера домена. Значение счетчика USN увеличивается каждый раз, когда на контроллере домена происходит транзакция, это операции создания, обновления или удаления объекта.
Get-ADDomainController -Filter * | % { # отобразить USN объекта на всех DC в домене
dcpromo /forceremoval # принудительно выполнит понижение в роли контроллера домена до уровня рядового сервера. После понижения роли выполняется удаление всех ссылок в домене на этот контроллер. Далее производит включение сервера в состав домена, и выполнение обратного процесса, т.е. повышение сервера до уровня контроллера домена.
nltest /DSGETDC:$env:userdnsdomain # узнать на каком DC аудентифицирован хост (Logon Server)
nltest /SC_RESET:$env:userdnsdomain\srv-dc2.$env:userdnsdomain # переключить компьютер на другой контроллер домена AD вручную (The command completed successfully)
Get-ADComputer –Identity $env:computername -Properties PasswordLastSet # время последней смены пароля на сервере
Test-ComputerSecureChannel –verbose # проверить доверительные отношения с доменом (соответствует ли локальный пароль компьютера паролю, хранящемуся в AD)
PasswordNeverExpires=True # срок действия пароля не истекает - да
Set-ADAccountPassword support4 -Reset -NewPassword (ConvertTo-SecureString -AsPlainText "password" -Force -Verbose) # изменить пароль учетной записи
Set-ADUser -Identity support4 -ChangePasswordAtLogon $True # смена пароля при следующем входе в систему
$day = (Get-Date).adddays(-90)
Get-ADUser -filter {(passwordlastset -le $day)} | ft # пользователи, которые не меняли свой пароль больше 90 дней
$day = (Get-Date).adddays(-30)
Get-ADUser -filter {(Created -ge $day)} -Property Created | select Name,Created # Новые пользователи за 30 дней
$day = (Get-Date).adddays(-360)
Get-ADUser -Filter {(LastLogonTimestamp -le $day)} -Property LastLogonTimestamp | select Name,SamAccountName,@{n='LastLogonTimestamp';e={[DateTime]::FromFileTime($_.LastLogonTimestamp)}} | sort -Descending LastLogonTimestamp # пользователи, которые не логинились больше 360 дней. Репликация атрибута LastLogonTimestamp составляет от 9 до 14 дней.
Get-ADReplicationPartnerMetadata -Target dc-01 | select Partner,LastReplicationAttempt,LastReplicationSuccess,LastReplicationResult,LastChangeUsn # время последней и время успешной репликации с партнерами
Get-ADReplicationUpToDatenessVectorTable -Target dc-01 # Update Sequence Number (USN) увеличивается каждый раз, когда на контроллере домена происходит транзакция (операции создания, обновления или удаления объекта), при репликации DC обмениваются значениями USN, объект с более низким USN при репликации будет перезаписан высоким USN.
repadmin /replsummary # отображает время последней репликации на всех DC по направлению (Source и Destination) и их состояние с учетом партнеров
repadmin /showrepl $srv # отображает всех партнеров по реплкации и их статус для всех разделов Naming Contexts (DC=ForestDnsZones, DC=DomainDnsZones, CN=Schema, CN=Configuration)
repadmin /replicate $srv2 $srv1 DC=domain,DC=local # выполнить репликацию с $srv1 на $srv2 только указанный раздела домена
repadmin /Queue $srv # отображает кол-во запросов входящей репликации (очередь), которое необходимо обработать (причиной может быть большое кол-во партнеров или формирование 1000 объектов скриптом)
Error: 1722 - сервер rpc недоступен (ошибка отката репликации). Проверить имя домена в настройках сетевого адаптера, первым должен идти адрес DNS-сервера другого контроллера домена, вторым свой адрес.
Get-Service -ComputerName $srv -Name RpcSs -RequiredServices # зависимые службы
Зависимые службы RPC:
"Служба сведений о подключенных сетях" - должен быть включен отложенный запуск. Если служба срабатывает до "службы списка сетей", может падать связь с доменом (netlogon)
"Центр распространения ключей Kerberos"
"DNS-сервер"
nslookup $srv
tnc $srv -p 135
repadmin /retry # повторить попытку привязки к целевому DC, если была ошибка 1722 или 1753 (RPC недоступен)
repadmin /showrepl $srv
Last attempt @ 2022-07-15 10:46:01 завершена с ошибкой, результат 8456 (0x2108) # при проверки showrepl этого партнера, его ошибка: 8457 (0x2109)
Last success @ 2022-07-11 02:29:46 # последний успех
Когда репликация автоматически отключена, ОС записывает в DSA - not writable одно из четырех значений:
#define DSA_WRITABLE_GEN 1 - версия леса несовместима сОС
#define DSA_WRITABLE_NO_SPACE 2 - на диске, где размещена база данных Active Directory или файлы журналов (логи), недостаточно свободного места
#define DSA_WRITABLE_USNROLLBCK 4 - откат USN произошел из-за неправильного отката базы данных Active Directory во времени (восстановление из снапшота)
Загрузиться в режиме восстанавления WinRE (Windows Recovery Environment) - Startup Settings - Restart - DSRM (Directory Services Restore Mode)
reagentc /boottore # shutdown /f /r /o /t 0 # перезагрузка в режиме WinRE - ОС на базе WinPE (Windows Preinstallation Environment), образ winre.wim находится на скрытом разделе System Restore
На контроллере домена единственная локальная учетная запись — администратор DSRM. Пароль создается при установке роли контроллера домена ADDS на сервере (SafeModeAdministratorPassword).
ntdsutil
activate instance ntds
Files
Info
integrity # проверить целостность БД
Ошибка: Failed to open DIT for AD DS/LDS instance NTDS. Error -2147418113
mkdir c:\ntds_bak
xcopy c:\Windows\NTDS\*.* c:\ntds_bak # backup содержимого каталога с БД
При создании backup DC через WSB, создается копия состояния системы (System State), куда попадает база AD (NTDS.DIT), объекты групповых политик, содержимое каталога SYSVOL, реестр, метаданные IIS, база AD CS, и другие системные файлы и ресурсы. Резервная копия создается через службу теневого копирования VSS.
Get-WindowsFeature Windows-Server-Backup # проверить установлена ли роль
Add-Windowsfeature Windows-Server-Backup –Includeallsubfeature # установить роль
Get-DnsServerResourceRecord -ZoneName domain.local -RRType A # вывести все А-записи в указанной зоне
Add-DnsServerResourceRecordA -Name new-host-name -IPv4Address 192.168.1.100 -ZoneName domain.local -TimeToLive 01:00:00 -CreatePtr # создать А-запись и PTR для нее
dfsutil /AddFtRoot /Server:\\$srv /Share:public # на новой машине предварительно создать корень на основе домена
dfsutil /root:\\domain.sys\public /import:C:\export-dfs.txt /<verify /set # Import (перед импортом данных в существующий корень DFS, утилита создает резервную копию конфигурации корня в текущем каталоге, из которого запускается утилита dfsutil)
/verify # выводит изменения, которые будут внесены в процессе импорта, без применения
/set # меняет целевое пространство имен путем полной перезаписи и замены на конфигурацию пространства имен из импортируемого файла
/merge # импортирует конфигурацию пространства имен в дополнение к существующей конфигурации для слияния, параметры из файла конфигурации будут иметь больший приоритет, чем существующие параметры пространства имен
Export-DfsrClone # экспортирует клонированную базу данных репликации DFS и параметры конфигурации тома
Get-DfsrCloneState # получает состояние операции клонирования базы данных
Import-DfsrClone # импортирует клонированную базу данных репликации DFS и параметры конфигурации тома
net use x: \\$srv1\public\* # примонтировать диск
Get-DfsrFileHash x:\* | Out-File C:\$srv1.txt # забрать hash всех файлов диска в файл (файлы с одинаковыми хешами всегда являются точными копиями друг друга)
Set-PowerCLIConfiguration -Scope AllUsers -InvalidCertificateAction ignore -confirm:$false # eсли используется самоподписанный сертификат, изменить значение параметра InvalidCertificateAction с Unset на Ignore/Warn
Set-PowerCLIConfiguration -Scope AllUsers -ParticipateInCeip $false # отключить уведомление сбора данных через VMware Customer Experience Improvement Program (CEIP)
Get-ClientAccessService | fl identity, *uri* # настройки службы автообнаружения в Exchange 2016
Get-ClientAccessService -Identity $srv | Set-ClientAccessService -AutoDiscoverServiceInternalUri https://mail.domain.ru/Autodiscover/Autodiscover.xml # изменить на внешний адрес
Get-OutlookAnywhere # OA позволяет клиентам Outlook подключаться к своим почтовым ящикам за пределами локальной сети (без использования VPN)
Get-WebServicesVirtualDirectory
Get-OwaVirtualDirectory
Get-ActiveSyncVirtualDirectory
Get-OabVirtualDirectory # виртуальная директория автономной адресной книги
MS (Mailbox) - сервер с БД почтовых ящиков и общих папок, отвечает только за их размещение и не выполняет маршрутизацию никаких сообщений.
CAS (Client Access Server) - обработка клиентских подключений к почтовым ящикам, которые создаются клиентами Outlook Web Access (HTTP для Outlook Web App), Outlook Anywhere, ActiveSync (для мобильных устройств), интернет протоколы POP3 и IMAP4, MAPI для клиентов Microsoft Outlook.
Hub Transort - ответвечает за маршрутизацию сообщений интернета и инфраструктурой Exchange, а также между серверами Exchange. Сообщения всегда маршрутизируются с помощью роли транспортного сервера-концентратора, даже если почтовые ящики источника и назначения находятся в одной базе данных почтовых ящиков.
Relay - роль пограничного транспортного сервера (шлюз SMTP в периметре сети).
SCP (Service Connection Point) - запись прописывается в AD, при создание сервера CAS. Outlook запрашивает SCP, выбирает те, которые находятся в одном сайте с ним и по параметру WhenCreated – по дате создания, выбирая самый старый.
Autodiscover. Outlook выбирает в качестве сервера Client Access тот, который прописан в атрибуте RPCClientAccessServer базы данных пользователя. Сведения о базе данных и сервере mailbox, на котором она лежит, берутся из AD.
Get-MessageTrackingLog -Start (Get-Date).AddHours(-24) -ResultSize Unlimited | where {[string]$_.recipients -like "*@yandex.ru"} # вывести сообщения за последние 24 часа, где получателем был указанный домен
-Start "04/01/2023 09:00:00" -End "04/01/2023 18:00:00" - поиск по указанному промежутку времени
-MessageSubject "Тест" - поиск по теме письма
-Recipients "support4@domain.ru" - поиск по получателю
-Sender - поиск по отправителю
-EventID – поиск по коду события сервера (RECEIVE, SEND, FAIL, DSN, DELIVER, BADMAIL, RESOLVE, EXPAND, REDIRECT, TRANSFER, SUBMIT, POISONMESSAGE, DEFER)
-Server – поиск на определенном транспортном сервере
Get-MailboxFolderStatistics -Identity "support4" -FolderScope All | select Name,ItemsInFolder,FolderSize # отобразить кол-во писем и размер в каждой папке
Get-MailboxStatistics "support4" | select DisplayName,LastLoggedOnUserAccount,LastLogonTime,LastLogoffTime,ItemCount,TotalItemSize,DeletedItemCount,TotalDeletedItemSize,Database,ServerName # общее кол-во писем, их размер, время последнего входа и выхода, имя сервера и БД
Get-Mailbox -Server s2 | Get-MailboxStatistics | where {$_.Lastlogontime -lt (get-date).AddDays(-30)} | Sort Lastlogontime -desc | ft displayname,Lastlogontime,totalitemsize # ящики, которые не использовались 30 и более дней
Enable-Mailbox -Identity support9 -Database test_base # создать почтовый ящик для существующего пользователя в AD
New-Mailbox -Name $login -UserPrincipalName "$login@$domain" -Database $select_db -OrganizationalUnit $path -Password (ConvertTo-SecureString -String "$password" -AsPlainText -Force) # создать новый почтовый ящик без привязки к пользователю AD
Set-MailBox "support4" -PrimarySmtpAddress support24@domain.ru -EmailAddressPolicyEnabled $false # добавить и изменить основной SMTP-адрес электронной почты для пользователя
Set-Mailbox -Identity "support4" -DeliverToMailboxAndForward $true -ForwardingSMTPAddress "username@outlook.com" # включить переадресацию почты (электронная почта попадает в почтовый ящик пользователя support4 и одновременно пересылается по адресу username@outlook.com)
Remove-MoveRequest -Identity $db_name # завершить процесс перемещения (убрать статус перемещения с почтового ящика и очистить список перемещений)
Get-MailboxDatabase | Select Name, MailboxRetention # после перемещения ящиков, размер базы не изменится, полное удаление из базы произойдет, как пройдет количество дней, выставленное в параметре MailboxRetention
Set-MailboxDatabase -MailboxRetention '0.00:00:00' -Identity $db_name # изменить значение
Get-Service | Where {$_ -match "exchange"} | Restart-Service
Get-MailboxDatabase -Server exch-01 # список баз данных на MX-сервере
New-MoveRequest -Identity "support4" -TargetDatabase it_2022 # переместить почтовый ящик в новую БД
Move-Databasepath $db_name –EdbFilepath "F:\DB\$db_name\$db_name.edb" –LogFolderpath "E:\DB\$db_name\logs\" # переместить БД и транзакционные логи на другой диск
Set-MailboxDatabase -CircularLoggingEnabled $true -Identity $db_name # включить циклическое ведение журнала (Circular Logging), где последовательно пишутся 4 файла логов по 5 МБ, после чего первый лог-файл перезаписывается
Set-MailboxDatabase -CircularLoggingEnabled $false -Identity $db_name # отключить циклическое ведение журнала
Get-MailboxDatabase -Server "ukh-exch-mx-01" -Status | select EdbFilePath,LogFolderPath,LogFilePrefix # путь к БД, логам, имя текущего актуального лог-файла
New-MailboxRepairRequest -Database it2 -CorruptionType ProvisionedFolder, SearchFolder, AggregateCounts, Folderview # запустить последовательный (в конкретный момент времени не доступен один почтовый ящик) тест и исправление ошибок на прикладном уровне
Get-MailboxRepairRequest -Database it2 # прогресс выполнения
Позволяет исправить:
ProvisionedFolder – нарушения логической структуры папок
SearchFolder – ошибки в папках поиска
AggregateCounts – проверка и исправление информации о количестве элементов в папках и их размере
При отправке/получении любого письма Exchange сначала вносит информацию в транзакционный лог, и только потом сохраняет элемент непосредственно в базу данных. Размер одного лог файла - 1 Мб. Есть три способа урезания логов: DAG, Backup на базе Volume Shadow Copy, Circular Logging.
State: Dirty Shutdown - несогласованное состояние, означает, что часть транзакций не перенесена в базу, например, после того, как была осуществлена аварийная перезагрузка сервера.
eseutil /ml E:\MS_Exchange_2010\MailBox\db_name\E18 # проверка целостности транзакционных логи, если есть логи транзакций и они не испорчены, то можно восстановить из них, из файла E18 считываются все логи, должен быть статус - ОК
Soft Recovery (мягкое восстановление) - необходимо перевести базу в состояние корректного отключения (Clear shutdown) путем записи недостающих файлов журналов транзакций в БД.
eseutil /R E18 /a /i /l E:\MS_Exchange_2010\MailBox\db_name\ /d D:\MS_Exchange_2010\Mailbox\db_name\db_name.edb # если с логами что-то не так, можно попробовать восстановить базу игнорируя ошибку в логах
/p - удалит поврежденные страницы, эта информация будет удалена из БД и восстановит целостность
esetuil /d D:\MS_Exchange_2010\Mailbox\db_name\db_name.edb # выполнить дефрагментацию (если был потерян большой объем данных, то может сильно снизиться производительность)
После выполнения команд необходимо вручную удалить все файлы с расширением log в папке MDBDATA, перед попыткой смонтировать базу данных.
isinteg -s "db_name.edb" -test alltests # проверьте целостность базы данных
isinteg -s "server_name" -fix -test -alltests # если проверка будет провалена. Выполнять команду до тех пор, пока у всех ошибок не станет статус 0 или статус не перестанет меняться, иногда необходимо 3 прохода для достижения результата.
Log Required # требуются ли файлы журналов, необходимые базе, чтобы перейти в согласованное состояние. Если база размонтирована корректно, то это значение будет равняться 0.
mount-Database -force db_name # примонтировать БД
Get-MailboxDatabase –Status db_name | fl Mounted # статус БД
New-MailboxRepairRequest -Database db_name -CorruptionType SearchFolder,AggregateCounts,ProvisionedFolder,FolderView # восстановление логической целостности данных
После этого восстановить Index.
Если индексы не восстанавливаются, но БД монтируется, то перенести почтовые ящики в новую БД.
2. Восстановить БД с логами из Backup в любое место.
3. Запустить мягкое восстановление БД (Soft Recovery).
4. Создать новую БД.
5. Создать Recovery Database и смонтировать в нее восстановленную из бэкапа БД, скопировать из неё почтовые ящики в новую БД и переключить на них пользователей.
6. Если использовать Dial Tone Recovery, то так же перенести из временной БД промежуточные данные почтовых ящиков.
1. Восстановить целостность Soft Repair или Hard Recovery.
2. Создать новую БД. Указывать в свойствах: «база может быть перезаписана при восстановлении».
3. Если база была только что оздана и еще не была подмонтирована, то эта папка будет пуста, туда перемещаем базу из Backup, которая была обработана ESEUTIL вместе со всеми файлами. Указать имя .edb такое же, которое было при создании новой базы.
4. Монтируем базу.
5. Перенацеливаем ящики со старой (Mailbox_DB_02), неисправной базы, на новую базу (Mailbox_DB_02_02):
Get-Mailbox -Database "MailboxDB" | Set-Mailbox -Database "TempDB" # перенацелить ящики с одной БД (нерабочей) на другую (пустую)
Get-Mailbox -Database TempDB # отобразить почтовые ящики в БД TempDB
Restart-Service MSExchangeIS # перезапустить службу Mailbox Information Store (банка данных), иначе пользователи будут по-прежнему пытаться подключиться к старой БД
iisreset
Get-Mailbox -Database "TempDB" | Set-Mailbox -Database "MailboxDB" # после восстановления старой БД, нужно переключить пользователей с временной БД обратно
После этого сделать слияние с временной БД с помощью Recovery.
New-MailboxDatabase –Recovery –Name RecoveryDB –Server $exch_mx –EdbFilePath "D:\TempDB\TempDB.edb" -LogFolderPath "D:\TempDB" # для переноса новых писем из временной БД в основную необходим только сам файл TempDB.edb со статусом Clean Shutdown, из нее необходимо создать служебную БД (ключ -Recovery)
New-MailboxRestoreRequest –SourceDatabase RecoveryDB –SourceStoreMailbox support –TargetMailbox support # скопировать данные почтового ящика с DisplayName: support из RecoveryDB в почтовый ящик с псевдонимом support существующей базы. По умолчанию ищет в почтовой базе совпадающие LegacyExchangeDN либо проверяет совпадение адреса X500, если нужно восстановить данные в другой ящик, нужно указывать ключ -AllowLegacyDNMisMatch
New-MailboxRestoreRequest –SourceDatabase RecoveryDB –SourceStoreMailbox support –TargetMailbox support –TargetRootFolder "Restore" # скопировать письма в отдельную папку в ящике назначения (создается автоматически), возможно восстановить содержимое конкретной папки -IncludeFolders "#Inbox#"
Get-MailboxRestoreRequest | Get-MailboxRestoreRequestStatistics # статус запроса восстановления
Get-MailboxRestoreRequestStatistics -Identity support
Get-MailboxRestoreRequest -Status Completed | Remove-MailboxRestoreRequest # удалить все успешные запросы
Get-TransportConfig | select MaxSendSize, MaxReceiveSize # ограничение размера сообщения на уровне траспорта (наименьший приоритет, после коннектора и почтового ящика).
New-TransportRule -Name AttachmentLimit -AttachmentSizeOver 15MB -RejectMessageReasonText "Sorry, messages with attachments over 15 MB are not accepted" # создать транспортное правило для проверки размера вложения
Get-ReceiveConnector | select Name,MaxMessageSize,RemoteIPRanges,WhenChanged # ограничения размера сообщения на уровне коннектора (приоритет ниже, чем у почтового ящика)
Set-ReceiveConnector ((Get-ReceiveConnector).Identity)[-1] -MaxMessageSize 30Mb # изменить размер у последнего коннектора в списке (приоритет выше, чем у траспорта)
Search-AdminAuditLog -StartDate "02/20/2022" | ft CmdLetName,Caller,RunDate,ObjectModified -Autosize # поиск событий истории выполненых команд в журнале аудита Exchange
Error Exchange 452 4.3.1 Insufficient system resources - окончание свободного места на диске, на котором находятся очереди службы Exchange Hub Transport, за мониторинг отвечает компонент доступных ресурсов Back Pressure, который в том числе отслеживает свободное место на диске
Порог Medium (90%) — перестать принимать по SMTP почту от внешних отправителей (почта от MAPI клиентов при этом обрабатывается)
Порог High (99%) — обработка потока почты полностью прекращается
Решение: очистить, например логи IIS (C:\inetpub\logs\LogFiles\W3SVC1), увеличить размер диска, отключить мониторинг Back Pressure (плохой вариант) или перенести транспортные очередь на другой диск достаточного объёма.
C:\Program Files\Microsoft\Exchange Server\V15\Bin\EdgeTransport.exe.config # конфигурационный файл, который содержит путь к бд с очередью (блок <appSettings> ключи <add key="QueueDatabasePath" value="$new_path" /> и QueueDatabaseLoggingPath)
Для переноса БД, необходимо переместить существующие файлы базы данных Mail.que и Trn.chk (контрольные точки для отслеживания записи в логах) из исходного местоположения в новое. Переместите существующие файлы журнала транзакций Trn.log, Trntmp.log, Trn nnnn.log , Trnres00001.jrs, Trnres00002.jrs и Temp.edb из старого расположения в новое. tmp.edb — временный файл для проверки схемы самой базы, перености не нужно.
После запуска службы транспорта удалить старую базу данных очереди и файлы журнала транзакций из старого расположения.
Get-MailboxDatabase -Status | ft Name, DatabaseSize, AvailableNewMailboxSpace
DatabaseSize - текущий размер базы
AvailableNewMailboxSpace - объём пустых страниц, пространство, которое можно освободить при дефрагментации
(DatabaseSize — AvailableNewMailboxSpace) x 1,1 - необходимо дополнительно иметь свободного места не менее 110% от текущего размера базы (без учета пустых страниц)
Install-WindowsFeature -Name Failover-Clustering -ComputerName EXCH-MX-01 # основывается на технологии Windows Server Failover Cluster
New-DatabaseAvailabilityGroup -Name dag-01 -WitnessServer fs-05 -WitnessDirectory C:\witness_exchange1 # создать группу с указанием файлового свидетеля для кворума
Quorum - это процесс голосования, в котором для принятия решения нужно иметь большинство голосов, что бы сделать текущую копию базы данных активной.
WitnessDirectory — используется для хранения данных файлового ресурса-свидетеля.
Set-DatabaseAvailabilityGroup dag-01 –DatabaseAvailabilityGroupIPAdress $ip # изменить ip-адрес группы
Get-DatabaseAvailabilityGroup # список всех групп
Get-DatabaseAvailabilityGroup -Identity dag-01
Add-DatabaseAvailabilityGroupServer -Identity dag-01 -MailboxServer EXCH-MX-01 # добавить первый сервер (все БД на серверах в DAG должны храниться по одинаковому пути)
Resume-MailboxDatabaseCopy -Identity db_name\EXCH-MX-04 # возобновить (Resume) или запустить копирование бд на EXCH-MX-04 (из статуса Suspended в Healthy)
Suspend-MailboxDatabaseCopy -Identity db_name\EXCH-MX-04 # остановить копирование (в статус Suspended)
Set-MailboxDatabaseCopy -Identity db_name\EXCH-MX-04 -ActivationPreference 1 # изменить приоритет для активации копий БД (какую использовать, 1 – самое высокое значение)
Move-ActiveMailboxDatabase db_name -ActivateOnServer EXCH-MX-04 -MountDialOverride:None -Confirm:$false # включить копию БД в DAG (переключиться на активную копию)
Remove-MailboxDatabaseCopy -Identity db_name\EXCH-MX-04 -Confirm:$False # удалить копии пассивной базы в DAG-группе (у БД должно быть отключено ведение циклического журнала)
Remove-DatabaseAvailabilityGroupServer -Identity dag-01 -MailboxServer EXCH-MX-04 -ConfigurationOnly # удалить MX сервер из группы DAG
Import-Module FailoverClusters
Get-ClusterNode EXCH-MX-04 | Remove-ClusterNode -Force # удалить отказавший узел из Windows Failover Cluster
Get-MailboxDatabaseCopyStatus * | select name,status,ContentIndexState,ContentIndexErrorMessage,ActiveDatabaseCopy,LatestCopyBackupTime,CopyQueueLength # узнать состояние работы индксов БД и текст ошибки, на каком сервере активная копия БД, дата последней копии и текущая очередь
Get-MailboxDatabaseCopyStatus -Identity $db_name\* | Format-List Name,ContentIndexState # отобразить список всех копий конкретной БД на всех серверах, и статус их индексов, если у второго сервера статус Healthy, можно восстановить из него
Get-MailboxDatabaseCopyStatus -Identity $db_name\EXCH-MX-04 | Update-MailboxDatabaseCopy -SourceServer EXCH-MX-01 -CatalogOnly # восстановить БД из копии
cd %PROGRAMFILES%\Microsoft\Exchange Server\V14\Scripts # или v15 для Exchange 2016
.\ResetSearchIndex.ps1 $db_name # скрипт восстановления индекса
Get-MailboxDatabaseCopyStatus * | where {$_.ContentIndexState -eq "Failed" -or $_.ContentIndexState -eq "FailedAndSuspended"} # отобразить у какой БД произошел сбой работы (FailedAndSuspended) или индекса (ContentIndexState)
$selenium.FindElements([OpenQA.Selenium.By]::CssSelector('button')) | select TagName,Text # отобразить все Button по TagName используя CSS selector
$selenium.FindElements([OpenQA.Selenium.By]::TagName('button')) # поиск по TagName
$selenium.FindElements([OpenQA.Selenium.By]::CssSelector('button')) | ? Text -match "Войти" # поиск Button по содержимому Text
$button = $selenium.FindElements([OpenQA.Selenium.By]::CssSelector('*')) | ? Text -like "Войти через Яндекс ID" # поиск во всех элементах по содержимому Text для получения нужного элемента (SPAN) для дальнейшего быстрого поиска
Get-Process | select Name, CPU | ConvertTo-HTML -As Table > "$home\desktop\proc-table.html" # вывод в формате List (Format-List) или Table (Format-Table)
git show d01f09dead3a6a8d75dda848162831c58ca0ee13 # отобразить подробный лог по номеру коммита
git checkout filename # откатить изменения, если не было команды add
git checkout d01f09dead3a6a8d75dda848162831c58ca0ee13 # переключить локальные файлы рабочей копии на указанный коммит (изменить HEAD на указанный коммит)
git reset HEAD filename # откатить изменения последнего индекса, если был add но не было commit, тем самым вернуться до последней зафиксированный версии (коммита) и потом выполнить checkout
git reset --mixed HEAD filename # изменения, содержащиеся в отменяемом коммите, не должны исчезнуть, они будут сохранены в виде локальных изменений в рабочей копии
git restore filename # отменить все локальные изменения в рабочей копии
git restore --source d01f09dead3a6a8d75dda848162831c58ca0ee13 filename # восстановить файл на указанную версию по хэшу индентификатора коммита
git revert HEAD --no-edit # отменить последний коммит, без указания комментария (события записываются в git log)
(Get-MySQLiteDB $path).Tables # список таблиц в базе
New-MySQLiteDB -Path $path # создать базу
Invoke-MySQLiteQuery -Path $path -Query "SELECT name FROM sqlite_master WHERE type='table';" # список всех таблиц в базе
Invoke-MySQLiteQuery -Path $path -Query "CREATE TABLE Service (Name TEXT NOT NULL, DisplayName TEXT NOT NULL, Status TEXT NOT NULL);" # создать таблицу
Invoke-MySQLiteQuery -Path $path -Query "INSERT INTO Service (Name, DisplayName, Status) VALUES ('Test', 'Full-Test', 'Active');" # добавить данные в таблицу