Powershell 5.0 lõpuks valmis

Sel nädalal sai valmis Windows Management Framework (WMF) 5.0, mis muuhulgas sisaldab Powershell 5.0 versiooni.  Toetatud on Windows Serveri (2008 R2 kuni 2012 R2), ning pärast klientide sooviavaldust on toetatud ka Windows klient-OS (7 ja 8.1).

See versioon asendab Powershell 5.0 Production Preview versiooni (seda pole vaja enne maha võtta).  Seetõttu on paigaldamise eeltingimused enam-vähem samad.  Server 2008 R2 puhul tuleb enne masinasse paigaldada WMF 4.0 .  Lisaks tuleb arvestada, et Powershell WorkFlow ja DSC vajavad mõlemad sisselülitatud WinRM-i.

Kui funktsionaalsuse osas tekib mõtteid, mida tahaks arendajatega jagada, siis UserVoice saidis on eraldi Powershelli foorum, mis asendab endist Microsoft Connect saiti.

Exchange 2013 uuenduste paigaldus

Sai hiljuti just läbi tehtud Exchange 2013 serverile uuenduste paigaldus.  Ja pärast seda olen veendunud, et ainuke õige viis Exchangele uuenduste pealepanekuks on olemasoleva serveri kõrvale uue paigaldamine ning rollide ületõstmine.  Sest nii hoiab kõvasti närve ja tõenäoliselt ka aega kokku.  Ning lisaks muudele eelistele saab uuendamist teha rahulikult keset päeva.

Exchange on juba pikka aega olnud selline keskkond, kus parandused lastakse välja ühe komplektina.  Ning Exchange 2013 puhul on seesama komplekt sobiv ka uue serveri paigalduseks.  Aga kui Sa järele proovid, siis tuleb välja, et testitud on ainult tühja masinasse Exchange paigaldust.

Mis siis valesti on?  Paigaldusprotsess on jagatud mitmeks sammuks.  Iga samm paigaldab/uuendab ühe komponendi.  Uuendamise puhul võetakse sammu alguses ports teenuseid (sealhulgas Exchange teenused), pannakse need seisma ja keelatakse nende käivitamine.  Kuskil paigalduse käigus aga läheb neid teenuseid järsku vaja ning teenused käivitatakse uuesti.  Windowsi teenustega on tavaliselt kõik hästi, ent Exchange enda teenuste puhul on paigaldusprotsess unustanud, et teenused keelati ära.  Ja tulemuseks on veateade ning poolik paigaldus.

Mis halvasti, see uuesti.  Aga tulemuseks on sama probleem, kuna paigalduse sammu alguses keelatakse teenused ning töö käigus püütakse neid uuesti käivitada.  Ja seda hoolimata sellest, et antud sammu on juba korduvalt jooksutatud…

See probleem pole Exchange 2013 Cumulative Update 10 juures unikaalne, vaid eksisteerib juba mitu aastat.  Ning kuskilt otsast pole näha, et midagi muutuks.

Kui ülaltoodud jutt pole Sind veel piisavalt ära hirmutanud ja Sa siiski proovid, siis varu kannatust ning ära mine arvutist kaugele, sest paigaldusprotsessi tuleb pidevalt järele aidata.

Enne alustamist tasuks salvestada hetke teenuste häälestus.  Seda saab teha näiteks Powershelliga:

Get-CimInstance -ClassName Win32_Service |
  Select-Object Name, StartMode , State |
  Export-Csv -Path .\teenused.csv -UseCulture -Encoding Default

Kui jooksva sammu progress on jõudnud ~3% peale, siis tuleks (tavalises) Powershellis käivitada järgmised käsud:

Get-Service -Name msexchange*, fsm |
  Set-Service -StartupType Manual

Ja sedasi iga kord, kui paigaldus uue sammu peale läheb.  Seetõttu ei tohigi masinast kaugele minna, sest teenused tuleb uuesti käivituvaks teha, muidu jääb paigaldus pooleli. Ja tuleb jälle kõik sammud läbi käia…

Kui nüüd paigaldus on lõppenud, siis on kogu selle sebimise käigus läinud kaduma teenuste varasem staatus.  Seetõttu tuleb see ise taastada:

$teenused = Import-Csv .\teenused.csv -UseCulture

$teenused | Where-Object StartMode -Like "Auto" |
  ForEach-Object {
    Set-Service -Name $_.name -StartupType $_.StartMode
  }

$teenused | Where-Object State -Like "Running" |
  Start-Service

Tegelikult salvestab Exchange paigaldus samuti teenuste häälestuse.  Ent miskipärast häälestuse taastamisega paigalduse lõpus enam hakkama ei saadud.

Powershell DSC for Linux

Linuxi kaughaldus Powershelli abiga on juba mõnda aega võimalik olnud.  Selleks oli vaja kas SSH tuge Powershellile või siis CIM/OMI serverit Linuxi masinasse.  Esimesel puhul vastas Linuxist shell, teisel juhul suhtles Powershell CIM-liidese abil.

Nüüd on (tegelikult juba 4 kuud) olemas Powershell Desired State Configuration (DSC) liides Linuxi jaoks.  See tähendab, et nüüd saab DSC abil kirjeldada Linuxi masina häälestust ja see siis kehtestada.  Või siis salvestada DSC Pull serverisse ja Linux tuleb tõmbab omale ise häälestuse.

Värskelt välja lastud versioon 1.1 toetab Azure Automation DSC-d ja sealset Pull Serverit.  Seega saab seda kõike juba Azure’is jooksvate Linux masinate peal kasutada.

Powershell 5 – Production Preview

Windows 10 on juba üle kuu aja väljas, ent varasematele Windowsi versioonidele pole senimaani uut Powershelli versiooni.  Nüüd siis lasti välja Windows Management Framework (WMF) 5.0 Production Preview, mis ei ole küll veel valmis versioon, aga on Microsofti poolt toetatud ning töökeskkonnas kasutuskõlblik.

WMF 5 töötab Windows 7 SP1 või värskema operatsioonisüsteemi peal ning vajab töötamiseks .NET Framework 4.5.

Muuseas tasub ka ära märkida, et Powershellil on nüüd juba mõnda aega oma koduleht, mis teeb info leidmise mõnejagu lihtsamaks.

Veel kord kasutajaprofiilidest

Sai kunagi kirjutatud, kuidas Powershelli abiga kasutajaprofiile üles leida ja kustutada.  Vahepeal on aeg edasi läinud ja uued Powershelli versioonid oskavad samu asju natuke paremini teha.  Sellega seoses sai kirjutatud moodul, mis võimaldab kasutajaprofiilide haldust automatiseerida.  Mooduli leiab Technet Script Gallery’st ja Powershell 5.0 omanikud võivad selle alla tõmmata Powershell Gallery‘st.  Viimaste jaoks on see käsurealt ülilihtsalt teostatav:

#otsi
Find-Module -Name UserProfile

#paigalda
Install-Module -Name UserProfile

Mooduli kasutamine käib järgnevalt:

#Find all user profiles except special system profiles.
Get-UserProfile -Special $false

#Delete all roaming profiles that are not used for 3 months.
$myDate = (Get-Date).AddDays(-90)
Get-UserProfile -Before $myDate -Roaming $true -Loaded $false |
  Remove-UserProfile

#Find user profile of specific user.
Get-AdUser John |
  Select-Object @{n="sid";e={[string]$_.sid}} |
  Get-UserProfile

#Find all roaming profiles from specific computers.
$session = new-cimsession -ComputerName srv1,srv2 -credential domain\user
Get-UserProfile -CimSession $session -Roaming $true

#Migrate local user account profile into domain user account profile.
$oldAccount = Get-CimInstance Win32_UserAccount -filter "caption='PC\\user'"
$newAccount = Get-AdUser Mati
Get-UserProfile -Sid $oldAccount | Set-ProfileOwner -SID $newAccount.SID

#discover user profile owner by folder name
Get-Item c:\users\kasutaja |
  Select-Object -ExpandProperty FullName |
  Get-UserProfile |
  Get-ProfileOwner

Ülalmainitud moodul töötab ilusti ka Windows 7 ja Server 2008 R2 peal ning võib-olla et isegi Vista/Server 2008 peal, kui sinna Powershell 3.0 paigaldada.  Pole hetkel Vista masinat kuskilt võtta, seega ei saa proovida.

Loodetavasti on antud moodul mugavam kasutada, kui kunagi pakutud skriptinäide.

SSH tugi Powershellis

Powershelli tootetiim andis teada, et nad alustasid SSH protokolli toe planeerimist Powershellile.  Seda siis muuseas ka sedapidi, et eemalt masinast saab teha SSH ühenduse ja sihtpunktis kasutada Powershelli.

Teistpidi lahendusi (Powershell teeb SSH sessiooni teise masinasse) on juba mõnejagu olemas.  Näiteks võiks mainida moodulit Posh-SSH.  Kommertstoodetest võiks mainida PowershellServerit, millest on tasuta personaalne versioon olemas.  Samuti võib võtta suvalise Windowsi peal töötava SSH serveri ja kasutada selle sees käsurea interpretaatoriks Powershelli.

Nimetatud funktsionaalsust on korduvalt Powershelli tagasiside veebis küsitud.

Seisuga Oktoober 2015 on valmis saadud OpenSSH for Windows, mis on esialgu veel arendamisel, ent tulemus lubatakse valmis saada järgmise aasta esimeses pooles.

Powershell 5 Preview April 2015

Järjekordne versioon Windows Management Framework 5.0 eelvaatest.  On möödunud aasta esimesest eelvaatest ja seekord saab seda paigaldada ka Windows 7/Server 2008 R2 ja Server 2012 peale.

Uusi asju on juurde tulnud päris palju.  Muudatusi on nii väikeseid kui suuri.  Peamised suured asjad on ikka Desired State Configuration ja moodul PowershellGet.  Aga on ka pisikesi asju, nagu näiteks Get-Clipboard, Set-Clipboard ja New-TemporaryFile.

Nagu eelvaatega ikka, kui leiad midagi, mida tahad muuta, siis kirjuta aadressil https://windowsserver.uservoice.com/forums/301869-powershell, või siis vähemalt hääleta juba kirjutatud asjade seas neid, mis ka Sinu arust vajalikud on.

Powershell ja sündmuste logid

Aeg-ajalt on vaja otsida sündmuste logidest teatud kindlaid sündmusi.  Ja vahel oleks hea ka ise sündmusi logida.

Vaatame kõigepealt, kuidas sündmusi leida.  Selleks on Powershellis kaks käsku: Get-EventLog ja Get-WinEvent.  Esimest neist tuleks kasutada ainult juhul, kui on vaja otsida sündmusi Windows XP/Server 2003 logidest. Ning lisaks ei ole PowerShell v6+ seda käsku enam olemas.

Kõigi uuemate OS-ide puhul tuleks kasutada teist käsku.  See oskab otsida sündmusi ka Event Tracing for Windows logidest.  Ja neid logisid on tänapäeval palju.  Alustamegi siis sellest, et otsime meid huvitava logi üles:

Get-WinEvent -ListLog * Get-WinEvent -ListLog Application

Nüüd teades logi nime, saame sealt otsida sündmusi.  Piirame selle otsimise mingi arvuga, et mitte liiga kaua oodata:

Get-WinEvent -LogName Application -MaxEvents 10
Get-WinEvent -LogName "Windows Powershell" -MaxEvents 10

# vanemad sündmused enne
Get-WinEvent -LogName Application -MaxEvents 10 -Oldest

Tavaliselt ei huvita meid kõik logisse kirjutatud sündmused, vaid ikka spetsiifilised.  Lisaks võivad huvipakkuvad sündmused olla kirjutatud ka mitmesse erinevasse logisse.  Seetõttu saab sündmusi otsida ka mitte logide, vaid hoopis sündmuse allika järgi.  Kõigepealt leiame olemasolevate sündmuste küljest allikad:

(Get-WinEvent -ListLog Application).ProviderNames 
Get-WinEvent -ListProvider * 
Get-WinEvent -ListProvider *PowerShell 
Get-WinEvent -ListProvider Outlook

Nüüd teades allikat, on lihtne saada kätte sündmused:

Get-WinEvent -ProviderName Outlook -MaxEvents 10
Get-WinEvent -ProviderName Microsoft-Windows-PowerShell -MaxEvents 10

Teades täpsemalt mida otsime, saame ka sündmusi täpsemalt filtreerida.  Näiteks võime me vaadata ainult viimase 24 tunni jooksul toimunud sündmusi:

$eile = (Get-Date).AddDays(-1)
Get-WinEvent -FilterHashtable @{
   LogName = "Application"
   StartTime = $eile
}

Või siis otsime me kindlat sündmust, mille puhul on teada ka sündmuse number (EventID):

Get-WinEvent -MaxEvents 10 -FilterHashtable @{
   ProviderName = "Outlook"
   ID = 32
}
Get-WinEvent -FilterHashtable @{
   Logname="Application"
   ProviderName="Application Error"
   Data="iexplore.exe"
}

Kasulikke näiteid ja infot leiab ka Powershelli skriptimisnäidetest.

Kui me oleme eelnevalt rakenduses Event Viewer loonud sündmuste filtri, siis selle saab ette anda ka Powershellile.  Vaja see vaid salvestada XML failiks ja sealt võtta välja element QueryList.  Selle saab ka vaate filtrit muutes vahelehelt XML.

Get-WinEvent -MaxEvents 10 -FilterXml @'
<QueryList>
   <Query Id="0" Path="Application">
      <Select Path="Application">
         *[System[Provider[@Name='Application Error'] and (Level=2) and (EventID=1000)]]
      </Select>
   </Query>
</QueryList>
'@

Get-WinEvent -FilterXml ([xml](Get-Content .\filter.xml)) -MaxEvents 10

$Filter = "*[System[Provider[@Name='Application Error'] and (Level=2) and (EventID=1000)]]"
Get-WinEvent -LogName Application -FilterXpath $Filter

Kasulikku teavet XML ja XPath päringute kohta leiab ka Windows Event Log API päringute tegemise juhendist.

XML-dokumendiga tasub jännata ainult keerulisemate päringute puhul, mida varem näidatud viisidel ei saa kokku panna (näiteks, kui on vaja leida mitmele erinevale EventID-le vastavaid sündmusi vms.).

Logidesse kirjutamisega on asi natuke keerulisem.  Nimelt tuleks oma skripti jaoks luua uus logi või siis vähemalt uus sündmuste allikas.  Muidu on pärast raske oma skripti sündmusi üles leida.  Ja nii uute logide kui ka uute allikate loomiseks on vaja süsteemiülema õigusi:

$myProvider = "minuskript"

#Requires -RunAsAdministrator
New-EventLog -LogName Application -Source $myProvider
New-EventLog -Source TestApp -LogName TestLog 

try {
   Get-WinEvent -ListProvider $myProvider | Out-Null 
} catch {
   Start-Process -Verb runas powershell.exe -ArgumentList "New-EventLog -LogName Application -Source $myProvider"
}

Ülaltoodud tegevus tuleb sooritada ühekordselt.  Pärast seda on uus logi/allikas masinas defineeritud ja skript saab rahulikult kirjutada sündmusi:

$params = @{
   LogName = "Application"
   Source = $myProvider
   EventId = 1
   Message = "Minu kohandatud sündmus"
}
Write-EventLog @params

Get-WinEvent -ProviderName $myProvider

PowerShell 6+ alates on olukord keerulisem. Write-EventLog kui Windows only käsk jäeti sealt välja ning New-WinEvent nõuab seda, et allika juures oleks olemas Event Manifest, mis muuhulgas määrab lubatud EventId’d. Ja lisaks võimaldab see käsk kirjutada vaid Event Tracing for Windows (ETW) logidesse. Sellisel juhul on lihtsam kasutada .NET meetodit WriteEntry:

$myProvider = "minuskript"
$eventId = 1

[Diagnostics.Eventlog]::WriteEntry(
    $myProvider,
    'see on logisündmus',
    [Diagnostics.EventLogEntryType]::Information,
    $eventId
)

Logiallikas peab ikka eelnevalt registreeritud olema, aga muidu saab ilusti kirjutada. Tuleb vaid tähele panna, et sõnumis ei tohi olla teksti %n, kus n on täisarv.

Kui logiallikat ei ole, siis tuleb ka see luua (süsteemiülema õigustes) .NET abil:

#Requires -RunAsAdministrator

if (-not [Diagnostics.EventLog]::SourceExists($myProvider)) {
    [Diagnostics.EventLog]::CreateEventSource(
        $myProvider,
        'Windows Powershell'
    )
}

Powershell 5.0 eelvaade

Veebruaris tuli välja järjekordne versioon Windows Management Framework 5.0-st.  Võrreldes varasemate versioonidega on nüüd näiteks tööle hakanud kõik erinevad linkide versioonid:

New-Item -ItemType File -Path asi.txt
New-Item -ItemType Directory -Path kaust

#Requires -Version 5
New-Item -ItemType HardLink -Name sama.txt -Value .\asi.txt
New-Item -ItemType Junction -Path .\kaustalink -Value .\kaust

#Requires -RunAsAdministrator
New-Item -ItemType SymbolicLink -Path .\uus.txt -Value .\asi.txt
New-Item -ItemType SymbolicLink -Path .\uuskaust -Value .\kaust

Veel üks uus ja põnev omadus on oma skripti lähtekoodi analüüs, kasutades etteantud või ise lisatud reegleid.

Sama versioon (või versiooninumbri järgi isegi värskem versioon) on ka Windows 10 sees.

E-maili aadresside eemaldamine Exchange serveris

Meiliaadresside lisamine on tavaliselt lihtne. Kui seda on vaja paljudele, siis muudame meiliaadreside poliitikat; kui seda on vaja üksikutele, siis lihtsalt lisame.

Eemaldamisega on lugu natuke keerulisem.  Kõigepealt tuleb üles leida adressaadid, kellel on sobiv aadress.  Üldiselt sobib selleks käsk Get-Recipient, aga teeme seda lihtsuse huvides ainult postkastidega:

$EmailFilter = "*@minu.ee"
$kastid = Get-Mailbox -ResultSize Unlimited |
  Where-Object EmailAddresses –Like $emailFilter

Kui adressaadid leitud, siis tuleb üles leida ka konkreetne eemaldamist vajav aadress.  Seda peamiselt seetõttu, et olemasolevate aadresside loendist ei saa eemaldada aadressi mustri järgi, vaid tuleb esitada täisaadress:

$kastid | Foreach-Object {
  foreach ($address in $_.emailaddresses) {
    if ($address -like $EmailFilter) {
      New-Object PSObject -Property @{Name=$_.name; Alias=$_.alias ; SmtpAddress=$address}
    }
  }
}

Tulemuseks kuvatakse hetkel meile kõik leitud meiliaadressid koos postkasti nimega, mille küljes see aadress on.  Nii et nüüd jääb üle asendada kuvamine kustutamisega.  Siin saab ära kasutada Exchange serveri üldist lähenemist: kui atribuudil võib olla mitu väärtust, siis saame olemasolevate väärtuste hulgas teha muutusi (lisada, eemaldada, asendada)

      Set-Mailbox -Identity $_.id -EmailAddresses @{remove=$address}

Ülaltoodud näide töötab Exchange 2010..2016 peal.  Exchange 2007-l ei olnud veel seda mainitud üldist lähenemist loodud, seega peab seal tegema natuke teistmoodi:

      $NewAddresses = $_.emailaddresses - $address
      Set-Mailbox -Identity $_.id -EmailAddresses $NewAddresses

Kui nüüd peaks vajadus tekkima eemaldada aadresse gruppide, kontaktide või muude adressaatide küljest, siis tuleb lihtsalt asendada adressaatide leidmise ja muutmise käsud.  Muu loogika peaks samaks jääma.