Anmerkungen

Anmerkungen

Ich habe Ubuntu 18.04 in Hyper-V auf einem Windows 10-Host installiert und auf einigen Ports Funktionen freigegeben, die beim Zugriff auf andere auf dem Host laufende Programme verfügbar sind http://vm-ip-number:port(z. B. http://192.168.0.1:12345). Funktioniert sehr gut.

Ich möchte einen Namen anstelle der IP-Nummer der VM verwenden, um eine Verbindung mit ihr herzustellen (aus den üblichen Gründen, da dies in Konfigurationsdateien erfolgt). Bei vollständigen Linux- oder MacOS-Servern würde ich den Host sich selbst mit Zeroconf ankündigen lassen, aber einige Recherchen haben ergeben, dass dies für Windows 10 über VM-Grenzen hinweg nicht gut funktioniert.

Ein anderer Ansatz könnte darin bestehen, dass Hyper-V der VM einen von mir bereitgestellten Namen zuweist, der dann verfügbar ist, wenn die VM aktiv ist. Ich bin jedoch nicht gut genug mit Hyper-V vertraut, um zu wissen, ob dies möglich ist oder nicht. Die Installation zusätzlicher Tools nur zu diesem Zweck im Gast ist akzeptabel, im Host nur, wenn nötig.

Ich möchte lediglich während der Ausführung auf die VM zugreifen können, http://my-own-nameohne die IP-Nummer irgendwo fest zu codieren.

Vorschläge?

Antwort1

Das folgende PowerShell-Skript generiert eine hostsDatei, die die IP-Adressen und VM-Namen aller laufenden VMs enthält:

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

Einige Hinweise:

  • Das Skript muss als Administrator ausgeführt werden.

  • DerSet-InhaltehostsDer Befehl benötigt einen besseren Pfadparameter, da er derzeit die Datei im aktuellen Ordner überschreibt .

  • Wenn Sie die Datei nicht hostsüberschreiben, sondern anhängen möchten, verwenden Sie Inhalt hinzufügen Befehl stattdessen. Auf diese Weise können Sie mit einer Anfangsdatei beginnen hostsund diese einfach anhängen.

  • Der Schreib-Ausgabe Der Befehl gibt den ersten Eintrag im ipaddressesFeld aus. Wenn sowohl IPv4 als auch IPv6 aktiviert sind, enthält die Liste zwei Einträge, wobei der erste Eintrag normalerweise IPv4 ist.

Eine Beispieldatei hosts, die von diesem Skript für meine laufende VM generiert wurde:

172.17.223.121 Windows10Test

(Es ist wahrscheinlich besser, Leerzeichen in den VM-Namen zu vermeiden, da sonst mehr Arbeit am Skript erforderlich ist.)

Antwort2

Fügen Sie die IP-Adresse in die HOSTS-Datei von Windows ein. Der vollständige Pfad lautet C:\Windows\System32\drivers\etc\hosts. Führen Sie Notepad (oder einen beliebigen Texteditor) als Administrator aus und öffnen Sie die Datei mit Ctrl+ O. Fügen Sie dann die IP-Adresse hinzu. Das Format lautet IP-Adresse und Gastname. Hier ist ein Beispiel:

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

192.168.0.1 myguest

Weitere Informationen finden Sie unterWikipedia: hosts(Datei).

Antwort3

Ich habe eine Möglichkeit gefunden, von anderen Gast-VMs oder dem Host aus eine Verbindung per Namen zu Gast-VMs herzustellen. Dabei verwende ich Namen, die automatisch von Hyper-V verwaltet werden:

  1. Verbinden Sie den Gast mit dem Standard-Switch (dies ist die Standardeinstellung für eine neue VM).
  2. Stellen Sie die IP-Adresse des Gasts auf DHCP ein (dies ist die Standardeinstellung für eine neue VM).
  3. Legen Sie den Computernamen/Hostnamen im Gastbetriebssystem auf einen eindeutigen Namen fest, z. B. myfirstvm. Das DNS-Suffix spielt keine Rolle.
  4. Versuchen Sie, von einer anderen VM oder dem Host aus Kontakt aufzunehmen <host_name>.mshome.net. Wenn Sie den Hostnamen beispielsweise auf festgelegt haben myfirstvm, versuchen Sie, myfirstvm.mshome.netvom Host aus einen Ping zu senden.

Erläuterung:

Auf meinem System fand ich eine Datei im selben Verzeichnis wie die hostsDatei mit dem Namen hosts.ics. Sie schien Einträge für alle meine Gäste zu enthalten, die anDefault Switch und ein Eintrag für das Basissystem, aber alle mit dem Suffix mshome.net. Ich glaube, dass Netzwerkadapter, die mit dem Standard-Switch verbunden sind, die Funktion „Internetverbindungsfreigabe“ verwenden, die diese hosts.icsDatei automatisch erstellt und verwaltet. Wenn Ihr Gast bootet, fordert er per DHCP eine IP-Adresse an und versucht, sich beim in Hyper-V integrierten DNS-Server zu registrieren. Ich glaube, dass Hyper-V den Namen, den der Gast zu registrieren versucht, nimmt und ihn in dieser hosts.icsDatei mit dem neuen Suffix speichert mshome.net. Wenn zwei Ihrer Gast-VMs versuchen, denselben Namen zu registrieren, wird dieser Vorgang abgebrochen.

Ich bin mir nicht sicher, ob dies eine neue Funktion ist oder schon immer da war. Gefunden unter Windows 11 Pro, Hyper-V 10.0.22000.1

Antwort4

Dieses Powershell-Skript basiert aufLukas Schlather's Antwort (https://superuser.com/a/1485949/280673) auf diese Frage.

Der wichtigste Unterschied besteht darin, dass nicht die gesamte Hosts-Datei mit den IP-Adressen Ihrer VMs überschrieben wird, sondern stattdessen neue Einträge angehängt werden, wenn neue VMs vorhanden sind, und die Adressen bereits vorhandener Einträge überschrieben werden. Dadurch sollte die Notwendigkeit entfallen, Backups zu erstellen, und andere Einträge in der Hosts-Datei, die Sie möglicherweise für die lokale Entwicklung oder andere Zwecke erstellt haben, bleiben erhalten.

#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."
}

Anmerkungen

Abhängig von Ihrer VM müssen Sie möglicherweise zusätzliche Pakete innerhalb der VM installieren, zum Beispielhypervauf Arch, bevor Sie die IP herausfinden können, die der VM von HyperV und Powershell zugewiesen wird. Dies wird wahrscheinlich zwischen verschiedenen Betriebssystemen unterschiedlich sein, daher müssen Sie wahrscheinlich eine Anleitung für Ihr System nachschlagen (oder eine neue Frage stellen), wenn Sie die Adresse nicht von der Hostseite abrufen können.

Ich habe den Backup-Abschnitt ausgelassen und nur auskommentiert, um das Experimentieren mit dem Skript und die Iteration zu erleichtern. Außerdem soll es einfacher sein, Backups an einem sinnvolleren Ort zu erstellen, falls diese benötigt werden (Backups sind nicht erforderlich, wenn keine Änderungen vorgenommen werden, also erstellen Sie sie erst kurz vor dem Schreiben der Änderungen).

Ich habe auch den Kommentar dazu, wie der reguläre Ausdruck zum Ersetzen der Adresse funktioniert, in den Code eingefügt, statt außerhalb hier im Post-Text. Dies soll es einfacher machen, dem Code zu folgen, falls der Verweis auf diesen Post nach einigem Kopieren und Einfügen verloren geht, und hoffentlich hilfreich sein, falls jemand Änderungen daran vornehmen möchte.

verwandte Informationen