2>&1

インフラ寄りのメモ。

Windows で 元気モリモリご飯パワー元年 を実装してみた

Windows が苦手な いか です。
Win10 でレジストリを変えて 元気モリモリご飯パワー元年を実装してみた。

f:id:ika_as_engineer:20190106184539p:plain

...設定を変えるだけのことである。4年間放置したブログを更新した理由が、元気モリモリご飯パワーにかける情熱であった。

元号レジストリ設定

現状はリッチな公式情報が日本語で公開されている。
https://support.microsoft.com/ja-jp/help/4469068/summary-of-new-japanese-era-updates-kb4469068

Windows / .NET の範囲では Windows Update で新元号が適用される予定だが、現時点(1/6)で具体的な日程のアナウンスを見つけられない。


ちなみに、2017の秋頃から下記情報を確認していたものの、当時の公式情報は英語しかあらず。
Era Handling for the Japanese Calendar - Windows applications | Microsoft Docs

> If necessary, additional eras can be added to that key through the normal Windows Update process.

という文章の通り、Windows Update で提供されることは既定路線であった。

Windows / .NET Framework の年号はレジストリをざっくり参照しそうな挙動

Get-DateとカレンダーGUIではレジストリを参照することを確認した。
文字数制限は大きそうで、史上の最大文字数は、奈良時代の「天平感宝」(てんぴょうかんぽう) のようなので、これは余裕そうである。
とは言え、漢字3文字やデフォルトひらがな、デフォルトカタカナ、何故かデフォルト英字などが来たら困るシステム屋が居そうなので、忖度してくださるとええですね(チラッ

実際に変えてみる

  • コントロールパネル > 地域 > 追加の設定 > 日付タブ > カレンダーの種類を和暦に。

f:id:ika_as_engineer:20190106184604p:plain

  • regedit.exe から HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras に文字列値を追加。

f:id:ika_as_engineer:20190106184448p:plain
# レジストリ修正はシステムに重大な影響を及ぼす可能性があるため、修正の際には個人責任で細心の注意を払った上でのご実施を。

  • 時刻設定を変更。

f:id:ika_as_engineer:20190106184506p:plain
# Kerberos認証等ができなくなる可能性があるため、変更の際には個人責任で細心の注意を払った上でのご実施を。

諸注意点

Windows10のカレンダGUIやコンパネGUIPowerShell .NET Framework の Get-Date、System.DateTime 型では元号は保持するが、Windows のあらゆる参照値が件のレジストリである保証はなさそうです。公式文書を見つけられないため。
そのため、テストをするのが何よりも確実。

㍻ といったやつですね。これらは上記で論じていたものと別物にして、筆者は門外漢。
文字コード警察の諸兄が答えてくださるでしょう(チラッ
目ぼしい情報が見つかったら追記予定。

まとめ

  • 元気モリモリご飯パワー元年は俺達で作り出せる。
  • Windows / .NET の範囲では Windows Update で新元号が適用される予定だが、現時点(1/6)で具体的な日程のアナウンスを見つけられない。
  • Windows / .NET の範囲では [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras] から元号設定をざっくり参照しそう。
  • 元号の上限文字数は、Windows としては現実的に問題にならなそう。
  • テストして確認するのが何よりも確実。レジストリ修正、時刻変更は個人責任で細心の注意を。
  • 文字コードにおける対応は、文字コード警察の諸兄が答えてくださるでしょう。


以上、ばいちゃ。

PowerShell DSCのConifgurationを引いて監視を効率化する

第3回PoewrShell勉強会でLTやってきたのでスライドとコードを掲載。

始めてのLTだったので優しくしてください><


技術評論社のChef本に、Nodeオブジェクト上に監視用のattributeを起こして、監視を自動化する実装が書いてあって、それにインスパイアを受けました。PowerShell DSCでも似たようなことができないかと思い、挑戦してみました。

コンフィグ実行時に-ConfigurationDataで渡すオブジェクトを利用すれば、同じようなことができます。

[Configuration] -ConfigurationData $ConfigurationData

こんな書き方をしますが、この$ConfigurationDataオブジェクトがChefでいうNodeオブジェクトにあたるので、よしなに必要な情報をリストに入れてあげて(オブジェクト名や中の要素等、すべてが自由書式)、このオブジェクトを流用する形になりますね。

監視用のモジュールというか関数というか別スクリプトを起こす気がなかったのと、二番煎じになるので今回は別のやり方にしました。(近いうちに書いてみます)


PowerShell DSCとChefで大きく違う点は、Nodeオブジェクトもレシピも一緒くたに書けてしまう点です。そのため、複数名で運用する想定なら、ある程度書き方の規約を決める必要があると思います。…とりあえずChefのファイル郡構成を模す形にするのがいいかもですね。


話がそれました。今回は$ConfigurationDataを作り込んで監視情報を引くというより、その情報自体がDSCサーバーに記録されて引けるので、そちらを利用するものを書きました。

[ノード名].mofファイルのbasenameや、Service Resourceの記述が引ければ、それだけでも手堅い監視ができちゃいますよね。

ということで下記が監視スクリプトです。

$ConfPath = ".mofファイル格納ディレクトリのパス"

(Get-ChildItem $ConfPath).Fullname | ForEach-Object {
	$NodeName = (Split-Path $_ -Leaf).Replace(".mof","")
	$Session = New-CimSession -ComputerName $NodeName
	$DscConfig = Get-DscConfiguration -CimSession $Session

	if (!$?){
		if(!(Test-Connection $NodeName)) {
			. Error-Action; echo "$NodeName is Node Down!"
		}
		continue
	}

	$DscConfig | Where-Object {$_.CimClass.CimClassName -eq "MSFT_ServiceResource" } | ForEach-Object {
		$ServiceName = $_.Name
		if ($_.State -eq "Stopped") {
			. Error-Action; echo "$NodeName : $ServiceName is Stopping!"
		}
	}
}

function Error-Action {
	echo "Danger!!"
}

Cimの認証(-credentialオプション)は省略してます。よしなに実装です。

エラー時のアクションは例示です。メール送信とか書く気力がなかったんです。こんな書き方をした奴の頭がそもそもデンジャー。


DSCサーバーから実行することを想定しています。DSCサーバーの外から実行する場合は.mofファイルを嘗める実装になります。

PULLする構成の場合、.mofはPULLノードから引ける必要があるので、監視サーバーもPULLノードにして、SMBなりで見に行けばスマートですかね。

.mofファイルを嘗める実装、スライドに書いていませんでしたが、実は書いてありました。(むしろ最初は.mofファイルを嘗めて「ハイ、完成」でしたが、Get-DscConfigurationが現状のステータスを拾ってくれるのに気付いて書き直した次第。)

で、下記の通りです。

# Param
$ConfPath = ".mofファイル格納ディレクトリのパス"
[bool]$Flag = $False
$AllNodes = @()

# Get .mof file information
(Get-ChildItem $ConfPath).Fullname | ForEach-Object {
	$NodeName = (Split-Path $_ -Leaf).Replace(".mof","")
	$Services = @()

	get-content $_ | ForEach-Object {
		if ($_ -like '*`[Service`]*') {
			$Flag = $True
		}
		if ($_ -like ' Name =*' -and $Flag ) {
			$Flag = $False
			$Services += $_.split('`"')[1]
		}
	}
	
	$Node = @(@{"NodeName"=$NodeName;"Services"=$Services})
	$AllNodes += $Node
}

# Monitoring
$AllNodes | ForEach-Object {
		$NodeName = $_.NodeName
		if(Test-Connection $NodeName) {
			$_.Services | ForEach-Object {
				if ((Get-Service -ComputerName $NodeName -Name $_).Status -ne "Running") {
					. Error-Action; echo "$NodeName : $_ is Stopping!"
				}
			}
		} else { . Error-Action; echo "$NodeName is Node Down!" }
}

# Alert or Start-DSCConfiguration.
function Error-Action {
	echo "Danger!!"
}

あとは例示で出したコンフィグを記念に。SNMPとBitLockerの機能を入れて、関連サービスを「自動起動」にして、開始するだけのものです。実際にこんなConfiguration書く人はおらんでしょう。どないサーバーやねん、て。

$ConfigurationData = @{
  AllNodes = @(
    @{NodeName = "192.168.100.150"},
    @{NodeName = "192.168.100.151"}
  )
}

Configuration EXConfig2 {
	Node  $AllNodes.NodeName {
		WindowsFeature SNMP {
			Ensure = "Present"
			Name = "SNMP-Service"
		}
		WindowsFeature BL {
			Ensure = "Present"
			Name = "BitLocker"
		}
		Service SNMP {
			Name = "SNMP"
			StartupType = "Automatic"
			State = "Running"
		} 
		Service SNMPTRAP {
			Name = "SNMPTRAP"
			StartupType = "Automatic"
			State = "Running"
		} 
		Service BDESVC {
			Name = "BDESVC"
			StartupType = "Automatic"
			State = "Running"
		} 
	}
}

EXConfig2 -ConfigurationData $ConfigurationData


近日中にSyntaxHighLight処理しときます。