HYPERCONCERTO株式会社のチーフエンジニア雑記Blog

hyperconcerto株式会社のチーフエンジニアが日々気づいたことを書いています

6回目、vSphereをPowerShellで操作するときのTips

Powershellのお悩み1
LinuxのRSHみたいにリモートからスクリプトの実行はできないのでしょうか?

回答
できます。
実行するためにはいくつか事前準備が必要となります。
※Windows Server 2012R2で検証

サーバー側(スクリプトを送り込まれて実行するマシン)
Enable-PSRemoting を実行してYesで抜ける
Set-ExecutionPolicy Remotesigned にする

クライアント側(スクリプトを送り込むマシン)
Enable-PSRemoting を実行してYesで抜ける
Set-ExecutionPolicy Remotesigned にする

あとWindows girewallの許可が必要ですが、Enable-PSRemotingで勝手に穴が開くはずです。
ネットワーク機器側の設定は必要です。

Invoke-Command -ComputerName SERVER1 -Credential SERVER1\user10 -FilePath C:\Temp\Script.ps1 -ArgumentList "Arg1"

クライアント側のC:\Temp\Script.ps1がSERVER1で実行されます。
Invoke-Commandはサーバーの中にあるファイルも実行できます。
また、Administrators権限のあるユーザーを指定した場合は管理者として実行と同じ状態になるようなので
IPアドレス変更やホスト名変更など、ちょっと厄介なスクリプトも動きます。

Powershellのお悩み2
Grep的なコマンドは無いのでしょうか?

回答
どうやるんだっけ?と頭をひねってしまうけど、初歩的コマンドです。
Select-Stringというコマンドでできます。
例えばnetstat -anの結果のうちLISTENINGになってる部分だけ欲しい時は下記のように書きます。
netstat -an | Select-String LISTENING

正規表現も使えます
netstat -an | Select-String -pattern ".ISTENING"

aliasを使えばgrepとして呼び出せます。
Set-Alias grep Select-String
netstat -an | grep LISTENING

5回目、vSphereをPowerShellで操作するときのTips

昨年末からPowershellとPowerCLI関係の作業が続いているので、しばらくこの調子でいきたいと思います。

PowershellとBATのお悩み1
タスクスケジューラで実行しているスクリプトからファイルサーバーへ接続できないんですが…

回答
タスクスケジューラやスクリプトの単体実行の場合、特に意識しない限り実行ユーザーは
ローカルコンピュータに作成されたユーザーアカウントで実行されます。
タスクスケジューラの場合はローカルAdministratorが多いのではないでしょうか。
で、そんな状態でファイルサーバーへ接続しようとしても、ADと連携しているファイルサーバーに
ローカルユーザーアカウントが通用するわけもなく接続に失敗します。
このような場合はnet useコマンドで明示的にADユーザーを指定してネットワークドライブを作成します

例:Vドライブとしてマウントする
net use V: \\192.168.0.1\Temp P@ssw0rd1! /user:test-domain\user1

使い終わったらスクリプトの終端部分でネットワークドライブを消します
net use V: /delete

わりと知らない人が多くて現場ではまっているのをよく見かけます。


Powershellのお悩み2
Powershellレジストリ操作はできるのでしょうか

回答
レジストリの書き込み例
UACを無効にする場合
$path1 = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
Set-ItemProperty $path1 -name "ConsentPromptBehaviorAdmin" -value "0"
Set-ItemProperty $path1 -name "PromptOnSecureDesktop" -value "0"

レジストリの内容を取得する場合
$path1 = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
Get-ItemProperty $path1


Powershellのお悩み3
Windows Serverの初期設定スクリプトのサンプルをください

回答
運用自動化の関係でこういう問い合わせが増えています。
下記内容の設定を一発で行うスクリプト例を示します

1.ユーザーを追加
2.Remote Desktopを有効化
3.UAC無効化
4.Windows Firewall無効化

※管理者として実行としないと動かないです

#testuserを管理者権限を付けてパスワード期限を無期限
net user testuser /add
net user testuser P@ssw0rd1!
net localgroup administrators testuser /add
wmic useraccount where "Name='testuser'" set PasswordExpires=FALSE

#Remote Desktop有効化
$path1 = "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server"
$path2 = "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp"
Set-ItemProperty $path1 -name "fDenyTSConnections" -value "0"
Set-ItemProperty $path2 -name "UserAuthentication" -value "0"

#UAC無効化
$path1 = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
Set-ItemProperty $path1 -name "ConsentPromptBehaviorAdmin" -value "0"
Set-ItemProperty $path1 -name "PromptOnSecureDesktop" -value "0"

#Firewall無効化
netsh advfirewall set allprofiles state off

4回目、vSphereをPowerShellで操作するときのTips

PowerCLIの実行速度が遅いんですが…

回答
PowerCLI 6.5 R1なら早いですよ。
実は6.5からは最初から最適化済みのモジュールがインストールされるので実行速度が上がっています。
というわけで調べてみました。

下記コマンドを実行
Measure-Command { get-vm }

6.0の32bit版で最適化無
約3.5秒

6.5の32bit版でインストール直後
約0.8秒

6.0までは32bit版が速かったのですが、6.5からは64bit版の方が速いみたい。

参考
6.5の64bit版でインストール直後
約0.45秒

いままでの6.0は最適化されていないのか?という疑問がありますが、最適化されていません。
詳細は下記記事を参照
https://blogs.vmware.com/PowerCLI/2011/06/how-to-speed-up-the-execution-of-the-first-powercli-cmdlet.html

6.0の最適化自体は下記コマンドで実行できます。
C:\Windows\Microsoft.NET\Framework\v4.0.30319\ngen.exe install “VimService60.XmlSerializers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=10980b081e887e9f”
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\ngen.exe install “VimService60.XmlSerializers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=10980b081e887e9f”

動きとしてはngen.exeでネイティブイメージを生成してグローバルアセンブリに登録するという動きをします。

次はスクリプトの書き方による実行速度の違いを解説します。

●書き方による速度の違い

同じ出力を得ることができますが、いくつかの書き方ができます。

例1
Measure-Command { $ret = get-vm;$ret | where { $_.Name -eq "testvm-01" }}
約2秒

例2
Measure-Command { get-vm | where { $_.Name -eq "testvm-01" }}
約1.9秒

例3
Measure-Command { get-vm -name testvm-01 }
約0.5秒

例1はfor文で拾う時用ですね。
当然ですが、Get-VMの-Name引き数で指定したほうが速いです。


ループの場合

下記のような書き方にすると遅くなることが多いです。

あかん例
foreach ($tempList in $VMList){
Get-VM -Name $tempList
}

改善した例
$ret = Get-VM
foreach ($tempList in $VMList){
$ret | where { $_.Name -eq $tempList }
}

$VMListに入っている数が数個ならいいのですが10個を超えるとかなり遅くなります。

基本的にPowerShellは実行速度が結構遅いので、書き方に注意が必要です。
Where-Object句自体がちょっと遅い気がします。

その他の遅いと苦情を言われるパターン
PowerCLIのモジュールを使うps1ファイルの場合ですが、PowerCLI自体のモジュールのロードが遅いです。
数分かかることもありますので、頻繁に実行するのならプロセスを上げたままで処理するなどの工夫が必要です。

3回目、vSphereをPowerShellで操作するときのTips

特定のOSを使用しているGeustOSの一覧を作りたい!

回答
EOL対応とかセキュリティ対応でいますぐ出してよ!ってよく言われるあれです。
構成管理をさぼってると非常に大変な作業でして、いちいちログインして確認するのは非現実的なので
、vCenterからGUIから確認することが多いと思います。
しかし、台数が多いと大変なので自動化してみます。
前回のGet-VMGuestコマンドで取得できますが、このコマンドはVM名を引数として渡さないと動きません。
一気に表示する場合は下記のようなコマンドになります。
※表示に時間がかかるので実行時には注意してください。

Get-VM | Get-VMGuest

さらにGet-VMGuestの中身からWhere-ObjectコマンドでWindows Server 2012に該当するものだけを抽出すると下記のようになります。

Get-VM | Get-VMGuest | Where-Object {$_.OSFullName -like "*Microsoft Windows Server 2012*"}

このコマンドだと下記の表示になってわかりにくいです。


State IPAddress OSFullName

          • --------- ----------

Running {10.0.0.1} Microsoft Windows Server 2012 (64 ビット)
Running {10.0.0.2} Microsoft Windows Server 2012 (64 ビット)
Running {10.0.0.3} Microsoft Windows Server 2012 (64 ビット)

改良したコマンド
Get-VM | Get-VMGuest | Where-Object {$_.OSFullName -like "*Microsoft Windows Server 2012*"} | SELECT VmName,HostName,IPAddress,OSFullName

VmName HostName IPAddress OSFullName

            • -------- --------- ----------

TestVM1 WINAD1 {10.0.0.1} Microsoft Window...
TestVM2 WINSRV2 {10.0.0.2} Microsoft Window...

見切れてますのできちんとした形で見る場合はCSV形式で書き出しましょう

CSV書き出しと電源状態の表示を追加したコマンド
Get-VM | Get-VMGuest | Where-Object {$_.OSFullName -like "*Microsoft Windows Server 2012*"} | SELECT VmName,HostName,IPAddress,OSFullName,State | Export-Csv C:\Temp\test.txt -Encoding Default


作成から1ヵ月以上経過しているスナップショットを持っているか調べる方法はないのでしょうか?

回答
VMware社の推奨では48時間を超えてスナップショットを保持しないでくださいというガイドラインがあります。
指定した期間を経過していたら表示するコマンドがあったら便利ですが、用意されて内容です。
しかし、PowerCLIでちょっと作りこまないと多分無理です。
ちょっと頑張って任意の日数で抽出するスクリプトを作ってみました。

※モジュールの読み込みコマンドを入れてないのでPowerCLIの窓から呼び出してください。

ShowSnapshotInfo.ps1

$VIServer = "192.168.0.1"
$UserName = "administrator@vsphere.local"
$Password = "P@ssw0rd1!"
$LimitDay = 7

$vCenter_ret = Connect-VIServer -Server $VIServer -User $UserName -Password $Password

$i = 0

$ret_get_vm = Get-VM
$LimitDay = $LimitDay * -1
$tempLimitDay = (Get-Date).AddDays($LimitDay)

foreach($temp_Results1 in $ret_get_vm){
$ret_SnapShot = Get-Snapshot -vm $temp_Results1.Name

foreach($temp_Results2 in $ret_SnapShot){
$tempSnapShotDay = $temp_Results2.Created
if ($tempSnapShotDay.Date -lt $tempLimitDay.Date){
#CSV形式へ変換
$OutString = $temp_Results1.Name + "," + $temp_Results2.Name + "," + $temp_Results2.Created
#結果出力
$OutString
}
}
}

Disconnect-VIServer -Server $VIServer -Confirm:$false


使い方
vCenterのIPアドレスや認証情報を環境に合わせて修正してください。
変数$LimitDayに対して検知したいスナップショットの古さを指定してください。
1か月の場合は下記のようになります。
$LimitDay = 30

出力はVM名、スナップショット名、スナップショット日付
となります。

スクリプトは全数に対してGet-VMを投げているのでVMの数が多い環境では非常に時間がかかります。

スクリプトに対する安全性やバグについては保証しません。

2回目、vSphereをPowerShellで操作するときのTips

スクリプトをファイルにまとめて実行すると、Dissconnect-VIServerでログオフの確認メッセージが出て自動化できない!

回答

  • Confirm:$failseを付けると確認メッセージが出ません。

具体的には下記のように書くといいです。
※-Serverオプションはつけなくても動きますが、うまくいかない環境もあるようなので付けました。
※-Serverオプションに指定するアドレスはvCenterのアドレスです

Disconnect-VIServer -Server 192.168.0.1 -Confirm:$false


Get-VMコマンドで取得できる項目を知りたい。Get-VMコマンドで表示される項目が少なすぎる

回答
Get-VM | Get-Member
で戻り値が持っているプロパティなどが見れます。
モリーの割当量を見たい場合はMemoryGBを参照します。

ちなみにGet-VMGuestコマンドの方がGuest OSの細かな情報が取れます。
例えばOSの情報とかIPアドレスなど

例:
Get-VMGuest -VM PC1

詳しくはPowerCLIのリファレンスを参照してください

PowerCLIのTipsその1

だいぶ時間が空いてしまいましたが、2017年1回目の更新を行いたいと思います。

仮想化関係が得意ですと発表してしまっているので、仮想化関係の記事を書こうとここ最近悩んでいました。
しかし、なかなかネタが思いつきません。

最近vSphereのスクリプト開発が多かったので、PowerShellやPowerCLI関係の事を書きたいと思います。

1回目、vSphereをPowerShellで操作するときのTips

PowerCLIのウインドウからならGet-VMとかのコマンドが通るけど、PowerShellのウインドウから実行できないのはどうして?
PowerCLIってPowerShellベースじゃないの?
スクリプトファイルでの実行できないよ!

回答
PowerCLIはPowerShellに対してVMwareが提供するモジュールを組み込んだものです。
ですので、手動でモジュールを組み込めばコマンドが通ります。

基本コマンドを使えるようにするには下記モジュールを読み込みます
Import-Module VMware.VimAutomation.Core

読み込めたらConnect-VIServerが通るはずです。

他のモジュールはこの中に入っているので、使いたいプロダクトに合わせて読み込んでください。
C:\Program Files (x86)\VMware\Infrastructure\PowerCLI\Modules

全てのモジュールを読み込む場合は初期化スクリプトを呼び出してください
& 'C:\Program Files (x86)\VMware\Infrastructure\PowerCLI\Scripts\Initialize-PowerCLIEnvironment.ps1'


PowerCLI6.5RC1がリリースされているので補足
PowerCLI6.5RC1の段階ではHorizonViewに関するコマンドは提供されていませんが、ViewAPIがサポートされるようになったので一応は操作可能です。
ViewAPIを使った操作は結構大変なので、VMware.Hv.HelperというGitHubで公開されているモジュールを使ったほうが良いでしょう。
ただしデスクトッププールなどの一般的な操作のみサポートされています。
(細かな操作はViewAPIを使う必要があります)

ヘッドホンアンプの箱を特注しました

前回はヘッドホンアンプの基板を基板工場で作ってもらい、部品実装をするところまで進みました。
今回は基板を入れる箱の特注をお届けしようと思います。

箱はタカチ電機様に加工までお願いしました

最初からクライマックスですけれど、完成した箱の写真です。
f:id:hyperconcerto:20161107172530p:plain

諸事情によりフロントパネルはあえて撮影していません。(すみません…)

加工依頼の流れ

ここが一番気になるところでしょう。
基板作成はできても筐体加工は無理っていうのは結構あると思います。
穴あけだけでも10mm超えるとボール盤じゃないと辛い部分もありますし、金属カスやバリ取りの手間を考えたら専門家にお任せしたほうがいいかなと思います。
そもそもドリルの刃って結構しますし…

1.タカチ電機様のWebサイトから箱を選定します
2.同Webサイトに箱のCADデータがあるはずなのでダウンロードします(私が使った箱はCADデータありませんでした)
3.もしCADデータが無いのなら問い合わせをします
4.加工指示をCADデータに書き込みます※1
5.DWG形式かDXF形式で保存します
6.タカチ電機様や代理店に加工依頼を行います※2
7.支払い方法を指定して、支払いを済ませます
8.届くのを待ちます

※1 DXF形式かDWG形式のようなので、対応しているCADを使ってください
※2 今回はマルツエレック様経由で対応して頂きました

加工指示の具体的内容ですが、どの位置にどのような穴を開けるかといった内容がメインになります。
また、ネジ穴付きのスタッドなども指定すれば加工してくれますので基板固定に悩む必要はありません。

気になるお値段ですが…
具体的なそのものずばりな金額は避けますが、今回の場合だと加工費は文字入れと穴あけで箱の1.3倍ぐらいでした。
箱2個ちょっとで済むので結構リーズナブルではないかと思います。