Instalei o Ubuntu 18.04 no Hyper-V em um host Windows 10 e expus funcionalidades em algumas portas, que estão disponíveis para outros programas em execução no host ao acessar http://vm-ip-number:port
(ou seja http://192.168.0.1:12345
,). Funciona muito bem.
Eu gostaria de usar um nome em vez do número IP da VM para conectar-se a ela (por todos os motivos usuais, pois isso estará nos arquivos de configuração). Para servidores Linux ou MacOS completos, eu deixaria o host se anunciar usando o zeroconf, mas algumas pesquisas indicaram que isso não funciona bem para o Windows 10 além dos limites da VM.
Outra abordagem pode ser fazer com que o Hyper-V atribua à VM um nome fornecido por mim, que estará disponível quando a VM estiver ativa, mas não estou familiarizado o suficiente com o Hyper-V para saber se isso é possível ou não. Instalar ferramentas adicionais apenas para isso no convidado é aceitável, no host somente se necessário.
Tudo que eu quero é poder http://my-own-name
acessar a VM durante a execução sem codificar o número IP em qualquer lugar.
Sugestões?
Responder1
O seguinte script do PowerShell gerará um hosts
arquivo que contém os endereços IP e nomes de VM para todas as VMs em execução:
get-vm | Get-VMNetworkAdapter | ? IPAddresses -ne $null | % {Write-Output "$($_.ipaddresses[0]) $($_.VMName)"} | Set-Content -Path ".\hosts"
Alguns pontos a serem observados:
O script precisa ser executado como administrador.
ODefinir conteúdo O comando precisa de um parâmetro Path melhor, pois atualmente ele substituirá o
hosts
arquivo na pasta atual.Se você não deseja que o
hosts
arquivo seja sobrescrito, mas anexado, use Adicionar conteúdo comando em vez disso. Dessa forma, você pode começar a partir de umhosts
arquivo inicial e apenas anexar a ele.O Saída de gravação comando gera a primeira entrada no
ipaddresses
campo. Se IPv4 e IPv6 estiverem habilitados, a lista conterá duas entradas, onde a primeira entrada geralmente é IPv4.
Um hosts
arquivo de exemplo que foi gerado para minha VM em execução por este script:
172.17.223.121 Windows10Test
(Provavelmente é melhor evitar espaços em branco nos nomes das VMs, ou será necessário mais trabalho no script.)
Responder2
Adicione o endereço IP no arquivo HOSTS do Windows. O caminho completo é C:\Windows\System32\drivers\etc\hosts
. Execute o Bloco de Notas (ou qualquer editor de texto) como administrador e abra esse arquivo com Ctrl+ O. Em seguida, adicione o endereço IP. O formato será o endereço IP e depois o nome do convidado. Aqui está um exemplo:
# This is a comment
# 127.0.0.1 localhost loopback
# ::1 localhost
192.168.0.1 myguest
Para mais informações, leiaWikipédia: hosts (arquivo).
Responder3
Encontrei uma maneira de conectar por nome a VMs convidadas de outras VMs convidadas ou do host, usando nomes que são gerenciados automaticamente pelo Hyper-V, como segue:
- Conecte o convidado ao switch padrão (este é o padrão para uma nova VM).
- Defina o endereço IP como DHCP no convidado (este é o padrão para uma nova VM).
- Defina o nome do computador/nome do host no sistema operacional convidado para algo exclusivo, por exemplo
myfirstvm
. O sufixo DNS não importa. - De outra VM ou do host, tente entrar em contato com
<host_name>.mshome.net
, por exemplo, se você definir o nome do host comomyfirstvm
, tente fazer pingmyfirstvm.mshome.net
do host.
Explicação:
No meu sistema encontrei um arquivo no mesmo diretório do hosts
arquivo chamado hosts.ics
. Parecia conter entradas para todos os meus convidados anexadas aDefault Switch
e uma entrada para o sistema básico, mas todos com o sufixo mshome.net
. Acredito que os adaptadores de rede conectados ao switch padrão usam o recurso Compartilhamento de conexão com a Internet, que cria e mantém esse hosts.ics
arquivo automaticamente. Quando o seu convidado inicializa, ele solicita um endereço IP por DHCP e tenta registrar-se no servidor DNS integrado ao Hyper-V. Acredito que o Hyper-V pega o nome que o convidado tenta cadastrar e armazena neste hosts.ics
arquivo com um novo sufixo mshome.net
. Se duas de suas VMs convidadas tentarem registrar o mesmo nome, esse processo será interrompido.
Não tenho certeza se este é um recurso novo ou sempre esteve aqui. Encontrado no Windows 11 Pro, Hyper-V 10.0.22000.1
Responder4
Este script do PowerShell se baseiaLucas Schlathera resposta (https://superuser.com/a/1485949/280673) para esta pergunta.
A diferença mais importante é que ele não substitui todo o arquivo hosts pelos endereços IP das suas VMs, mas em vez disso anexa novas entradas se houver novas VMs e substitui os endereços de entradas pré-existentes. Isso deve eliminar a necessidade de fazer backups e preservar outras entradas no arquivo hosts que você possa ter feito para desenvolvimento local ou outros fins.
#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."
}
Notas
Dependendo da sua VM, pode ser necessário instalar pacotes adicionais dentro da VM, por exemplohyperv
no arch, antes de descobrir o IP atribuído à VM do HyperV e do PowerShell. Isso provavelmente variará entre os diferentes sistemas operacionais, então você provavelmente terá que procurar um guia para o seu sistema (ou postar uma nova pergunta) se não conseguir obter o endereço do host.
Saí da seção de backup e apenas comentei, para facilitar a experimentação e a iteração no script. Também para tornar mais fácil fazer backups se eles forem desejados em um local mais sensato (não há necessidade de backups se nenhuma alteração estiver sendo feita, portanto, não os faça antes de as alterações serem gravadas).
Também coloquei o comentário de como funciona a regex para substituição do endereço no código, ao invés de fora aqui no corpo do post. Isso é para tornar mais fácil seguir o código caso a referência a esta postagem seja perdida após alguma cópia e colagem e, esperançosamente, seja útil caso alguém queira fazer alterações nele.