Windows PowerShellCostrutti di Windows PowerShell

Don Jones

Il mese scorso vi ho mostrato alcuni modi di immediata utilità di Windows PowerShell nella risoluzione di attività amministrative, senza dover effettivamente scrivere alcuno script. Tuttavia, pur essendo Windows PowerShell una eccellente shell interattiva, si possono sfruttare in modo efficace le sue funzionalità ed automatizzare attività più complesse iniziando ad utilizzare il suo linguaggio di script, efficace ma semplice.

Prima, però, potrete forse chiedervi: Microsoft ha davvero bisogno di un altro linguaggio di script? Dopo tutto, Microsoft ci ha fornito KiXtart, un processore di script di accesso, e Visual Basic® Scripting Edition (VBScript). Nonostante tutto, la risposta è si. Microsoft ha davvero bisogno di un altro linguaggio di script. Vi spiego perché.

Il linguaggio di Windows PowerShell™ doveva essere semplice ed intuitivo, in modo che gli amministratori potessero impararlo con un minimo di formazione. Doveva anche essere piuttosto flessibile in modo da poter gestire tutte le potenti funzionalità che Windows PowerShell era in grado di offrire agli utenti.

Poiché Windows PowerShell si basa su Microsoft® .NET Framework, la sua sintassi di script doveva essere compatibile .NET. Nell'assemblare un linguaggio di script per Windows PowerShell, i progettisti hanno selezionato una sintassi che fondamentalmente è un C# (si pronuncia C-Sharp, uno dei linguaggi forniti con .NET Framework) molto semplificato. Perché non utilizzare una sintassi simile a VBScript? Il linguaggio di script di Windows PowerShell non è tutto sommato così diverso rispetto a VBScript, ma rifacendosi maggiormente alla sintassi C#, PowerShell fornisce una sorta di punto di partenza per l'apprendimento della programmazione .NET Framework. Se doveste decidere di passare a Visual Studio® e di iniziare a scrivere applicazioni C#, gran parte della sintassi di script di Windows PowerShell vi seguirebbe.

Una delle cose più importanti del linguaggio di script di Windows PowerShell, o di qualunque altro linguaggio di script in questo campo, sono i suoi costrutti. Si tratta di speciali elementi di linguaggio che permettono a Windows PowerShell di eseguire confronti logici e intraprendere azioni diverse sulla base dei risultati dei confronti, o che permettono di ripetere indefinitamente una o più istruzioni.

Pensare in modo logico

I confronti logici costituiscono l'essenza di molti costrutti dei linguaggi di script e Windows PowerShell non fa eccezione. Un confronto guarda essenzialmente due valori o oggetti e valuta se il confronto è True o False. Per esempio, ci si può chiedere "La data di scadenza di questa password è uguale alla data di oggi?" Il risultato sarà True se le date sono uguali, o False se sono diverse. Notare che le iniziali di True e False sono in maiuscolo perché si tratta di termini con un significato particolare in Windows PowerShell.

Ecco un esempio di un vero confronto logico che è possibile eseguire in Windows PowerShell:

PS C:\> $a = 1
PS C:\> $b = 2
PS C:\> $a -eq $b
False

Ho creato una variabile denominata $a e le ho assegnato valore 1. In Windows PowerShell, i nomi delle variabili iniziano sempre con il simbolo del dollaro, sono quindi di facile individuazione. Il segno = tecnicamente è indicato come operatore di assegnamento poiché è utilizzato per assegnare un valore. Successivamente ho creato una seconda variabile, $b, assegnandole il valore di 2. Si arriva quindi all'effettivo confronto logico: chiedo a Windows PowerShell di confrontare i contenuti di $a e $b usando l'operatore -eq (uguaglianza). PowerShell effettua il confronto, determina che i due valori non sono uguali e mostra il risultato: False

Gli operatori di Windows PowerShell sono un po' diversi da quelli degli altri linguaggi di script che forse conoscete e sono diversi anche da C#. La maggior parte dei linguaggi usa l'operatore = sia per eseguire verifiche di uguaglianza sia per l'assegnazione dei valori; Windows PowerShell evita confusioni con un operatore dedicato per ciascuna funzione. La Figura 1 mostra gli operatori di confronto di Windows PowerShell con operatori equivalenti di altri linguaggi (come VBScript), che potrebbero esservi già familiari.

Figure 1 Gli operatori di confronto di PowerShell

Operatore Nome. Descrizione
-eq Uguaglianza Verifica se i valori sono uguali. Altri linguaggi usano = o == per verificare l'uguaglianza.
-ne Non uguale Verifica l'ineguaglianza. Altri linguaggi usano <> o != per verificare l'ineguaglianza.
-gt Maggiore di Verifica se un valore è maggiore di un altro. Altri linguaggi usano il carattere >.
-lt Minore di Verifica se un valore è minore di un altro. Altri linguaggi usano il carattere <.
-ge Maggiore o uguale a Verifica se un valore è maggiore o uguale ad un altro. Simile a >= in VBScript e in altri linguaggi.
-le Minore o uguale a Verifica se un valore è minore o uguale ad un altro. Simile a <= in VBScript e in altri linguaggi.

Tali operatori di confronto hanno un'altra interessante caratteristica. Date un'occhiata a questo confronto:

PS C:\> $a = "TechNet"
PS C:\> $b = "technet"
PS C:\> $a -eq $b
True

Di default, gli operatori di confronto non riconoscono maiuscole e minuscole, ciò vuol dire che la versione in maiuscolo di TechNet è considerata uguale a "technet". È conveniente, poiché nella maggior parte delle attività amministrative il formato dei caratteri non è importante. Tuttavia a volte potrebbe esserlo ed è possibile chiedere a Windows PowerShell di eseguire un confronto distinguendo tra minuscole e maiuscole anteponendo la lettera c all'operatore di confronto:

PS C:\> $a -ceq $b
False

Allo stesso modo, se vi preoccupa o vi confonde il fatto che Windows PowerShell esegua un confronto senza distinzione tra minuscole e maiuscole, è possibile forzarlo a farlo anteponendo la lettera i:

PS C:\> $a -ieq $b
True

Ricordate solo che i confronti logici danno sempre come risultato uno dei due valori: True o False.

Prendere delle decisioni

Ora che siete in grado di scrivere confronti logici potete iniziare ad utilizzarli nei costrutti. Il primo costrutto che vi mostrerò permette a Windows PowerShell di decidere sulla base di un confronto. È denominato costrutto If e ne esistono alcune variazioni. Ecco la più semplice:

PS C:\> if ($a -eq $b) {
>> Write-Host "They are equal"
>> }
>>
They are equal

Ci sono alcune cose interessanti da notare qui. In primo luogo le variabili $a e $b contengono ancora rispettivamente i valori "TechNet" e "technet". Ho iniziato il costrutto utilizzando la parola chiave If. Successivamente, fra parentesi, ho inserito il confronto logico che desideravo eseguire. Segue quindi una parentesi graffa che segnala l'inizio di quello che chiamerò codice condizionale, il codice che Windows PowerShell eseguirà se il confronto dà come risultato True. Dagli esempi precedenti sapete che questo confronto dà come risultato True, quindi mi aspetto l'esecuzione del codice condizionale. Digito il mio codice condizionale, Write-Host "Sono uguali" e premo Invio. Infine chiudo la sezione del codice condizionale chiudendo la parentesi graffa e premendo Invio due volte (il secondo Invio su una riga vuota comunica al parser che ho terminato di scrivere e sono pronto all'esecuzione del codice).

Notare che questo costrutto non è in esecuzione da un file di script. L'ho semplicemente digitato nella riga di comando di Windows PowerShell. Questo è ciò che rende Windows PowerShell unico nel mondo dello script di Windows: gli script possono essere creati in modo interattivo oppure inseriti in un file per l'archiviazione permanente.

Non appena ho aperto la parentesi graffa e premuto Invio, Windows PowerShell ha visualizzato un prompt >>. È il suo modo di dire "Riconosco che sei in un costrutto e aspetto che inizi a digitare il contenuto del costrutto". Dopo aver chiuso la parentesi graffa e aver premuto Invio due volte Windows PowerShell ha eseguito immediatamente il costrutto, determinando che il confronto logico era True, ed ha eseguito il codice condizionale. È possibile capirlo perché la frase "Sono uguali" è stata visualizzata prima che PowerShell tornasse al suo normale prompt. L'uso di Windows PowerShell per creare script in modo interattivo permette di testare rapidamente segmenti di codice prima di assemblarli in uno script più permanente, cosa che rende più semplici l'apprendimento e il debug.

Vorrei sottolineare che Windows PowerShell non è particolarmente esigente riguardo a cose come premere Invio. Per esempio, questo funzionalmente è un esempio uguale al precedente:

PS C:\> if ($a -eq $b) { Write-Host "They are equal" }
They are equal

Poiché l'ho digitato tutto su un'unica riga, Windows PowerShell non ha avuto bisogno di visualizzare il prompt >> speciale, ha semplicemente eseguito il costrutto quando ho premuto Invio alla fine della riga. Come ha fatto Windows PowerShell a sapere che eseguire il costrutto era OK? Perché a quel punto era completo, la parentesi graffa era stata chiusa.

Ho accennato ad altre variazioni del costrutto If. Ecco un esempio completo, presentato come potrebbe apparire in un file di script PS1 piuttosto che nella shell:

if ($a -eq $b) {
  Write-Host "They are equal"
} elseif ($a -lt $b) {
  Write Host "One is less than the other"
} else {
  Write Host "One is greater than the other"
}

Il costrutto inizia nello stesso modo ma utilizzando la parola chiave If. Tuttavia, nell'eventualità che il confronto sia False, ho fornito un altro confronto utilizzando la parola chiave Elseif. Se anche il secondo confronto risulta False, la mia ultima parola chiave, Else, fornisce un set di codice finale che verrà eseguito.

Ripetersi

Windows PowerShell contiene un paio di costrutti per l'esecuzione continua del codice, finché uno dei confronti risulta True o False. I programmatori lo chiamano costrutto lo op. Meglio ancora, uno dei costrutti loop più utili è in grado di enumerare gli oggetti di una raccolta e di eseguire una o più righe di codice per ciascun oggetto. In modo abbastanza appropriato, il costrutto è definito un costrutto Foreach e ha questo aspetto:

PS C:\> $names = get-content "c:\computers.txt"
PS C:\> foreach ($name in $names) {
>> Write-Host $name
>> }
>>
don-pc
testbed

Ho iniziato chiedendo a Get-Content smdlet di Windows PowerShell di recuperare il contenuto di c:\computers.txt file, un file che io stesso ho creato contenente un nome di computer per ogni riga. Windows PowerShell tratta ogni riga come un oggetto, quindi il file è essenzialmente una raccolta che li contiene. La raccolta si risolve nelle variabili $nomi. Usando la parola chiave Foreach, dico a Windows PowerShell di enumerare la raccolta $nomi, usando la variabile $nome per rappresentare l'oggetto corrente ogni volta che viene eseguito il ciclo. Il codice di ciclo è riportato tra parentesi graffe. Quindi, immetterò ogni nome contenuto nel file nella riga comando. Come potete vedere dall'output risultante dal costrutto, questo è esattamente ciò che Windows PowerShell fa. Potete rendervi conto di come ciò offrirebbe un ovvio vantaggio nell'uso degli script nell'amministrazione del sistema: è possibile costruire facilmente una lista di nomi di server, per esempio, e far sì che Windows PowerShell recuperi informazioni a rotazione da ciascuno di essi.

Costrutti reali

Adesso prendiamo i confronti logici, il costrutto If e il costrutto Foreach e facciamone qualcosa di utile. Poniamo che io voglia verificare rapidamente lo stato del servizio Messenger su un gruppo di server. Mi aspetto che il servizio non sia avviato sulla maggior parte dei server, quindi non voglio che Windows PowerShell elenchi tutti i server nei quali il servizio è nello stato che mi aspetto, voglio solo che elenchi i server in cui Messenger è effettivamente avviato perché quelli sono i server sui quali ho bisogno di fare qualcosa.

So che Get-Service cmdlet di Windows PowerShell può aiutarmi a recuperare le informazioni di cui ho bisogno per il computer locale.. Sfortunatamente, comunque, non può arrivare ad un computer remoto che è il mio obiettivo reale. Fortunatamente posso anche accedere alle stesse informazioni attraverso Windows Management Instrumentation (WMI), usando Get-WMIObject cmdlet, che mi permette di lavorare con un computer remoto. Quindi ecco lo script:

$names = get-content c:\computers.txt
foreach ($name in $names) {
  $svc = get-wmiobject win32_service '
   -computer $name -filter "name='messenger'"
  if ($svc.started -eq $True ) {
    write-host "$name has Messenger running"
  }
}

Notare il carattere ' nella terza riga. Dice a Windows PowerShell che la riga successiva è un seguito. È utile in casi come questo in cui la riga intera non entrerebbe senza andare a capo. Notare inoltre che il mio costrutto If confronta $svc.started con $True. La variabile $True è una variabile speciale che in Windows PowerShell rappresenta il valore booleano True. (Una variabile complementare, $False, rappresenta il valore booleano False.) In realtà, avrei potuto fare un piccolo collegamento lì:

$names = get-content c:\computers.txt
foreach ($name in $names) {
  $svc = get-wmiobject win32_service '
   -computer $name -filter "name='messenger'"
  if ($svc.started) {
    write-host "$name has Messenger running"
  }
}

Ricordate che la condizione del costrutto If deve essere semplicemente True o False. Normalmente si ottiene come risultato True o False nel confronto tra due valori, come ho fatto io nella prima versione dello script. Tuttavia, poiché la proprietà Avviato è True o False, non c'è bisogno di confrontarla realmente a True o False.

Un utile strumento

Quindi eccolo lì, un semplice, utile strumento amministrativo che utilizza i costrutti per svolgere il suo lavoro. Sia che lo digitiate in Windows PowerShell in modo interattivo sia che lo salviate in un file PS1 per poterlo facilmente riutilizzare, è uno strumento semplice per verificare lo stato di un servizio su vari computer e costituisce una grande dimostrazione di come i costrutti possono aiutare ad automatizzare le attività amministrative.

Don Jones è il Responsabile progetti e servizi di SAPIEN Technologies e coautore di Windows PowerShell: TFM (SAPIEN Press, 2006). È possibile contattare Don attraverso il suo sito web ScriptingAnswers.com.

© 2008 Microsoft Corporation e CMP Media, LLC. Tutti i diritti riservati. È vietata la riproduzione completa o parziale senza autorizzazione.