LoginSignup
7
4

More than 3 years have passed since last update.

Win10のhostsをBATで書き換え

Posted at

目的

WordPressで構築したサイトをドメインはそのままでサーバー移行する際、そのサイトの管理者に移行先の動作を確認してもらう必要があった。

管理者のスキルだとhostsの直接編集が難しそうだったためhostsの切り替えを簡単に行うことを目指す。

検討

まずは検索
windows hosts 編集 バッチ - Google 検索

Windows 10でhostsファイルを編集する方法と、一発で編集できる便利コマンド | TeraDas

powershell -NoProfile -ExecutionPolicy unrestricted -Command "start notepad C:\Windows\System32\drivers\etc\hosts -verb runas"

Windowsのhostsファイルの変更がめんどくさい人のためのbat - Qiita
djeeno.log: Windowsでhostsをすごく簡単に編集するためのバッチファイル(.bat)

同じ内容が紹介されていた。

@echo off
start powershell.exe -Command "Start-Process -Verb RUNAS notepad C:\Windows\System32\drivers\etc\hosts"

maruton's memorandum: [Windows]hostsファイルを変更するバッチファイル

set hosts=c:\windows\system32\drivers\etc\hosts
set hoststmp=c:\windows\system32\drivers\etc\hosts.tmp
copy %hosts% %hoststmp%
notepad %hoststmp%
copy %hoststmp% %hosts%
pause

Powershell to manipulate host file - Stack Overflow
上記ページで下のスクリプトが紹介されていた
Powershell script for adding/removing/viewing entries to the hosts file.

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

結果

hosts.ps1 が扱いやすそうだったのでこれをBATから起動する方針に決定。

下のBATを、「移行先に切り替え」、「移行元に切り替え」、「設定削除(移行期間完了時に使用)」の三種類に適宜書き換え、hosts.ps1と同じフォルダに置く。BATを「管理者として実行」してhostsを編集する。

@echo off
REM 設定の追加 ファイル実行の引数に「 add 」、「 ipアドレス 」、「 ホスト名 」を追加
@powershell %~dp0hosts.ps1 add 127.0.0.1 example.com -Verb runas
REM 設定の削除 ファイル実行の引数に「 remove 」と「 ホスト名 」を追加
@powershell %~dp0hosts.ps1 remove example.com -Verb runas
REM スクリプト実施後の設定値一覧を表示
echo result: 
@powershell -ExecutionPolicy RemoteSigned -File %~dp0hosts.ps1 show
REM 念のため DNS リゾルバー キャッシュ削除
ipconfig /flushdns
pause

その他参考

備考

hosts.ps1 の print-hosts の関数名が原因で UseApprovedVerbs PSScriptAnalyzer/UseApprovedVerbs.md at master · PowerShell/PSScriptAnalyzer · GitHub の警告がテキストエディタ上に出たので、
PowerShell コマンドの承認された動詞 - PowerShell | Microsoft Docs
で許されている動詞に変更して使っている。

hosts.ps1
- 37 function print-hosts([string]$filename) {
+ 37 function show-hosts([string]$filename) {

- 66        print-hosts $file
+ 66        show-hosts $file
試行錯誤メモ.bat
REM 管理者権限パスのための引数検討
@powershell -ExecutionPolicy RemoteSigned -File %~dp0hosts.ps1 remove centralltd.co.jp -Verb runas

REM 最初の検討→引数のつけ方がよくわからなかった
@powershell -Command "Start-Process powershell.exe -ArgumentList c:\temp\hosts.ps1 -Verb runas"

REM 子プロセスのスクリプト空の返り値検討
@powershell -Command "Start-Process powershell.exe -ArgumentList %~dp0test.ps1 -Verb runas;exit $LASTEXITCODE"
echo Powershell returned value: %ERRORLEVEL%
7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4