一對多 Powershell 腳本
我正在嘗試創建一個腳本以作為計劃任務執行,它將針對多個伺服器執行並檢索一些資訊。
首先,我通過使用 Get-ADComputer 查詢符合特定條件集的所有伺服器的 AD 來填充伺服器列表。
問題是,列表作為對象返回,然後我不能將其傳遞給 New-PSSession 列表。我嘗試通過執行以下操作將其轉換為逗號分隔的字元串:
foreach ($server in $serverlist) {$newlist += $server.Name + ","}
但這仍然行不通。
另一種方法是遍歷列表並一次對每個伺服器執行各種命令,但我的偏好是避免這種情況並使用一對多遠端處理來執行它們。
**更新:**為了澄清我最終想要做的是 using
-ComputerName $serverlist
,所以我希望 $serverlist 是一個字元串而不是一個對象。**更新2:**感謝所有建議。在它們和我原來的方法之間,我開始懷疑是否
-ComputerName
可以接受字元串變數?我在將電腦列表轉換為逗號分隔字元串方面取得了不同程度的成功,但無論我怎麼做,我總是得到無效的網路地址。
再解釋一下,如果你已經執行了,
Get-ADComputer
那麼你可能會得到一個對像數組或單個對象。我假設您正在呼叫類似以下內容:
$serverList = Get-ADComputer -LDAPFilter '(cn=*DC*)';
這將使所有電腦都以
DC
他們的名字命名。因為您可能有一個數組(不止一個)或您使用
ForEach-Object
cmdlet 處理的對象(也別名為%
orforeach
)是一個好方法。這基本上是為管道中的每條記錄執行一個腳本塊。但是,正如您所經歷的那樣,您從查詢中得到一個對象而不是一個字元串。因此,您只需選擇要使用的屬性。例如,如果您使用:
$serverList[0] | Get-Member
您將獲得電腦對象的所有屬性。
gm
也是 的別名Get-Member
。例如PS> $伺服器列表
$$ 0 $$| 通用汽車
TypeName: Microsoft.ActiveDirectory.Management.ADComputer Name MemberType Definition ---- ---------- ---------- Contains Method bool Contains(string propertyName) Equals Method bool Equals(System.Object obj) GetEnumerator Method System.Collections.IDictionaryEnumerator GetEnumerator() GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() Item ParameterizedProperty Microsoft.ActiveDirectory.Management.ADPropertyValueCollection Item(string p... DistinguishedName Property System.String DistinguishedName {get;set;} DNSHostName Property System.String DNSHostName {get;set;} Enabled Property System.Boolean Enabled {get;set;} Name Property System.String Name {get;} ObjectClass Property System.String ObjectClass {get;set;} ObjectGUID Property System.Nullable`1[[System.Guid, mscorlib, Version=2.0.0.0, Culture=neutral, ... SamAccountName Property System.String SamAccountName {get;set;} SID Property System.Security.Principal.SecurityIdentifier SID {get;set;} UserPrincipalName Property System.String UserPrincipalName {get;set;}
快速查看可以看到有一個 DNSHostName 屬性。
所以要執行你的命令,你可以使用類似的東西:
$serverList = Get-ADComputer -LDAPFilter '(cn=*DC*)'; $serverList | ForEach-Object { New-PSSession -ComputerName $_.DNSHostName; }
但是我會注意到,
New-PSSession
除了創建與電腦的遠端會話之外,cmdlet 並沒有做太多的事情(必須啟用 PowerShell Remoting 才能支持此功能)。您將需要使用Invoke-Command
cmdlet 從腳本中執行某些操作。範例 1:
$serverList = Get-ADComputer -LDAPFilter '(cn=*DC*)'; $serverList | ForEach-Object { New-PSSession -ComputerName $_.DNSHostName; } | ForEach-Object { Invoke-Command -Session $_ -ScriptBlock { #Execute commands here }; };
範例 2:
Get-ADComputer -LDAPFilter '(cn=*DC*)' | % { Invoke-Command -ComputerName $_.DNSHostName -ScriptBlock { #Execute commands here }; };
第二個範例優化了 ,因為如果您只呼叫沒有高級選項的
New-PSSession
,則實際上並不需要它。Invoke-Command
另請注意,實際上沒有必要將結果儲存在變數中,只有在執行時間很長並且必須多次使用它
Get-ADComputer
時才會這樣做。Get-ADComputer
這
$_
是一個管道變數,它成為目前管道中的任何對象。更新
專門用於
Invoke-Command
對多台電腦執行相同的命令,您可以使用該-ComputerName
參數來提供字元串數組。(這可以通過查看幫助來查看,即-ComputerName <String[]>
。並非所有命令都如此)。如前所述,輸出
Get-ADComputer
是一個對象。-ComputerName
因此將構造一個與參數兼容的字元串數組。$serverList = @(); Get-ADComputer -LDAPFilter '(cn=*DC*)' | % { $serverList += $_.DNSHostName; }
基本上這會創建一個新數組並將每台電腦的 DNS 主機名添加到其中,但您最終會得到
string[]
. 然後您就可以使用:Invoke-Command -ComputerName $serverList -ScriptBlock { #Execute commands here };
但是還要注意,雖然您可能只在後台執行了一個命令,但它幾乎總是一些 PowerShell cmdlet。例如命令管道有一個靜默
| Out-Host
附加到它們。您還可以將任何命令包裝在一個函式中以執行單個命令。
希望能回答你的問題。