かつて山市良と呼ばれたおじさんのブログ

セイテクエンジニアのブログ  かつて山市良と呼ばれたおじさんのブログ  vol.237 自動化の強い味方、PowerShell DirectとCopy-VMFile|Hyper-V 小技・裏技集

 

 

vol.237 自動化の強い味方、PowerShell DirectとCopy-VMFile|Hyper-V 小技・裏技集

2026年09月28日配信
2026年09月28日更新
執筆者:山内 和朗

 「Hyper-V小技・裏技集」シリーズでは、Hyper-Vの仮想環境を利用していて、知っていると便利な小技や裏技を紹介します。今回は、PowerShell DirectとCopy-VMFileの使いこなしについて。これらをうまく活用すれば、Hyper-VホストのPowerShellスクリプトを使用して、VMのゲスト側タスクの自動化ができます。

 

※ここで紹介するサンプルコードは、PowerShellスクリプト(.ps1)内に記述することを想定しています。-ErrorAction Stopパラメーターは、エラー時にスクリプト全体を停止します。PowerShellウィンドウに入力して実行した場合は、エラーが発生しても以後のスクリプトは停止しないため、別のエラーが発生する可能性があることに注意してください。

 

Hyper-VのPowerShell Direct、知らなきゃ、使わなきゃ損

 

 PowerShellの「PowerShell Remoting」は、ネットワーク経由でPowerShellのスクリプトブロックをリモート実行(Invoke-Command)したり、リモートセッションに接続(Enter-PSSession)したりできます。スクリプトブロックを実行するリモートのコンピューターは、-ComputerNameパラメーターで指定します。

 

 実は、Invoke-CommandやEnter-PSSessionは、-VMNameや-VMId、-ContainerIdパラメーターをサポートしており、Windowsゲストを実行するHyper-VのVMやWindowsコンテナーに対して使用することができます。この機能は「PowerShell Direct」と呼ばれるHyper-V Virtual Machine Managementサービス(vmms、VMの場合)およびHyper-Vホストコンピューティングサービス(vmcompute、Windowsコンテナーの場合)に依存する機能です(画面1)。PowerShell Remotingと同様に、PowerShell DirectではゲストOS側の資格情報が必要です。-Credentialパラメーターにユーザー名を渡した場合はパスワードの対話入力が求められます。資格情報([PSCredential]またはGet-Credential)を渡した場合は、対話なしで実行できます。

 

Invoke-Command -VMName "VM名" -Credential ユーザー名または資格情報 -ScriptBlock { スクリプトブロック }
Enter-PSSession -VMName "VM名" -Credential ユーザー名または資格情報

 

画面1 Windowsゲストを実行するVMに対して使えるPowerShell Direct。VMBus経由で通信するため、VMのネットワーク接続に依存せず利用できる

画面1 Windowsゲストを実行するVMに対して使えるPowerShell Direct。VMBus経由で通信するため、VMのネットワーク接続に依存せず利用できる

 

 PowerShell Directを受け入れる側のVMの条件はWindowsゲストであることだけです。ホスト側はWindows PowerShell 5.1とPowerShell 7のどちらからでも使用できますが、Windowsゲスト側ではWindows標準のWindows PowerShell 5.1がWindowsに組み込まれているHyper-V統合コンポーネントによって呼び出されます。ホストとゲスト間の通信には内部的なチャネル(Hyper-Vの場合は仮想マシンバス《VMBus》)が使用されるため、VMやコンテナーのネットワーク接続に依存せずに利用できます。また、ネットワーク経由のPowerShell Remotingの場合、受け付ける側でEnable-PSRemotingを実行して機能を有効化する必要がありますが、PowerShell Directではそのような事前準備なしで手軽に利用できます。つまり、Hyper-Vホスト上にWindows VMがあればすぐに利用できます。

 

 前述したように、PowerShell Directの受け取り側はWindowsゲストである必要があり、ゲスト側のWindows PowerShell 5.1でスクリプトブロックが実行されます(Windows PowerShell 5.1のセッション内でpwsh.exeを実行することでPowerShell 7も使用可能)。Linuxゲストに対しては機能しません。代替としては、PowerShell 7(6以降)のSSH経由のPowerShell Remoting(SSH Remoting)を使用できます(画面2)。SSH Remotingを利用するには、LinuxゲストにPowerShell 7(6以降)とOpenSSH Serverのインストールと構成が必要です。SSH Remotingのためには、/etc/ssh/sshd_configにSubsystem powershell /usr/bin/pwsh -sshs -NoLogoを追加します。なお、Windows PowerShell 5.1は、SSH Remotingに対応していないため、実行元のHyper-VホストでもPowerShell 7を使用する必要があります。ちなみに、Windows Server 2019以降にはOpenSSH Serverが搭載されるようになりましたが、Windows ServerのOpenSSH ServerをSSH Remoting用に構成(C:¥ProgramData¥ssh¥sshd_configで構成)することも可能です(実行例)。

 

参考:
SSH 経由の PowerShell リモート処理(PowerShell remoting over SSH)|PowerShell(Microsoft Learn)

 

vol237_scr02b
画面2 PowerShell DirectはLinuxゲストのVMに対しては機能しないが、PowerShell 7のSSH Remoting(VMのネットワーク経由)で代替可能

 

 Invoke-CommandやEnter-PSSessionにパスワードを渡すパラメーターがないため、パスワード認証によるSSH接続の場合は入力プロンプトと対話する必要があり、スクリプト内での利用は難しいでしょう。公開鍵認証によるSSH接続の場合は対話なしで実行/接続できます(必要に応じて-KeyFilePathに秘密鍵ファイルを指定します)。なお、秘密鍵がパスフレーズで保護されている場合は、ssh-agentサービスの有効化と開始、ssh-addによる秘密鍵の登録でパスフレーズの入力を回避できます。

 

Set-Service ssh-agent -StartupType Automatic
Start-Service ssh-agent
ssh-add $HOME\.ssh\秘密鍵ファイル
Enter passphrase for ...: パスフレーズ

 

WindowsとLinuxの両方で使えるCopy-VMFile

 

 Hyper-Vの統合サービスの1つ「ゲストサービス」は、Hyper-VホストからVMのゲストへの一方向のファイルコピーを可能にする機能です。VMでゲストサービスを有効にすると(既定は無効)、ゲスト側で対応するサービス(Windows VMのHyper-V Guest Service Interface、Linux VMのhv-fcopy-daemonまたはhypervfcopyd)が実行中となり、Hyper-Vホストから「Copy-VMFile」を使用して、ホストの指定したファイルをゲストの指定したパスにコピーすることができるようになります。PowerShell Directとは異なり、資格情報は必要ありません。

 

Copy-VMFile "VM名" -SourcePath "コピー元ファイルのパス" -DestinationPath "ゲスト側のコピー先フォルダーパス" -FileSource Host -Force

 

 Copy-VMFileは、PowerShell Direct(Linuxゲストの場合はSSH Remotingで代替)と組み合わせると便利です。例えば、PowerShellスクリプト(.ps1)をHyper-Vホスト側で用意し、Copy-VMFileを使用してVMのゲストにコピーしたら、PowerShell DirectやSSH Remotingを使用してゲスト側にコピーしたスクリプトを実行させることができます(画面3)。

 

画面3 Copy-VMFileは、WindowsまたはLinuxゲストのVMに対してホストからファイルをコピーする機能。統合サービスの「ゲストサービス」
画面3 Copy-VMFileは、WindowsまたはLinuxゲストのVMに対してホストからファイルをコピーする機能。統合サービスの「ゲストサービス」

 PowerShell DirectとCopy-VMFileを利用した役に立つサンプルスクリプトをいくつか考えてみました。今回は長くなってしまったので、1つだけ紹介します(Copy-VMFileの例は次回)。

 

VMを再起動(その2)とクラスターVMの停止

 

 前回はGet-VM、Stop-VM、Start-VMを組み合わせてHyper-VホストからVMのゲストOSを再起動するPowerShellスクリプトを紹介しました。次のPowerShellスクリプトもまた、VMのゲストOSを再起動します。今回のスクリプトは、Invoke-Commandを使用して、ホストからVM側のRestart-Computerを実行して再起動を開始します。再起動の完了はGet-VMのHeartbeatプロパティで判断しています。なおこのスクリプトでは、平文のパスワードをスクリプト内に直接記述しています。これはセキュリティ上推奨されない方法です。スクリプトにパスワードを含めない方法については、次回説明します。

 

$username = ".\Administrator"
$password = "P@ssw0rd!"
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$cred = [PSCredential]::new($username, $securePassword)
# または
# $cred = Get-Credential

$vmName = "vm01"

$vm = Get-VM -Name $vmName -ErrorAction Stop
Invoke-Command -VMName $vm.Name -Credential $cred -ScriptBlock { Restart-Computer -Force }
do {
    Start-Sleep -Seconds 1
} until ($vm.Heartbeat -like "NoContact")
Write-Host "$($vm.Name) is Rebooting..."
do {
    Start-Sleep -Seconds 1
} until ($vm.Heartbeat -like "Ok*")
Write-Host "$($vm.Name) is Rebooted."

(プレーンテキストでダウンロード/表示)


画面4 Invoke-Commandを使用して、VM側でRestart-Computerを実行し、再起動を開始する(画面のクリックで拡大)
画面4 Invoke-Commandを使用して、VM側でRestart-Computerを実行し、再起動を開始する(画面のクリックで拡大)

 

 LinuxゲストのVMの場合は、PowerShell Directの代わりに、PowerShell 7のSSH Remotingを利用することで対応できます(画面5)。sudo rebootやsudo shutdown -r nowをパスワード入力なしで実行できるように(SSH Remotingはリモート実行であるため、ローカル実行とは異なりrebootやshutdownをsudoで実行する必要があります)、sudo visodoを使用して/etc/sudoers(または/etc/sudoers.d/内のファイルの最後に次の行を記述して保存します(shutdownとrebootのパスは環境に合わせてください。)。

 

ユーザー名        ALL=(root) NOPASSWD:  /usr/sbin/shutdown, /usr/sbin/reboot

 

画面5 SSH Remotingを使用したLinux VMの再起動(画面のクリックで拡大)

画面5 SSH Remotingを使用したLinux VMの再起動(画面のクリックで拡大)

 

 フェールオーバークラスターを再起動したり、シャットダウンしたりする場合は、単純にRestart-ComputeやStop-Computerを実行することは推奨されません。クラスターをシャットダウンしてからノードを停止するという手順が推奨されます。次の例は、2ノードクラスターの最初のノードでInvoke-Commandを使用してクラスターのシャットダウン(Stop-Cluster -Force)を実行してから、すべてのVMをシャットダウンして停止します。

$username = ".\Administrator"
$password = "P@ssw0rd!"
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$cred = [PSCredential]::new($username, $securePassword)
# または
#$cred = Get-Credential

$vmNames = @("node01","node02")

$vms = Get-VM -Name $vmNames -ErrorAction Stop
Invoke-Command -VMName $vms[0].Name -Credential $cred -ScriptBlock { 
    Stop-Cluster -Force
}
$vms | Stop-VM -Force
do {
    Start-Sleep -Seconds 1
} until (($vms.State | Select-Object -Unique) -ne "Off")
Write-Host "All nodes are Off."


(プレーンテキストでダウンロード/表示)

 

リファレンス(Microsoft Learn):
Get-VM(Hyper-V)| Start-VM(Hyper-V)| Stop-VM(Hyper-V)| Invoke-Command(PowerShell Core)| Eenter-PSSession(PowerShell Core)| Copy-VMFile(Hyper-V)| Restart-Computer(PowerShell Management)| Stop-Computer(PowerShell Management)| Stop-Cluster(FailoverClusters)

Hyper-V 小技・裏技集 (1)|(2)|(3)|(4)|(5)|(6)

blog_yamanxworld_subscribe

blog_yamanxworld_comment

blog_yamanxworld_WP_ws2025

最新記事