Skriptid ja häälestus

Iga skript vajab mingeid seadistusi. On see siis server kellega ühendust võtta või autentimisinfo või info mida korjata. Ning alati tekib see probleem, et mis peaks saama skripti sisse kirjutatud ja mida oleks vaja sagedamini muuta.

Esimese hooga tundub et milles küsimus. Kirjutame muutujad kõik skripti alguses ühte blokki kokku ja muudame kui vaja. Aga siis pead Sa sama skripti jooksutama korraga paljudes serverites. Ja siis tuleb seda aastate jooksul muuta: parandada vigu või kohendada funktsionaalsust. Ja siis on alati üks jama nende muutujatega. Alati peab mäletama et teises serveris on need teistsugused. Ja see tähendab et skripti ei saa lihtsalt automaatikaga üle kirjutada, kui uuem versioon valmis saab. Ning uude serverisse ei saa skripti võtta vanast, vaid peab mäletama, et muutujad tuleb ära muuta.

Interaktiivse skripti puhul (mida käivitab inimene) on asi lihtne: teed muutujatest käsurea parameetrid ja skripti käivitamisel annad need ette. Ja harvemini varieeruvatele parameetritele saab anda vaikeväärtused. Aga kui skripti tuleb jooksutada automaatselt? Task Scheduler (või cron) võimaldab parameetrid ka lisada, aga see ei ole just väga mugav, eriti kui vahel oleks vaja neid muuta.

Siis võiks ju proovida luua teise skripti mis sisaldaks esimesele vajalikke väärtusi. Aga siis on Sul ühe skripti asemel hallata kaks tükki. Ja see teine skript oleks ikka käivituv kood, mis võiks olla käivitajale kättesaadav ainult lugemisõigustes (või siis signeeritud).

Selle asemel võiks kasutada keskkonna muutujad:

$PSEmailServer = $env:MailServer

# muudame väärtust
[Environment]::SetEnvironmentVariable(
  'MailServer',
  'my.mail.server',
  [EnvironmentVariableTarget]::User
)

Ainsaks probleemiks on, et iga keskkonnamuutuja on üks string (ja keegi peab need väärtustama ka, või vähemalt mäletama et enne skripti käivitamist tuleb muutujad väärtustada). Keerulisema häälestuse salvestamiseks läheb neid muutujaid päris palju. Ning lisaks võivad keskkonnamuutujad hakata skriptide vahel sassi minema, kui just väga hoolikalt muutujate nimede peale ei mõtle.

Sedalaadi ülesandeks sobivad paremini häälestusfailid. Ja PowerShell oskab erinevaid struktuurseid andmefaile lugeda. Seega ei pea häälestusfail olema lihtsalt tekstridade kogumik (või .ini fail). Selle asemel saab kasutada XML, JSON või PowerShell Data file (.psd1) vormingut. Ja enamasti on need failid ka inimese jaoks loetavad.

Näiteks saab seda teha sarnaselt:

#Requires -Version 3.0
param (
  $LocalConfig = $(
    Join-Path -Path $PSScriptRoot -ChildPath (
      (Get-Item -Path $PSCommandPath).BaseName + '.config'
    )
  ),
  $WebConfig = 'https://web.site/data.config'
)

# XML config
$conf1 = [xml](Get-Content -Path $LocalConfig)
$conf2 = Invoke-RestMethod -Uri $WebConfig

# JSON
$conf1 = Get-Content -Path $LocalConfig | ConvertFrom-Json
$conf2 = Invoke-RestMethod -Uri $WebConfig

# PSD1
$conf2 = (Invoke-WebRequest -Uri $WebConfig).Content |
  Invoke-Expression
$ScriptBlock = [ScriptBlock]::Create(
  (Get-Content -Path $LocalConfig) -join [environment]::NewLine
)
$conf1 = $ScriptBlock.Invoke()
#Requires -Version 5.0
$conf1 = Import-PowerShellDataFile -Path $LocalConfig

Ja juba on võimalik kood ja häälestusinfo ilusti teineteisest lahku viia. Ning vajadusel tegeleda häälestuse keskse haldusega.

Kui nüüd tahta et paljud skriptid oskaksid samamoodi häälestust lugeda ja et kohe oleks olemas ka võimalus häälestust salvestada, siis tasuks kogu sellege tegelev kood viia eraldi moodulisse. Lisaks annaks see võimaluse, et meil on oma vaikehäälestus, mida saaks masina- või kasutajapõhiselt üle kirjutada. Ja et häälestus võiks olla ka kuskil mujal, kui failides.

Enne kui hakkad omale sellist moodulit kirjutama, vaata ehk sobib mõni alltoodutest:

  • Configuration – on mõeldud kasutamiseks ainult moodulitest. Töötab .psd1 failidega ja võimaldab häälestust laadida ja salvestada erinevatesse asukohtadesse (mooduli kaust, $env:LOCALAPPDATA, $env:APPDATA, $env:ProgramData).
  • PSFramework – muuhulgas pakub ka häälestuse seadistamist, salvestamist ja laadimist väga erinevatest asukohtadest (sealhulgas registrist või kasutaja määratud JSON failist/ veebiteenusest). Häälestuse süsteem on laiendatav ka selles osas, et kui leida/kirjutada vahendaja, saab häälestust hoida ka näiteks andmebaasis. Ja häälestust tarbiv rakendus ei pea kogu seda keerukust teadma.
  • PSConfig – võimaldab häälestust laadida .csv, .json või tekstifailist (kasutades ConvertFrom-StringData käsku). Või siis keskkonnamuutujatest.

Selliseid mooduleid on veel, aga need tunduvat rahuldavat ka kõige nõudlikuma tarbija vajadusi.

Powershell 7 RC2

Eelmine nädal toimus Powershell Community Call ja selle käigus teatati, et tuleb välja Powershell 7 Release Candidate 2. Ja sellega seoses nihutati lõpliku versiooni tähtaeg veebruarisse.

Powershell Release Candidate (sealhulgas ka RC2) on toetatud versioon, mis tähendab et probleemide korral saab pöörduda Microsofti toe poole.

Microsoft soovitab tungivalt juba praegu proovida, et kas kõik Windows Powershelli all töötav jookseb ka Powershell 7 all. Ja kui on midagi, mis ei lase uue versiooni peale üle minna, siis peaks sellest kindlasti teatama.

Praeguseks on kindel et üleminek tuleb korraldada käsitsi. Powershell 7 käivituv programm on pwsh.exe, mitte powershell.exe, seega tuleb kõik automaatikad üle vaadata ja ära muuta. Lisaks tuleb arvestada, et kuna .NET Core on siiski natuke erinev .NET Framework’ist, siis ei pruugi kõik asjad tööle jääda.

Samuti on soovitav viia Powershelli kaugühendused WinRM protokollilt üle SSH protokollile. See omakorda vajab, et masinatesse lisataks OpenSSH või mõni muu SSH protokolli oskav komponent. Windows 10 1809/Server 2019-ga tuleb OpenSSH kaasa, aga vanematele OS-idele tuleb see eraldi alla laadida ja käsitsi lisada. Ja häälestada tuleb SSH Serverit ikka, ning esialgu tuleb seda teha suht käsitsi.

Powershell 7 lisamine Windowsile jääb esialgu ka suhteliselt käsitööks. On olemas .MSI või .MSIX pakk ja miskis tulevikus ilmub Powershell 7 ka Microsoft Store keskkonda. Versioon 7.1 ajaks saab ehk midagi automaatsemat, aga kindel veel ei ole.

Muuhulgas oli Community Call’i ajal juttu ka Powershelli järgmisest versioonist. See on siis versioon 7.1 ja see saab seotud .NET 5 valmis saamise ajaga (praegu plaanis November 2020). Ja edaspidi saavadki Powershelli uued versioonid välja tulema koos uue .NET versioonga (ehk siis korra aastas) ning nende toe tingimused vastavad .NET versiooni toele.

PowerShelli tulevikust

Eelmine kord rääkisime sellest, kuidas tuvastada keskkonda, milles skript jookseb.  Sealt jäi välja üks pisiasi: kuidas tuvastada Nano Server või Server Core keskkonda.

Server Core keskkonnaga on lihtne, seal on meil tavaline Powerhsell keskkond ja OS funktsioonidega kaasatulevad haldusmoodulid.  Vajadusel saab seda kontrollida:

$regPath = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Server\ServerLevels\'

#Requires -Version 5.0
Get-ItemPropertyValue -Path $regPath -Name ServerCore

#Requires -Version 2.0
$RegKey = Get-ItemProperty -Path $regPath -EA SilentlyContinue
if ($RegKey."Server-Gui-Shell") {
  "Server with Desktop Experience"
} elseif ($RegKey.ServerCore) {
  "Server Core"
} elseif ($RegKey.NanoServer) {
  "Nano Server"
} else {
  "Not a Server OS"
}

Nano Server keskkonnaga on natuke raskem.  Nimelt on seal ruumi kokkuhoiuks OS funktsionaalsust vähendatud, sealhulgas .Net Framework on seal .Net Core, mitte täielik .Net Framework.  Ja kuna PowerShell sõltub .Net keskkonnast, siis on ka PowerShelli funktsionaalsus vähendatud.  Lisaks on puudu terve hunnik haldusmooduleid, mis tavaliselt olemas on.  Vähendatud funktsionaalsusega keskkond on tuntud kui PowerShell Core Edition:

#Requires -Version 5.1
$PSVersionTable.PSEdition

if ($PSVersionTable.PSEdition -like 'Core') {
  Write-Verbose 'Powershell Core'
} else {
  Write-Verbose 'Windows Powershell'
}

Natuke segadust võib tekitada see, et PowerShell v6 ajal pandi sellele nimeks PowerShell Core. Ja v7 nimetati jälle ümber (seekord lihtsalt PowerShell).

Skriptile võib lisada kontrolli, et vältida skripti käivitumist vales keskkonnas:

#Requires -Version 5.1
#Requires -PSEdition Core

Samuti on võimalik mooduli lisamisel/kasutamisel kontrollida, et see toetab keskkonda, kus teda kavatsetakse kasutada:

Find-Module -Tag PSEdition_Core

Get-Module -ListAvailable |
  Where-Object CompatiblePSEditions -Contains "Core"

Get-Module -ListAvailable | Where-Object {$_.CompatiblePSEditions}

Esialgu on moodulid ilma vajaliku infota manifestis, ent Windows 10 v1809/Server 2019 keskkonnas on OS-iga kaasatulevad moodulid juba ilusti märgistatud.  PowerShell Gallery moodulid on ka juba sildistatud või siis ei ole mooduli autor pidanud seda vajalikuks.

Pisike probleem selle märgistamisega on selles, et kui moodul peaks töötama ka varasemates PowerShelli versioonides, kui 5.1, siis ei saa CompatiblePSEditons tunnust lisada. Varasemad versioonid leiavad selle peale, et moodul on vigane ning ei lae seda. See on ka põhjus, miks Powershell Gallery soovitab lisada hoopis väljaande ja OS-põhised sildid. Nendesamade siltide järgi saab ka lokaalseid mooduleid filtreerida:

Get-Module -ListAvailable | Where-Object Tags -Contains 'Linux'

Get-Module -ListAvailable |
    Where-Object Tags -Contains 'PSEdition_Core'

Arvestades, et PowerShell 6 (ja 7) on juba olemas, tasub tähele panna:

  • Windows PowerShell 5.1 on viimane omast klassist ja seda edasi ei arendata.
    • Kõik Windows PowerShelliga seotud probleemid/ettepanekud tuleb raporteerida UserVoice saidis.  Vigade parandusi väidetavasti veel tehakse.
  • PowerShell on nüüd avatud lähtekoodiga projekt.  Seda ei panda Windowsiga kaasa, kuna seda arendatakse korraga mitmele platvormile: Windows, Linux, macOS.
  • PowerShell 6+ paigaldatakse Windows PowerShelli kõrvale ja see tuleb käivitada kui pwsh.exe
  • Kõik PowerShell 6/7-ga seotud probeemid/ettepanekud tuleb esitada Github saidis.
  • PowerShell 6+ ei sisalda enam järgmiseid asju:
    • Powershell ISE liides.  Arendustiim pakub alternatiivina kasutada Visual Studio Code redaktorit, mille Powershelli plugin on võimekam kui ISE.
    • Töövoogude (workflow) mootor.
  • Desired State Configuration saab samuti ümber kirjutatud .Net Core baasil (kunagi ehk).
  • PowerShell 2.0 režiimi ei ole enam v6+ sees. Samuti soovitatakse sellest v5+ peal lahti saada.

PowerShell 6+ kasutamisel on vaja tuvastada ka OS, mille peal joostakse.  Kuna CimCmdlets moodul pole veel komplektis, kui OS ei ole Windows, siis tuleb OS tuvastada teist moodi:

#Requires -Version 5.1
$PSVersionTable.PSEdition

#Requires -PSEdition Core
$PSVersionTable.OS

if ($PSVersionTable.PSEdition -like 'Core' ) {
    'PowerShell Core, OS: {0}' -f $PSVersionTable.OS
} else {
  "Windows PowerShell"
}

#Requires -Version 6
$IsWindows
$IsMacOs
$IsLinux

Kokkuvõtteks võib öelda, et tasub kõik oma skriptid/moodulid üle vaadata ning lisada vajalikud kontrollid, et vales keskkonnas oma töö asjaliku veateatega lõpetada. Ja lisada neile ka vajalikud sildid, et inimesed neid asjata alla ei tõmbaks.

Mis keskkonnas mu skript jookseb

Iga Windowsi süsteemiülem peab oskama PowerShelli kasutada.  Kui ta seda ei oska, siis ei saa ta ennast Windowsi süsteemiülemaks nimetada.  Ja vähehaaval nad seda ka õpivad (kui nad juba ei oska).

Kõik on väga tore, kuni me teame, millises masinas me oma asju jooksutame.  Aga kui me oleme jõudnud juba sinnamaale, et koodi jooksutatakse automaatselt, siis läheb elu keerulisemaks.  Nimelt tuleb siis hakata tuvastama, et mis keskkonnas kood parasjagu jookseb.  Sest kui seda mitte teha, siis võib kood mitte töötada.

Üks esimesi asju mida tuvastada on see, et kas meil on ka süsteemiülema õigused.  Seda on lihtsaim teha, kui luua omale abistav funktsioon:

function Test-IsAdmin {
  $AdminRole = [Security.Principal.WindowsBuiltinRole]::Administrator
  $CurrentIdentity = [Security.Principal.WindowsIdentity]::GetCurrent()
  $CurrentUser = [Security.Principal.WindowsPrincipal] $CurrentIdentity
  $CurrentUser.IsInRole($AdminRole)
}

Ja siis saab seda kasutada.  Alates Powershelli versioonist 4.0 on ka teine viis (täpsem info Powershelli spikris):

if (-not (Test-IsAdmin)) {
  throw "Süsteemiülema õigused vajalikud, katkestan"
}

#Requires -RunAsAdministrator

Kui süsteemiülema õigused on puudu, siis saab neid vajadusel omandada.  Sellest sai kirjutatud varem.

Tasub tähele panna ka seda, et #Requires kontrollid töötavad ainult salvestatud skripti sees ning neid kontrollitakse juba skripti laadimisel.  See tähendab, et kui nõue pole täidetud, ei käivitata skripti üldse ning seetõttu ei saa ka skripti sees midagi selle suhtes ette võtta.

Kui Sa jooksutad oma skripte erinevate Powershelli versioonide peal, siis on vaja ka seda kontrollida.  Selleks oli kaks meetodit:

if ($PSVersionTable.PSVersion -lt "5.0") {
  throw "see on vale PowerShelli versioon"
}

#Requires -Version 5.0

Neist esimese puhul ei pea tingimata skripti tööd katkestama.

Windows 8-st alates hakkasid Powershelli moodulid kaasa tulema ka opsüsteemiga.  Samuti on vaja moodulite olemasolu kontrollida juhul, kui kasutada mõnd lisatud funktsionaalsust.  Ka seda saab kahte moodi teha:

if (-not (get-module Hyper-V -ListAvailable)) {
  Write-Error "Vajalik funktsioon puudu, katkestan" -EA Stop
}

#Requires -Modules Hyper-V

Vajadusel saab kontrollida ka mooduli versiooni:

$ModuleId = @{ModuleName='Hyper-V';ModuleVersion="2.0.0.0"}
if (-not (Get-Module -FullyQualifiedName $ModuleId -ListAvailable)) {
  throw "Vajalik moodul puudu, katkestan"
}

#Requires -Modules @{ModuleName="Hyper-V";ModuleVersion="2.0.0.0"}

Kui moodulite halduseks on oma koodihoidla, siis saab muidugi lihtsamalt:

#Requires -RunAsAdministrator
#Requires -Modules PowerShellGet
Find-Module UserProfile -MinimumVersion 1.0 -Repository PSGallery |
  Install-Module -Force -Scope AllUsers

Get-InstalledModule | Update-Module

Aga vahel ei piisa ka mooduli olemasolu/versiooni kontrollist.  Näiteks on Windows 8.1-ga kaasas olevas moodulis (NetTCPIP) olemas käsk Test-NetConnection, mida Windows 8-ga kaasas olevas moodulis pole.  Aga mooduli versiooninumber on mõlemal sama.  Siis tuleb kontrollida konkreetse käsu olemasolu:

if (Get-Command Test-NetConnection -ErrorAction SilentlyContinue) {
  #olemas, võib tegutseda
} else {
  Write-Error "käsk puudu"
}

Get-Command telnet

Vahel oleks vaja hoopis teada, kas mõni opsüsteemi funktsioon on antud masinas olemas või puudu.  Windows Serveri haldusliidesed on funktsionaalsustest eraldi paigaldatavad ning võivad paikneda hoopis teises masinas.  Serveriga on asi lihtne.  Kui skripti jooksutavas masinas on ServerManager moodul (seda saab ka klient-OSile paigaldada, kui tõmmata omale RSAT), töötab järgmine kood:

if (-not (Get-WindowsFeature -Name RSAT-DNS-Server).Installed) {
  Install-WindowsFeature -Name RSAT-DNS-Server
}
#olemas, võib tegutseda

Klient-OSi puhul on see natuke keerulisem, kuna alates Win10 v1607-st otsustati osad OS funktsioonid muuta teistsuguseks, kui ülejäänud. Ja loomulikult tuli siis nende haldamiseks ka uued käsud välja mõelda:

#Requires -Modules Dism
#Requires -RunAsAdministrator

$Feature = Get-WindowsOptionalFeature -Online -FeatureName telnet*
if ($Feature.State -eq [Microsoft.Dism.Commands.FeatureState]::Disabled) {
  Enable-WindowsOptionalFeature -Online -FeatureName TelnetClient
}

# Win10/Srv16/Srv19
if (Get-Command Get-WindowsCapability -ErrorAction SilentlyContinue) {
  Get-WindowsCapability -Online -Name OpenSSH.Client*
}

Käsk Get-WindowsCapability on jälle üks neist, mis lisati tema moodulisse ilma mooduli versiooninumbrit muutmata. Ja ka Windows Sever (2016 või värskem) omab sama häda.

Edasi jääb veel vaid üle kontrollida, et kas meil on käes server-OS või midagi muud:

#Requires -Modules CimCmdlets
switch ((Get-CimInstance Win32_OperatingSystem).ProductType) {
  1 { "Workstation"}
  2 { "DC" }
  3 { "Server" }
}

Get-ItemProperty -Path "HKLM:\Software\Microsoft\Windows NT\CurrentVersion" |
  Select-Object -Property EditionId, InstallationType

#Requires -Modules Dism
#Requires -RunAsAdministrator
if ((Get-WindowsEdition -Online).Edition -like 'Server*') {
  "on server"
} else {
  "klient, vist"
}

Server OS-i puhul võib veel tekkida vajadus teha vahet Semi-Annual Channel ja Long-Term Support Channel masinate vahel. Dokumentatsioonis on ära toodud kood, millega vajalik info kätte saada, ent neid on veel:

# ettevalmistus
$RegPath = "HKLM:\Software\Microsoft\Windows NT\CurrentVersion"

$Product = (Get-ItemProperty -Path $RegPath).ProductName
$Edition = (Get-ItemProperty -Path $RegPath).EditionId

#Requires -Modules CimCmdlets
$Product = (Get-CimInstance Win32_OperatingSystem).Caption

#Requires -Modules Dism
#Requires -RunAsAdministrator
$Edition = (Get-WindowsEdition -Online).Edition

# lõplik kontroll
switch -wildcard ($Edition) {
  'Server*ACor' {
    "Semi-Annual Channel"
    break
  }
  'Server*' {
    "Long-Term Support Channel or older than Server 2016"
  }
  Default { 'Not a Server product' }
}

switch -regex ($Product) {
  'Server 201[69] ' {
    "Long-Term Support Channel"
    break
  }
  ' Server [DS]' {
    "Semi-Annual Channel"
 }
}

Olen seni teadlikult vältinud OS versiooni kontrolli.  nagu ülaltpoolt näha, pole seda enamasti vaja.  Ent arvestades Windows 10 (ja Windows Serveri) väljalaske tsükliga, võib seda vaja minna:

if ([environment]::OSVersion.Version -ge "6.3") {
  "Windows 8.1 või värskem"
}

Õnnetuseks otsustas Microsoft antud viisile panna peale kontrolli: kui rakendus ise ei deklareeri, et ta tunneb uuemaid OS versioone, siis valetatakse talle versiooniks alati “6.2.9200” ehk siis Windows 8/Server 2012. Tundub, et Powershell 4 ja värskem deklareerib, ent algusepoole oli ka seal näha valet versiooni, seetõttu ei saa tagastatud vastuses alati kindel olla.  Lisaks on Windows 10 versiooninumbri algus kõigil väljalasetel sama, muutub ainult BuildNumber.  Seda viimast aga saab kontrollida:

#Requires -Modules CimCmdlets
switch ((Get-CimInstance Win32_OperatingSystem).BuildNumber) {
  {[int]$_ -lt 10240} {"Pre-Win10 version"}
  10240 {"Win10 RTM"}
  10586 {"Win10 1511"}
  14393 {"Win10/Svr16 1607"}
  15063 {"Win10 1703"}
  16299 {"Win10/Svr 1709"}
  17134 {"Win10/Svr 1803"}
  17763 {"Win10/Svr19/Svr 1809"}
  18362 {"Win10/Svr 1903"}
  18363 {"Win10/Svr 1909"}
  19041 {"Win10/Svr 2004"}
  default {"Insider/future build"}
}

Tegelikult saaks siin registrist info mugavamini kätte:

#Requires -Version 5.0
$RegPath = "HKLM:\Software\Microsoft\Windows NT\CurrentVersion"
Get-ItemPropertyValue -Path $RegPath -Name ReleaseId

Get-CimInstance kasutamine võimaldab teha kontrolli ka eemalt.  Samamoodi saab ka versiooninumbri kätte.  Tuleb lihtsalt arvestada, et CIM tagastab versiooninumbri kui stringi ja see tuleb ise versiooninumbriks teisendada, kui seda vaja peaks olema:

#Requires -Modules CimCmdlets
(Get-CimInstance Win32_OperatingSystem).Version -as [version]

Varem oli vahel vaja ka teada Service Pack versiooni, aga uuemater versioonide puhul pole neid enam välja antud. Igaks juhuks paneme siia kirja selle tuvastamise moodused:

# text
$RegPath = "HKLM:\Software\Microsoft\Windows NT\CurrentVersion"
Get-ItemProperty -Path $RegPath |
  Select-Object -Property CSDVersion

# number
$ServicePack = [environment]::OSVersion.Version.MajorRevision
if ($ServicePack -lt 2) {
  Write-Error 'Service Pack level too low'
}

PowerShell Linuxile

Ja ongi saanud tõeks see, mida juba mõnda aega oodatud on.  Powershell on kättesaadav Linuxi ja Mac OS X platvormile.  Koos sellega on Powershelli lähtekood tehtud avalikuks ning on saadaval GitHubis Powershelli projekti saidis.

Vastav info on väljas ka Powershelli kodulehel .

Muuhulgas tasub mainida, et koos Windows 10 aastapäeva väljalaskega (1607) tuli välja ka Windows Management Framework (WMF) 5.1 .  Windows 7 ja Server 2008-le paigaldamisel eeldatakse, et WMF 4.0 on masinas juba olemas…

Nagu ka varasemate versioonidega, ei tasu seda installida Exchange või Sharepoint serverisse.

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.