
為什麼Invoke-Command
遠端運行命令時給出的結果與在完全相同的系統上本地運行完全相同的命令時給出的結果不同?
這些遠端呼叫的命令顯示 4 個空白行:
PS > Invoke-Command cluster02 { cmd /c dir c:\ | select-string 'bytes free' }
雖然這些本地命令按預期輸出:
PS > Invoke-Command cluster02 { cmd /c dir c:\ | select-string 'bytes free' }
11 Dir(s) 828,179,570,688 bytes free
如果我先啟動Enter-PSSession cluster02
然後運行它們,這兩個命令都會返回預期的輸出。
這是舊的 PowerShell(Windows 2012)上的錯誤還是我錯過了一些 PS 功能?如果它是錯誤或特性,它什麼時候會顯現出來?換句話說,從這種奇怪的行為可以學到什麼嗎?
答案1
您遇到的問題是您嘗試使用cmd /c
cmddir
命令遠端執行,然後將其遠端傳輸到 PowerShell 命令。
雖然您希望它在遠端運行時能夠與本地完全一樣地工作,但眾所周知,這會存在差異並導致混亂。
如中所述遠端運行時需要使用者設定檔的命令可能會失敗郵政
問題是,當您連接到遠端電腦時,您並沒有啟動完整的使用者環境。從技術上講,您並不是通常意義上的「登入」機器。是的,您正在進行身份驗證,但方式與對共用資料夾進行身份驗證的方式大致相同。您的遠端連線沒有完整的使用者設定文件,因此任何期望的連線都可能會出錯並失敗(即使它們沒有顯示這些錯誤)。
不幸的是,這個問題沒有簡單的解決方法。
當我Invoke-Command -ScriptBlock {}
在遠端電腦上運行時,我嘗試盡可能將命令保留為 PowerShell。如果您混合使用 cmd 和 PowerShell,則應該進行廣泛的測試,因為它的工作方式可能與您以互動方式登入系統時執行它時的工作方式不同。
遠端 PowerShell,取得磁碟機可用空間(以位元組為單位)(否cmd
)
Invoke-Command -ComputerName Cluster02 -ScriptBlock {(Get-PSDrive C).Free}
輸出
599257099776
解決方法
將 的輸出設為Invoke-Command
變量,然後從中選擇字串和行屬性似乎可以實現您喜歡的所需輸出。
PowerShell(變體 1)
$var = Invoke-Command cluster02 -ScriptBlock { cmd /c "dir c:\" };
($var| select-string 'bytes free').Line.Trim();
輸出
11 Dir(s) 36,011,925,504 bytes free
問題很可能是由於調用cmd /c
,然後 PowerShell 透過管道在遠端調用的會話中從中選擇匹配的字串。我透過保存正確返回的完整輸出來解決這個問題,invoke-command
作為 外部的變量invoke-command
,然後invoke-command
也在 之外相應地解析該變量。
PowerShell(變體 2)
這是與上面相同的處理,但不是將變數放入混合中,而是將右側通過管道傳遞Invoke-Command
給Select-String
查詢。
Invoke-Command cluster02 -ScriptBlock { cmd /c "dir c:\"; } | select-string 'bytes free';
或甚至是這樣的事情......
(Invoke-Command cluster02 -ScriptBlock { cmd /c "dir c:\"; } | select-string 'bytes free').Line.Trim()
答案2
(如果您喜歡這個 TLDR 版本,請對已接受的答案進行投票)
TLDR 指南
遠端運行腳本塊時:
- 如果可能,請避免執行任何非本機 PowerShell 的內容。例如替換
cmd /c dir c:\|sls 'bytes free'
為(Get-PSDrive C).Free
. - 如果不是,則在遠端 shell 中進行最少的處理。例如,將 select-string 移到遠端 shell 之外,如下所示:
Invoke-Command cluster02 { cmd /c "dir c:\" } | sls 'bytes free'
。