programing

호스트 파일을 조작하는 파워셸

lastmoon 2023. 9. 14. 23:25
반응형

호스트 파일을 조작하는 파워셸

호스트 파일의 내용을 업데이트하기 위해 파워셸 스크립트를 만들 수 있는지 알아보고 있습니다.

파워셸이나 다른 스크립트 언어를 사용하여 호스트 파일을 조작하는 예가 있는지 아는 사람?

감사해요.

이 모든 대답들은 꽤 정교합니다.호스트 파일 항목을 추가하는 데 필요한 것은 다음과 같습니다.

Add-Content -Path $env:windir\System32\drivers\etc\hosts -Value "`n127.0.0.1`tlocalhost" -Force

IP 주소와 호스트 이름은 탭 문자의 PowerShell 표기인 't'로 구분됩니다.

'n은 새 줄에 대한 PowerShell 표기입니다.

먼저 Vista 또는 Windows 7(윈도우 7)을 사용하는 경우 상승된 프롬프트에서 다음 명령을 실행해야 합니다.

# Uncomment lines with localhost on them:
$hostsPath = "$env:windir\System32\drivers\etc\hosts"
$hosts = get-content $hostsPath
$hosts = $hosts | Foreach {if ($_ -match '^\s*#\s*(.*?\d{1,3}.*?localhost.*)')
                           {$matches[1]} else {$_}}
$hosts | Out-File $hostsPath -enc ascii

# Comment lines with localhost on them:
$hosts = get-content $hostsPath
$hosts | Foreach {if ($_ -match '^\s*([^#].*?\d{1,3}.*?localhost.*)') 
                  {"# " + $matches[1]} else {$_}} |
         Out-File $hostsPath -enc ascii

이 점을 감안하면 정규 표현식을 사용하여 필요에 따라 입력을 조작하는 방법을 알 수 있을 것 같습니다.

Carbon 모듈에는 호스트 항목을 설정하기 위한 Set-HostsEntry 기능이 있습니다.

Set-HostsEntry -IPAddress 10.2.3.4 -HostName 'myserver' -Description "myserver's IP address"

더 발전된 예를 찾고 계신 분이 있다면, 저는 항상 이 요지를 특히 좋아했습니다: https://gist.github.com/markembling/173887

#
# Powershell script for adding/removing/showing entries to the hosts file.
#
# Known limitations:
# - does not handle entries with comments afterwards ("<ip>    <host>    # comment")
#

$file = "C:\Windows\System32\drivers\etc\hosts"

function add-host([string]$filename, [string]$ip, [string]$hostname) {
    remove-host $filename $hostname
    $ip + "`t`t" + $hostname | Out-File -encoding ASCII -append $filename
}

function remove-host([string]$filename, [string]$hostname) {
    $c = Get-Content $filename
    $newLines = @()

    foreach ($line in $c) {
        $bits = [regex]::Split($line, "\t+")
        if ($bits.count -eq 2) {
            if ($bits[1] -ne $hostname) {
                $newLines += $line
            }
        } else {
            $newLines += $line
        }
    }

    # Write file
    Clear-Content $filename
    foreach ($line in $newLines) {
        $line | Out-File -encoding ASCII -append $filename
    }
}

function print-hosts([string]$filename) {
    $c = Get-Content $filename

    foreach ($line in $c) {
        $bits = [regex]::Split($line, "\t+")
        if ($bits.count -eq 2) {
            Write-Host $bits[0] `t`t $bits[1]
        }
    }
}

try {
    if ($args[0] -eq "add") {

        if ($args.count -lt 3) {
            throw "Not enough arguments for add."
        } else {
            add-host $file $args[1] $args[2]
        }

    } elseif ($args[0] -eq "remove") {

        if ($args.count -lt 2) {
            throw "Not enough arguments for remove."
        } else {
            remove-host $file $args[1]
        }

    } elseif ($args[0] -eq "show") {
        print-hosts $file
    } else {
        throw "Invalid operation '" + $args[0] + "' - must be one of 'add', 'remove', 'show'."
    }
} catch  {
    Write-Host $error[0]
    Write-Host "`nUsage: hosts add <ip> <hostname>`n       hosts remove <hostname>`n       hosts show"
}

위의 케빈 레미소스키의 훌륭한 답변을 시작으로 여러 항목을 한 번에 추가/업데이트 할 수 있는 이것을 생각해 냈습니다.나는 또한 탭이 아닌 빈 공간을 찾기 위해 분할의 regex를 변경했습니다.

function setHostEntries([hashtable] $entries) {
    $hostsFile = "$env:windir\System32\drivers\etc\hosts"
    $newLines = @()

    $c = Get-Content -Path $hostsFile
    foreach ($line in $c) {
        $bits = [regex]::Split($line, "\s+")
        if ($bits.count -eq 2) {
            $match = $NULL
            ForEach($entry in $entries.GetEnumerator()) {
                if($bits[1] -eq $entry.Key) {
                    $newLines += ($entry.Value + '     ' + $entry.Key)
                    Write-Host Replacing HOSTS entry for $entry.Key
                    $match = $entry.Key
                    break
                }
            }
            if($match -eq $NULL) {
                $newLines += $line
            } else {
                $entries.Remove($match)
            }
        } else {
            $newLines += $line
        }
    }

    foreach($entry in $entries.GetEnumerator()) {
        Write-Host Adding HOSTS entry for $entry.Key
        $newLines += $entry.Value + '     ' + $entry.Key
    }

    Write-Host Saving $hostsFile
    Clear-Content $hostsFile
    foreach ($line in $newLines) {
        $line | Out-File -encoding ASCII -append $hostsFile
    }
}

$entries = @{
    'aaa.foo.local' = "127.0.0.1"
    'bbb.foo.local' = "127.0.0.1"
    'ccc.foo.local' = "127.0.0.1"
};
setHostEntries($entries)

호스트에서 엔트리를 삭제하는 코드를 작성했습니다.코드를 쉽게 변경하여 코드에서 항목을 추가할 수 있습니다.

$domainName = "www.abc.com"
$rplaceStr = ""
$rHost = "C:\Windows\System32\drivers\etc\hosts"
$items = Get-Content $rHost | Select-String $domainName
Write-host $items
foreach( $item in $items)
{
(Get-Content $rHost) -replace $item, $rplaceStr| Set-Content $rHost
}

자세한 정보는 http://nisanthkv.blog.com/2012/06/13/remove-host-entries-using-powershell/ 을 참조하십시오.

호스트 레코드를 수정하는 데 관리자 권한이 필요한 시간의 99%.파워셸 스크립트 맨 위에 이 코드를 추가해 보십시오.

If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))

{   
$arguments = "& '" + $myinvocation.mycommand.definition + "'"
Start-Process powershell -Verb runAs -ArgumentList $arguments
Break
}

호스트 파일을 처리할 때 가장 큰 어려움은 파일이 어디에 있는지 기억하는 것입니다.PowerShell 프로필에서 호스트 파일을 가리키는 변수를 설정하여 텍스트 편집기에서 쉽게 편집할 수 있습니다.

PowerShell에서 다음을 입력하여 프로필을 엽니다.

C:\> Notepad $profile

추가할 내용:

$hosts = "$env:windir\System32\drivers\etc\hosts"

파일을 저장한 다음 PowerShell을 닫고 다시 열어 관리자로 실행합니다.상향된 권한이 없으면 호스트 파일을 편집할 수 없습니다.

이제 프로파일을 편집할 때와 동일한 방식으로 호스트 파일을 편집할 수 있습니다.

C:\> Notepad $hosts

HOSTS 파일에 새 레코드를 추가하기 위한 간단한 GUI를 만드는 빠른 스크립트를 작성했습니다.창을 열고 호스트 이름과 IP를 요청한 다음 HOSTS 파일에 입력을 추가합니다.

단순화되고 더 깨끗해 보일 수 있을 겁니다하지만 내 사용 사례에는 문제가 없습니다.

맛있게 드세요.

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

$hostsfilelocation = "$env:windir\System32\drivers\etc\hosts"
$readhostsfile = Get-Content $hostsfilelocation

$form = New-Object System.Windows.Forms.Form
$form.Text = 'Update HOSTS File'
$form.Size = New-Object System.Drawing.Size(300,200)
$form.StartPosition = 'CenterScreen'

$AddHosts = New-Object System.Windows.Forms.Button
$AddHosts.Location = New-Object System.Drawing.Point(55,120)
$AddHosts.Size = New-Object System.Drawing.Size(90,25)
$AddHosts.Text = 'Add Record'
$AddHosts.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $AddHosts
$form.Controls.Add($AddHosts)

$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Point(170,120)
$CancelButton.Size = New-Object System.Drawing.Size(75,25)
$CancelButton.Text = 'Cancel'
$CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $CancelButton
$form.Controls.Add($CancelButton)

$Hostslabel = New-Object System.Windows.Forms.Label
$Hostslabel.Location = New-Object System.Drawing.Point(10,20)
$Hostslabel.Size = New-Object System.Drawing.Size(280,20)
$Hostslabel.Text = 'Enter New HOSTNAME/FQDN:'
$form.Controls.Add($Hostslabel)

$HoststextBox = New-Object System.Windows.Forms.TextBox
$HoststextBox.Location = New-Object System.Drawing.Point(10,40)
$HoststextBox.Size = New-Object System.Drawing.Size(260,20)
$form.Controls.Add($HoststextBox)

$IPlabel = New-Object System.Windows.Forms.Label
$IPlabel.Location = New-Object System.Drawing.Point(10,60)
$IPlabel.Size = New-Object System.Drawing.Size(280,20)
$IPlabel.Text = 'Enter IP:'
$form.Controls.Add($IPlabel)

$IPtextBox = New-Object System.Windows.Forms.TextBox
$IPtextBox.Location = New-Object System.Drawing.Point(10,80)
$IPtextBox.Size = New-Object System.Drawing.Size(260,20)
$form.Controls.Add($IPtextBox)

$form.Topmost = $true

$form.Add_Shown({($HoststextBox,$IPtextbox).Select()})

$result = $form.ShowDialog()

if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
    $inputhosts = $HoststextBox.Text
    $inputip = $IPtextBox.Text
    $newrecord = "$inputip $inputhosts"
    Add-Content -Path $hostsfilelocation -Value $newrecord
}

@Kevin Remisoski의 답변은 좋았지만 추가, 제거 및 찾기(제거 또는 추가를 시도하기 전에 호스트가 세트에 있는지 확인할 수 있도록)할 수 있기를 원했습니다.

단순화된 hosts.ps1:

# Original file - https://gist.github.com/markembling/173887

$DefaultHostsFilePath = "C:\Windows\System32\drivers\etc\hosts"

Function Add-Host([string]$Ip, [string]$HostName, [string]$HostsFilePath = $DefaultHostsFilePath) {
    Remove-Host $HostsFilePath $HostsFilePath
    $Ip + "`t`t" + $HostName | Out-File -Encoding ASCII -Append $HostsFilePath
}

Function Remove-Host([string]$HostName, [string]$HostsFilePath = $DefaultHostsFilePath) {
    $Content = Get-Content $HostsFilePath
    $NewLines = @()
    
    foreach ($Line in $Content) {
        $Bits = [regex]::Split($Line, "\t+")
        if ($Bits.Count -eq 2) {
            if ($Bits[1] -ne $HostName) {
                $NewLines += $Line
            }
        } else {
            $NewLines += $Line
        }
    }
    
    # Write file
    Clear-Content $HostsFilePath
    foreach ($Line in $NewLines) {
        $Line | Out-File -Encoding ASCII -Append $HostsFilePath
    }
}

Function Get-Hosts([string]$HostsFilePath = $DefaultHostsFilePath) {
    $Content = Get-Content $HostsFilePath
    
    $Result = @()
    foreach ($Line in $Content) {
        $Bits = [regex]::Split($Line, "\t+")
        if ($Bits.Count -eq 2) {
            $Result += "$Bits[0] `t`t $Bits[1]"
        }
    }
    return $Result;
}

Function Find-Host([string]$Pattern, [string]$HostsFilePath = $DefaultHostsFilePath) { 
    $Hosts = Get-Hosts $HostsFilePath;
    $Filtered = ($Hosts | Select-String $Pattern)
    return $Filtered
}

사용 스크립트의 예:

. ".\hosts.ps1"

if ((Find-Host "MyNewEntry").Count -eq 0)
{
    Add-Host "127.0.0.1:5000" "MyNewEntry"
    Write-Host "Added Entry"
}
else
{
    Remove-Host "MyNewEntry"
    Write-Host "Removed Entry"
}

Write-Host "-- Begin Printing Hosts --"
Get-Hosts | Write-Host
Write-Host "-- End Printing Hosts --"

이게 제가 결국 사용하게 된 제품입니다.업데이트할 때마다 실행하도록 Active Directory 그룹 정책을 만들었습니다. 따라서 항목 중 하나가 누락되어 있으면 추가되고, 항목이 이미 존재하면 이중 항목을 얻을 수 없습니다.

function Test-FileLock {
  param (
    [parameter(Mandatory=$true)][string]$Path
  )

  $oFile = New-Object System.IO.FileInfo $Path

  if ((Test-Path -Path $Path) -eq $false) {
    return $false
  }

  try {
    $oStream = $oFile.Open([System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::None)

    if ($oStream) {
      $oStream.Close()
    }
    return $false
  } catch {
    # file is locked by a process.
    return $true
  }
}

$hostsFile  = "$($env:windir)\system32\Drivers\etc\hosts"
$hostsEntry = @('192.168.223.223 w2012', '192.168.223.224 w2019', '192.168.223.5 tbstorage', '192.168.223.7 tgcstorage','192.168.223.202 paneladmin.local.com')

foreach ($HostFileEntry in $hostsEntry)
{
    While(Test-FileLock($hostsFile)) {
        Write-Host "File locked! waiting 1 seconds."
        Start-Sleep -s 1
    }
    # split the entry into separate variables
    $ipAddress, $hostName = $HostFileEntry -split '\s+',2
    # prepare the regex
    $re = '(?m)^{0}[ ]+{1}' -f [Regex]::Escape($ipAddress), [Regex]::Escape($hostName)
    # Write-Host $re

    If ((Get-Content $hostsFile -Raw) -notmatch $re) {
        Add-Content -Path $hostsFile -Value $HostFileEntry
        Write-Host "Writing $HostFileEntry"
    }
}

호스트 파일을 쓰기 전에 항목이 있는지 없는지 확인했습니다.

$domainCheck = "installer.example.com"
$rHost = "C:\Windows\System32\drivers\etc\hosts"
$domainName = "`n8.8.8.8`tinstaller.example.com"
if((Get-Content $rHost | Select-String $domainCheck ).length -eq 0){
    Add-Content -Path $rHost -Value $domainName -Force
}

최고의 해결책!

if(!((Select-String -Path $env:windir\System32\drivers\etc\hosts -Pattern "localhost") -ne $null)){
    Add-Content -Path $env:windir\System32\drivers\etc\hosts -Value "`n127.0.0.1`tlocalhost" -Force
}

친구들이여!저는 이 작업을 끝내기 위해 작은 대본을 썼습니다.

#Requires -RunAsAdministrator
$WindowsHostFilePath = "$( $env:windir )\System32\drivers\etc\hosts"

$RecordHash = @{
    'server1'               = '192.168.0.1'
    'server1.company.local' = '192.168.0.1'
    'server2'               = '192.168.0.254'
    'server2.company.local' = '192.168.0.254'
}

foreach ( $record in $RecordHash.Keys ){
    write-host "Adding [$record] to host file [$WindowsHostFilePath]." 
    Add-Content -Path $WindowsHostFilePath -Value "`n$( $RecordHash.$record )`t$record" -Force
}

관리자 권한으로 이 스크립트를 실행합니다.

언급URL : https://stackoverflow.com/questions/2602460/powershell-to-manipulate-host-file

반응형