HTTP経由でのNTP時刻合わせ(PowerShell利用)

  • 5
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

Firewall に囲まれてて NTP が通らないので書いた。

HTTP(S)で日本標準時を文字列で返してくれるサービスが提供されているのでそちらを利用、対象 OS が Linux 系なら wget を使えばいいけど Windows にはそんなものは(標準では)無いので PowerShell から .NET を呼び出してどうにかする。

コード

ntpdate.ps1
# 管理者権限で実行すること
$ntpdatestring = (new-object System.Net.WebClient).DownloadString("http://ntp-a1.nict.go.jp/cgi-bin/time").Replace(" JST", " +0900").Trim()
$datetime = [DateTime]::ParseExact($ntpdatestring, "ddd MMM dd HH:mm:ss yyyy zzzz", [Globalization.CultureInfo]::CreateSpecificCulture("en-US"))

set-date $datetime

あとはタスクスケジューラにぶち込んだりすれば良いのでは。定時ダッシュの精度が高まりますね

実装時にはまった点

PowerShell 初めて書いた& そもそも .NET あんまり知らんのでそもそも全部ハマっ
WebClient#DownloadString() が 返す文字列の後ろに謎の改行文字が入ってることに気付かなくてパース出来なかった
DateTime#ParseExact() の時にロケール…じゃなくてカルチャに en-US を指定をしないといけない(自環境だとデフォルトのカルチャが ja-JP になるので ddd は "日曜" だの "月曜" だのが有効な値、"Sun" やら "Mon" は認識出来ない)ことに気付くのに大分時間が掛かった

NTPリソース

日本標準時プロジェクト 公開NTP サービス対応クライアントリスト
日本標準時プロジェクト https/http を介してアクセスされる場合

/cgi-bin/time は RFC1123 形式っぽいけど少し違う
/cgi-bin/ntp と /cgi-bin/jst は text/plain じゃないのでアレ

環境

OS: Windows 7 Pro

Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.

PS C:\> $PSVersionTable

Name Value


CLRVersion 2.0.50727.5485
BuildVersion 6.1.7601.17514
PSVersion 2.0
WSManStackVersion 2.0
PSCompatibleVersions {1.0, 2.0}
SerializationVersion 1.1.0.1
PSRemotingProtocolVersion 2.1


書いてから気付いたけど PowerShell で JSON 読めるならそれ使ったほうが楽だったのでは…?
JSON 使えるやん…
→ PowerShell 3.0 からだった。Windows 7 デフォルトは V2 なのである意味セーフ

st に UNIX 時間が入ってるから new DateTime(1970, 1, 1, 9, 0, 0) に AddSeconds() で良いのかなー