HyppÀÀ sisÀltöön

💡 Gallium

TĂ€rpit

Avainsanat

Aivan kuten BashissÀ, myös PowerShellissÀ on varattuja sanoja, joita ei voi kÀyttÀÀ muuttujaniminÀ. TÀssÀ on lista niistÀ:

The following are the reserved words in PowerShell:

    assembly         exit            process
    base             filter          public
    begin            finally         return
    break            for             sequence
    catch            foreach         static
    class            from (*)        switch
    command          function        throw
    configuration    hidden          trap
    continue         if              try
    data             in              type
    define (*)       inlinescript    until
    do               interface       using
    dynamicparam     module          var (*)
    else             namespace       while
    elseif           parallel        workflow
    end              param
    enum             private

    (*) These keywords are reserved for future use.

MistÀ nÀmÀ löytyivÀt?

Olettaen ettÀ Help on pÀivitetty, saat nÀmÀ auki komennolla:

help about_reserved_words

Komennon help löytyy online: about_Reserved_Words.

Muuttujat

Koko totuus löytyy PowerShellin dokumentaatiosta (esim. about_Variables), mutta alla on pikaohje, jolla pÀÀset alkuun.

Dynaaminen

PowerShell on dynaamisesti tyypitetty kieli. TÀmÀ tarkoittaa, ettÀ sama muuttuja voi vaihtua kokoluvusta merkkijonoksi ja niin edelleen, ja tyyppi pÀÀtellÀÀn automaattisesti. Merkin = vasemmalle puolella on muuttujanimi, oikealla on lauseke: {variable} = {expression}. Lauseke voi olla literaali, kuten 123, tai sisÀltÀÀ operaattoreita, kuten 100 + 125 - 2. Oli niin tai nÀin, tulkki evaluioi =-merkin oikealla puolella olevan lausekkeen ja yrittÀÀ sijoittaa kyseisen arvon muuttujaan. Muuttuja saa tÀmÀn tyypin.

$x = 1            # Kokonaisluku (Int32)
$x = 1 + 2 - 1    # ... kuten tÀmÀkin.
$x = 3.12         # Liukuluku (Double)
$x = "abc"        # Merkkijono (String)
$x = @("abc", 42) # Taulukko (Array)
$x = @{a=1;b=2}   # Hajautustaulu (Hash table)

Vaihtaminen

Tyypin voi myös itse mÀÀrÀtÀ, jolloin se kÀytÀnnössÀ castataan kyseiseksi muuttujaksi. Huomaa, ettÀ itse muuttuja on kuitenkin yhÀ dynaaminen:

$x = [byte] 255      # Nyt se onkin tavu (Byte)
$x = [int] 255       # ... eiku kokonaisluku (Int32)
$x = [string] "abc"  # ... eiku merkkijono (String)

# Huomaa myös -as operaattori, joka palauttaa null jos castaus ei onnistu
$y = $x -as [int] # ... null, koska "abc" ei taivu luvuksi

TyypittÀminen

Voit myös kÀskeÀ muuttujan kÀyttÀmÀÀn tiettyÀ tyyppiÀ nyt ja jatkossa. Erona yllÀ olevaan on, ettÀ [type]$variable on nyt vasemmalla puolella =-merkkiÀ. Kaikki muuttujaan sijoitetut arvot pyritÀÀn jatkossa muuttamaan tÀhÀn tyyppiin. Jos muutos ei onnistu, saat virheen.

[string]$x = 1      # Kerran merkkijono, aina merkkijono
$x = "Kissa"        # ... ja yhÀ
$x = 1              # ... ja yhÀ

[int]$y = 12 # Nro
$y = "Koira" # Virhe

Sokeasti automaattiseen tyypitykseen luottamisessa on omat riskinsÀ. Mieti tarkkaan, mitÀ seuraavassa tapahtuu:

🐳 PowerShell
PS /> 4 + "2"
6
PS /> "4" + 2
42

SkriptejÀ kirjoittaessa tuskin tarvitset muita simple typejÀ kuin yllÀ listatut, mutta loput löytyvÀt esimerkiksi C# Docs: Simple Types tai DevBlogs: Understanding Numbers in PowerShell. NÀiltÀ sivuilta selviÀÀ myös numeraalisten tyyppien minimi- ja maksimiarvot, mikÀli tarvitset kertausta asiasta.

SelvittÀminen

Jos olet epÀvarma, mitÀ jotakin cmdlet palauttaa, voit aina selvittÀÀ sen nÀin:

# NÀin saat myös metodit ja parametrit esille
Get-Location | Get-Member

# NĂ€in saat tyypin tiedot
(Get-Location).GetType()      # itsessÀÀn System.RuntimeType
(Get-Location).GetType().Name # itsessÀÀn String

# Jos palautunut arvo on jo muuttujassa
$var | Get-Member
# tai
$var.GetType()

Drives

PowerShellissÀ on kÀsite "drive", joka on hieman erilainen kuin Linuxin tiedostojÀrjestelmÀ. Drive on kÀytÀnnössÀ jokin abstrakti kÀsite, joka voi olla esimerkiksi tiedostojÀrjestelmÀ, rekisteri tai jokin muu. Voit listata kaikki drivet komennolla Get-PSDrive. Voit vaihtaa driveÀ komennolla Set-Location. Alla on komentoja, joissa aloitetaan /home/-hakemistosta, vaihdetaan env:-driveen ja listataan muuttujia, josta vaihdetaan Variable:-driveen, ja lopulta takaisin kotoisin tieodstojÀrjestelmÀn puolelle.

cd /home         # Aloitetaan tÀstÀ (1)

cd env:          # Vaihdetaan env:-driveen (2) 
Get-ChildItem    # Listataan muuttujat
cd Variable:     # Vaihdetaan Variable:-driveen
cd /             # Vaihdetaan takaisin kotihakemistoon
  1. Huomaa, ettÀ cd on Alias Set-Location-komentoon.
  2. env:-drive sisÀltÀÀ ympÀristömuuttujat. Huomaa, ettÀ BashissÀ nÀmÀ ovat ihan vain muuttujia samassa namespacessa (esim. $PATH). PowerShell abstrahoi nÀmÀ omaksi drivekseen.

VianetsintÀ

Voimme kÀyttÀÀ Bash-kielestÀ tuttuja tapoja, mutta luonnolliseti niille on eri syntaksi. Tuttu set -u korvautuu StrictMode-asetuksella ja set -e korvautuu ErrorActionPreference-asetuksella.

StrictMode

PowerShellin StrictMode on hieman monimutkaisempi kuin Bashin set -u (eli nounset). KÀytÀnnössÀ se kuitenkin esimerkiksi tarkistaa, ettÀ et yritÀ kutsua kÀyttÀmÀttömiÀ muuttujia. Voit kytkeÀ skriptissÀ sen pÀÀlle nÀin:

Set-StrictMode -Version 2.0

Voit kÀyttÀÀ myös muita versioita, 1.0 tai 3.0. Tutustu niiden dokumentaatioon: Set-StrictMode

Kuinka testata?

Luo ja aja tiedosto:

stictmode_yes.ps1
Set-StrictMode -Version 2.0

Write-Host "Starting script with strict mode enabled..."
Write-Host "We are referencing: $undefinedVar"
Write-Host "This will never print."

Luo myös tiedosto strictmode_no.ps1, joka on muutoin identtinen, mutta muokkaa riviÀ yksi. Aseta se muotoon Set-StrictMode -Off. Aja molemmat tiedostot ja vertaa tuloksia.

ErrorActionPreference

PowerShellissÀ on useita preference-muuttujia (ks. about_Preference_Variables), joilla voit sÀÀtÀÀ, kuinka PowerShell kÀyttÀytyy. NÀistÀ set -e:tÀ eli errexit-toiminnallisuutta vastaa parhaiten ErrorActionPreference. Voit asettaa sen arvoksi Stop, jolloin skripti pysÀhtyy ensimmÀiseen virheeseen. Vakioarvo on Continue, jolloin skripti jatkaa virheistÀ huolimatta.

$ErrorActionPreference = "Stop"
Kuinka testata?

Luo ja aja tiedosto:

preference_stop.ps1
$ErrorActionPreference = "Stop"

Write-Host "Starting script with ErrorActionPreference set to Stop..."
Set-Location -Path "/thisdoesnotexist" 2>$null
Write-Host "This will never print."

Luo myös tiedosto preference_continue.ps1, joka on muutoin identtinen, mutta muokkaa riviÀ yksi. Aseta se muotoon $ErrorActionPreference = "Continue". Aja molemmat tiedostot ja vertaa tuloksia.

Write-Something

Yksi luonnollinen tapa debugata lÀhes mitÀ tahansa ohjelmointikieltÀ on tulostaa muuttujien arvo kesken skriptin terminaaliin. TÀmÀ ei kuulosta rakettitieteeltÀ, mutta voi olla hyvin tehokas tapa debugata. Bashin kanssa ehkÀ opit, ettÀ echo-komentoja on ÀrsyttÀvÀ lisÀtÀ ja poistaa tarpeen mukaan. KÀsin lisÀtty -v option (verbose) auttaa, mutta vaatii argumenttien parsimista ja if-lausekkeita. Yksi tapa on ohjata komennot stderr-virtaan, mutta se on sinÀnsÀ vÀÀrÀoppista, ettÀ debug-viestit eivÀt varsinaisesti ole virheitÀ.

PowerShell tarjoaa tÀhÀn ratkaisun tukemalla useita eri virtoja. NÀitÀ on useita. Alla olevassa esimerkissÀ kÀytÀmme virtoja: Success (1), Verbose (4) ja Warning(3). Verbose ei tulostu ruudulle tavallisesti, mutta jos asetat preference variablen VerbosePreference arvoksi Continue, nÀet myös Debug-virran tulosteet. Lue lisÀÀ ohjeista about_Output_Streams sekÀ about_Preference_Variables.

streams.ps1
Write-Output "I am typical output!"
Write-Verbose "Ah, you must have VerbosePreference set up properly! đŸ•”ïžâ€â™€ïž"
Write-Warning "Warning! Warning! 🚹"

Debuggaus

PowerShellissÀ on myös debugger, joka on kÀytettÀvissÀ Visual Studion Code -editorissa, olettaen, ettÀ PowerShell Extension on asennettuna. Voit kÀynnistÀÀ sen painamalla F5. Se on erityisen hyödyllinen breakpoint-toiminnon avulla esimerkiksi silmukoiden debuggaamisessa.

Tutustumme tÀmÀn kÀyttöön live-tunneilla.

TehtÀvÀt

TehtÀvÀ: DevausympÀristö ja runpwsh.sh

Warning

Huomaa, ettÀ jos työskentelet siten, ettÀ Windows on host-kÀyttöjÀrjestelmÀsi, voit kirjoittaa tÀmÀn saman skriptin PowerShell-kielellÀ. TÀssÀ esimerkissÀ kÀytetÀÀn Bashia, koska kurssin oletuksena on Linux-host.

PowerShell-osion ensimmÀisessÀ koodaustehtÀvÀssÀ luot itsellesi devausympÀristön. Pohja tÀtÀ varten sinulla pitÀisi olla jo olemassa Bash-osiosta. KÀytÀnnössÀ luot:

  • Hakemistorakenteen tehtĂ€vien vastauksia varten
  • Skriptin runpwsh.sh, joka joko:
    • Ajaa valitun skriptin kontissa
    • KĂ€ynnistÀÀ interaktiivisen shellin (pwsh)
  • Varmistat, ettĂ€ kaikki on versionhallinnassa

Jatka samassa repositoriossa työskentelyÀ, missÀ olet jo aiemmin työskenenlly. Jatka rakennetta seuraavanalaisesti:

johnanderton
├── README.md
├── bash/
├── pwsh
|   ├── README.md
│   ├── runpwsh.sh                  # Uusi tiedosto
│   ├── .help/powershell-help/      # Uusi hakemisto
│   └── scripts/                    # Uusi hakemisto
└── python
    └── .gitkeep

Tiedoston runpwsh.sh luominen olisi hyvÀÀ kertausta Bash-osiosta, mutta jotta voimme keskittyÀ PowerShell-osioon, voit ladata skriptin tÀmÀn repositorion polusta: gh:sourander/skriptiohjelmointi/exercise-assets/scripts/runpwsh.sh

TehtÀvÀ: PowerShell Hello World

Luo skripti `hello.ps1, joka tulostaa terminaaliin tekstin "Hello World!".

Sijoita se repositorion juuresta lukien relatiiviseen polkuun pwsh/scripts/hello.ps1. Aja skripti ./runpwsh.sh scripts/hello.ps1 ja varmista, ettÀ se tulostaa "Hello World!". KÀytÀ alla olevaa templaattia:

hello.ps1
# IMPLEMENT
TehtÀvÀ: PowerShell Turboahdettu Hello World
hello_turbo.ps1
<#
.SYNOPSIS
    Prints "Hello World!" to the terminal.

... ADD MORE HELP HERE ...
#>

# IMPLEMENT

Jalosta yllÀ nÀkyvÀÀ skriptin alkua. Lopullisen skriptin tulisi:

  • tulostaa absoluuttinen polku työhakemistoon
  • tulostaa absoluuttinen polku skriptin sijaintiin
  • tulostaa PSEdition-muuttujan arvon, mutta vain Debug-virtaan.
  • tukea Get-Help-komentoa. Implementoi ainakin:
    • Synopsis (yllĂ€)
    • Description
    • Example

Ohjelman tulosteen pitÀisi kÀyttÀytyÀ seuraavanlaisesti:

🐳 PowerShell
PS> pwsh /app/scripts/hello_turbo.ps1
========= Turbo Hello World! =========
Current working directory:     /
Script directory:              /app/scripts

PS> cd root

PS> $VerbosePreference = "Continue"

PS> pwsh /app/scripts/hello_turbo.ps1
========= Turbo Hello World! =========
Current working directory:     /root
Script directory:              /app/scripts
VERBOSE: Your PowerShell Edition:       Core

Varmista, ettÀ osaat tulostaa komennon helpin termiinaaliin.

Vinkki: Get-Help

Huomaa <# ... #> tiedoston alussa. TÀmÀ on monirivinen kommentti.

Vinkki: src_path

Katso about_automatic_variables ja $MyInvocation.

TehtÀvÀ: Save-Help

TehtÀvÀnÀsi on tallentaa .help/powershell-help-hakemistoon PowerShellin help-tiedostot.

Jos ajoit PowerShell 101-osion komentoja, huomasit varmasti, ettÀ Update-Help-komennon suorittamisessa kestÀÀ tovin. Se lataa Help-tiedostot verkosta. TÀmÀ pitÀisi ajaa joka kerta uusiksi, kun avaamme PowerShellin konttiin. Nopeutetaan tÀtÀ siten, ettÀ tallennetaan meille lokaali offline-kopio helpistÀ.

SkriptissÀ runpwsh.sh on mÀÀritetty bind mount read-write oikeuksin seuraavasti:

Host Container
.help/powershell-help /srv/powershell-help

Nyt tehtÀvÀnÀsi on tallentaa help-tiedostot kontin hakemistoon, joka on bind-mountattu sinun host-koneellesi. Alla on ajettavat komennot. Huomaa, ettÀ komennot tulee ajaa kontissa, ei sinun host-koneellasi.

🐳 PowerShell
# Create the directory
New-Item -ItemType Directory -Path /.help/PowerShellHelp

# Save the help files
Save-Help -DestinationPath /.help/PowerShellHelp

Tip

Vaihtoehtoinen tapa tÀlle tehtÀvÀlle olisi luoda oma Dockerfile ja rakentaa siltÀ pohjalta image, joka sisÀltÀÀ pÀivitetyn helpin. VÀltellÀÀn kuitenkin docker buildx:ÀÀ tÀllÀ kursilla ja pysytÀÀn skriptien ajamisen parissa.

TehtÀvÀ: gitignore .help

LisÀÀ lopuksi .help/-hakemisto sinun .gitignore-tiedostoon. Tiedostot ovat aina ladattavissa netistÀ, joten niiden sÀilöminen pitkÀaikaisesti omana kopiona Gitlabiin olisi turhuutta.

.gitignore
# ...ehkÀ jotain muuta...

# PowerShell help
.help/
TehtÀvÀ: localhelp.ps1

Jatkossa voit instansoida uuden kontin ja ottaa lokaalisti tallennetun helpin kÀyttöön nÀin:

🐳 PowerShell
Update-Help -SourcePath /srv/powershell-help

Hakemisto on kuitenkin .gitignore-tiedostossa, joten voi olla, ettÀ pÀÀdyt ajamaan tÀtÀ koodia uudella koneella. SiispÀ on tarpeellista luoda localhelp.ps1-skripti, joka:

  • PĂ€ivittÀÀ helpin aina, jos -Update-parametri on annettu
    • Ajaa: Save-Help -DestinationPath /var/powershell-help
  • Lataa helpin, pĂ€ivittyi se tai ei.
    • Ajaa: Update-Help -SourcePath /var/powershell-help