Windows PowerShell:通過命令而不是腳本完成操作
在 Windows PowerShell 爭取得到管理員接受方面,認(rèn)知一向是我們所面臨的***問題。長期以來,管理員對該 shell 的認(rèn)知是,它與 VBScript 一樣都是“腳本編寫語言”。雖然由于腳本編寫語言可被用于完成大量操作而深受許多管理員喜愛,但由于其復(fù)雜性和陡峭的學(xué)習(xí)曲線,也使很多管理員望而卻步。
這令人感到非??上АT?shell 支持基于腳本的強(qiáng)大功能,但同樣也支持更簡單的、以命令為導(dǎo)向的功能。該 shell 的真正吸引人之處在于您可以使用上述任何一種方法來完成大量同樣的工作。
僅僅是一個(gè)腳本
下列函數(shù)將從命令行處以字符串或輸入對象的“ComputerName”屬性的方式接受計(jì)算機(jī)名稱;它還會使用 Windows Management Instrumentation (WMI) 從每臺計(jì)算機(jī)檢索 BIOS 和 OS 信息。
function Get-Inventory { [CmdletBinding()] Param( [Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [string] $computername ) Process { $os = gwmi win32_operatingsystem -computername $computername $bios = gwmi win32_bios -computername $computername $obj = new-object psobject $obj | add-member noteproperty ComputerName $computername $obj | add-member noteproperty OSBuild ($os.buildnumber) $obj | add-member noteproperty SPVersion ($os.servicepackmajorversion) $obj | add-member noteproperty BIOSSerial ($bios.serialnumber) Write-output $obj } }
請注意,圓括號會強(qiáng)制 shell 執(zhí)行表達(dá)式(例如從 $os 變量的對象中獲取 BuildNumber 屬性),并將該表達(dá)式的結(jié)果作為 Add-Member 的第三個(gè)參數(shù)值返回。
我也可以通過管道輸入靜態(tài)計(jì)算機(jī)名稱來運(yùn)行此函數(shù):
'localhost','server2' | Get-Inventory
或者,通過發(fā)送每行包含一個(gè)計(jì)算機(jī)名稱的文本文件的內(nèi)容來運(yùn)行此函數(shù)。
Get-Content names.txt | Get-Inventory
或者甚至是通過從 Active Directory 檢索計(jì)算機(jī)對象、將“名稱”屬性更改為 ComputerName,并通過管道傳輸下列內(nèi)容:
Import-Module ActiveDirectory Get-ADComputer –filter * | Select-Object @{Label='ComputerName';Expression={$_.Name}} | Get-Inventory
另外,我使用括號來封裝可執(zhí)行代碼。$_ 占位符代表通過管道輸入 Select-Object cmdlet 的對象。上述操作的結(jié)果均為格式簡潔的表,包含四列。我可以輕松地將上述輸出重定向至文件、打印機(jī)或網(wǎng)格,或者甚至是在顯示結(jié)果之前對其進(jìn)行篩選和排序。例如,
Get-Content names.txt | Get-Inventory | Where { $_.BuildNumber –eq 7600 } | Sort ComputerName
再次重申,括號封裝一個(gè)可執(zhí)行代碼塊,即我希望篩選的表達(dá)式,而 $_ 占位符代表通過管道傳入的對象。
命令性能
類似那樣的腳本并沒有錯(cuò)誤,但是需要處理大量工作。對于這種腳本編寫人員或者說程序員式方法,許多管理員都認(rèn)為任務(wù)過于繁重。通過一個(gè)稍微復(fù)雜的命令也可以完成同樣的任務(wù)。打起精神來:
Get-WmiObject Win32_OperatingSystem -computername (get-content names.txt) | Select-object @{Label="ComputerName";Expression={$_.__SERVER}}, @{Label="OSBuild";Expression={$_.BuildNumber}}, @{Label="SPVersion";Expression={$_.ServicePackMajorVersion}}, @{Label="BIOSSerial";Expression={(gwmi win32_bios -comp $_.__server).serialnumber}}
這里要完成許多操作。下面是操作詳解:
- 首先,運(yùn)行 Get-WmiObject,從特定的計(jì)算機(jī)名稱中檢索 Win32_OperatingSystem 對象。如果您定期閱讀此專欄,您就可能知道 Get-WmiObject 所返回的對象始終包括一個(gè) __SERVER 屬性,該屬性包含 WMI 對象的來源計(jì)算機(jī)名稱。
- WMI 對象通過管道傳輸?shù)?Select-Object。我使用四個(gè)散列表來定義四個(gè)屬性:ComputerName、OSBuild、SPVersion 和 BIOSSerial。每個(gè)散列表都會指定一個(gè)標(biāo)簽和一個(gè)表達(dá)式,其中標(biāo)簽將隨后用作輸出的列標(biāo)題。該散列表通過使用 @ 數(shù)組運(yùn)算符后跟包含在括號內(nèi)的標(biāo)簽/表達(dá)式定義構(gòu)成。這些括號封裝定義散列表表達(dá)式部分的可執(zhí)行代碼。
- 對于前三列,該表達(dá)式只是指該對象的現(xiàn)有屬性;我只不過更改了屬性名稱。
- 對于第四列,我的表達(dá)式實(shí)際上是在同一臺服務(wù)器上執(zhí)行第二次 WMI 查詢。它會從 __SERVER 屬性中提取計(jì)算機(jī)名稱。查看整個(gè) WMI 調(diào)用是如何封裝在圓括號內(nèi)的?這會強(qiáng)制先執(zhí)行該表達(dá)式。該表達(dá)式所得到的任何對象都將代替圓括號內(nèi)部分插入。右括號后面的句點(diǎn)使我能夠訪問得到的對象的屬性,因此我可從第四列訪問其 SerialNumber 屬性。
在某種程度上,此語法比我所啟動的腳本更難讀。它比較緊湊,并使用了大量標(biāo)點(diǎn)符號。您可以將其用作模板,并根據(jù)您的需要進(jìn)行修改。如果您不明白為什么它無法工作,請?jiān)谖业?ConcentratedTech.com 博客上提問,我會為您解答。
不要將它稱為腳本
我的意思是我們不必將 Windows PowerShell 作為腳本語言使用。我演示的命令可能復(fù)雜,但也不會比我所見到的管理員為舊式 Cmd.exe shell 編寫的冗長命令更復(fù)雜。雖然需要進(jìn)行一些訓(xùn)練,但熟悉其語法之后,與編寫完整的腳本或函數(shù)相比,該命令要簡單的多。
因此,請不要看到“腳本語言”便不愿采用該 shell。您可以選擇使用腳本編寫較為簡單的功能。
Don Jones 是 Concentrated Technology 的創(chuàng)始人,他會在 ConcentratedTech.com 解答有關(guān) Windows PowerShell 和其他技術(shù)的問題。他也是 Nexus.Realtimepublishers.com 的撰稿人,他的許多著作還在他的網(wǎng)站上以電子版的形式提供。
【編輯推薦】