ノート

ノート

Windows 10 ホストの Hyper-V に Ubuntu 18.04 をインストールし、アクセス時にホスト上で実行されている他のプログラムで使用できるいくつかのポートの機能を公開しましたhttp://vm-ip-number:port(つまりhttp://192.168.0.1:12345)。非常にうまく動作します。

VM に接続するために、IP 番号ではなく名前を使用したいと思います (これは構成ファイルに記載されるため、通常の理由のためです)。完全な Linux または MacOS サーバーの場合は、zeroconf を使用してホスト自身をアナウンスさせますが、調べてみると、VM 境界を越えた Windows 10 ではこれがうまく機能しないことがわかりました。

別の方法としては、Hyper-V で VM に私が指定した名前を割り当て、VM が起動したときにその名前を使用できるようにするという方法がありますが、Hyper-V に詳しくないため、これが可能かどうかわかりません。ゲストにこの目的のためだけに追加ツールをインストールすることは許容されますが、ホストには必要な場合にのみインストールします。

http://my-own-name私が望むのは、IP 番号をどこにもハードコードせずに、実行中に VM にアクセスできるようにすることです。

提案はありますか?

答え1

次の PowerShell スクリプトは、hosts実行中のすべての VM の IP アドレスと VM 名を含むファイルを生成します。

get-vm | Get-VMNetworkAdapter | ? IPAddresses -ne $null | % {Write-Output "$($_.ipaddresses[0]) $($_.VMName)"} | Set-Content -Path ".\hosts"

注意すべき点:

  • スクリプトは管理者として実行する必要があります。

  • セット内容hosts現時点では、このコマンドは現在のフォルダー内のファイル を上書きするため、より適切な Path パラメータが必要です。

  • hostsファイルを上書きせずに追加したい 場合は、コンテンツの追加 代わりにコマンドを使用してください。この方法では、最初のファイルから開始してhosts、それに追加するだけです。

  • 書き込み出力 コマンドは、フィールドの最初のエントリを出力しますipaddresses。 IPv4 と IPv6 の両方が有効になっている場合、リストには 2 つのエントリが含まれ、最初のエントリは通常 IPv4 のエントリになります。

hostsこのスクリプトによって実行中の 1 つの VM 用に生成されたサンプルファイル:

172.17.223.121 Windows10Test

(VM 名に空白を入れないようにした方がよいでしょう。そうしないと、スクリプトにさらに作業が必要になります。)

答え2

Windows HOSTS ファイルに IP アドレスを追加します。フル パスは ですC:\Windows\System32\drivers\etc\hosts。メモ帳 (または任意のテキスト エディター) を管理者として実行し、Ctrl+を使用してそのファイルを開きますO。次に、IP アドレスを追加します。形式は、IP アドレス、ゲスト名となります。次に例を示します。

# This is a comment
# 127.0.0.1 localhost loopback
# ::1 localhost

192.168.0.1 myguest

詳細については、Wikipedia: hosts(ファイル)

答え3

次のように、Hyper-V によって自動的に管理される名前を使用して、他のゲスト VM またはホストからゲスト VM に名前で接続する方法を見つけました。

  1. ゲストをデフォルト スイッチに接続します (これは新しい VM のデフォルトです)。
  2. ゲストの IP アドレスを DHCP に設定します (これは新しい VM のデフォルトです)。
  3. ゲスト OS 内のコンピューター名/ホスト名を一意のものに設定します (例: ) myfirstvm。DNS サフィックスは重要ではありません。
  4. 別の VM またはホストから に接続してみます<host_name>.mshome.net。たとえば、ホスト名を に設定した場合はmyfirstvmmyfirstvm.mshome.netホストから ping を実行します。

説明:

hosts私のシステムでは、ファイルと同じディレクトリに というファイルを見つけましたhosts.ics。そこには、 に接続されているすべてのゲストのエントリが含まれているようです。Default Switch ベースシステムのエントリですが、すべてにサフィックス が付きますmshome.net。デフォルト スイッチに接続されているネットワーク アダプターは、インターネット接続の共有機能を使用して、このhosts.icsファイルを自動的に作成および管理していると考えられます。ゲストが起動すると、DHCP によって IP アドレスを要求し、Hyper-V に組み込まれている DNS サーバーに自分自身を登録しようとします。Hyper-V は、ゲストが登録しようとしている名前を取得し、hosts.ics新しいサフィックス を付けてこのファイルに保存すると考えられますmshome.net。2 つのゲスト VM の両方が同じ名前を登録しようとすると、このプロセスは中断されます。

これは新しい機能なのか、以前からあった機能なのかは不明です。Windows 11 Pro、Hyper-V 10.0.22000.1 で見つかりました。

答え4

このPowerShellスクリプトは、ルーク・シュラザーの回答(https://superuser.com/a/1485949/280673)この質問に対して

最も重要な違いは、VM の IP アドレスでホスト ファイル全体を上書きするのではなく、新しい VM がある場合は新しいエントリを追加し、既存のエントリのアドレスを上書きすることです。これにより、バックアップを作成する必要がなくなり、ローカル開発やその他の目的で作成したホスト ファイル内の他のエントリが保持されます。

#Requires -RunAsAdministrator

# Based on: https://superuser.com/a/1485949

Write-Host "Fix entries for local HyperV VMs in hosts file."

Set-StrictMode -Version 3.0
$ErrorActionPreference = "Stop"
$hostsFile = "${env:SystemRoot}/System32/drivers/etc/hosts"

$hostsFileContentOriginal = (Get-Content $hostsFile)
$hostsFileContent = $hostsFileContentOriginal

Write-Debug "Original hosts file content:"
Write-Debug ($hostsFileContent | Out-String)
Write-Debug "`n`n"

foreach ($vm in (Get-VM | Get-VMNetworkAdapter))
{
   $vmName = $($vm.VMName)
   $vmNameSanitized = $vm.VMName.ToLower() -replace '[. ]',''
   $hostName = "${vmNameSanitized}.local"
   Write-Verbose "Porcessing $vm."
   if (0 -lt $vm.IPAddresses.Length)
   {
      Write-Verbose "VM ${vmname} has IP addresses, updating hosts file."
      $address = $vm.IPAddresses[0]
      Write-Verbose "Selected IP Address for ${vmname}: $address."
      Write-Debug "All IP Addresses for ${vmname}: $($vm.IPAddresses)."

      $vmPreviouslyAddedToHostsFile = $hostsFileContent -match ".*$hostName.*"
      if($vmPreviouslyAddedToHostsFile)
      {
         Write-Verbose "VM $vmName already present in hosts, updating entry."
         # # Regex explanation
         # - `([^\d]*)` is a grouping `()` of 0 or more of the character group `[]*` that contains no digits `^\d`.
         # - `(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})` is a grouping `()` of 4 collections of 1 to 3 digits `\d{1,3}`, separated by a dot `\.`, which should match an ipv4 address.
         # - `(\s+$hostName.*)` is a grouping `()` that matches 1 or more spaces `\s+`, followed by the content of the hostname variable `$hostName`, followed by 0 or more of any characters `.*`.
         # # Substitution expression explanation
         # `${n}` is used to access the n-th (1 indexed) grouping from the regex.
         # Because we want to access the `$address` variable we can't use literal strings `''` but have to use normal strings instead `""`.
         # This results in having to escape the `$` character when doing the group substitution access.
         # # Caveat emptor
         # This only works for ipv4 addresses as written.
         # If you want to support ipv6 addresses, consider using `([a-f0-9:]+:+)+[a-f0-9]+` from https://stackoverflow.com/a/37355379 .
         # It will fail in interesting ways if the entry is commented out and there are digits in the comment in a position preceding the address.
         $hostsFileContent = $hostsFileContent -replace "([^\d]*)(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(\s+$hostName.*)","`${1}$address`${3}" -join "`r`n"
      }
      else
      {
         Write-Verbose "VM $vmName not previously in hosts, appending entry."
         $hostsFileContent += "$address $hostName" -join "`r`n"
      }
   }
   else
   {
      Write-Verbose "VM ${vmname} doesn't have IP addresses, skipping."
   }
}

$originalAsString = ($hostsFileContentOriginal | Out-String)
$updatedAsString = ($hostsFileContent | Out-String)

Write-Debug "`n`nUpdated hosts file content:"
Write-Debug "$updatedAsString"

if($originalAsString -ne $updatedAsString)
{
   Write-Host "There are new addresses for VMs, updtating hosts file."

   # $datestring = (Get-Date -Format "o") -replace '[:\-]','-'
   # $backupHostsFile = "$hostsFile.${datestring}.bak"
   # Write-Verbose "Backing up hosts file to $backupHostsFile."
   # Copy-Item $hostsFile $backupHostsFile

   # Write-Verbose "Setting new hosts file content."

   Set-Content -Path $hostsfile -Value $hostsFileContent -Encoding UTF8
}
else
{
   Write-Host "No new VMs or addresses, exiting."
}

ノート

VMによっては、VM内に追加のパッケージをインストールする必要があるかもしれません。例えば、hypervarch では、HyperV と PowerShell から VM に割り当てられる IP を調べる前に、この作業を行う必要があります。これはオペレーティング システムによって異なる可能性が高いため、ホスト側からアドレスを取得できない場合は、システムのガイドを調べる (または新しい質問を投稿する) 必要があるでしょう。

スクリプトの実験や反復を簡単にするため、バックアップ セクションはそのままにしてコメント アウトしました。また、より適切な場所でバックアップが必要な場合にバックアップを簡単に作成できるようにしました (変更が行われていない場合はバックアップは不要であるため、変更が書き込まれる直前までバックアップを作成しないでください)。

また、アドレスを置換する正規表現がどのように機能するかについての解説を、投稿本文の外部ではなく、コード内に記述しました。これは、コピー アンド ペースト後にこの投稿への参照が失われた場合にコードを追跡しやすくするためであり、誰かが投稿に変更を加えたい場合にも役立つはずです。

関連情報