しばたテックブログ

気分で書いている技術ブログです。

Windows 10 Creators UpdateでSQL*Plusを使うと日本語が文字化けする件について

【2017/06/05追記】

本現象は先日出た累積更新(KB4020102)で解消されています。

【追記ここまで】


きっかけは @masaru_b_cl さんのこのツイートから。

手元の環境でこの現象が再現して回避策を見つけることができたのでここにメモっておきます。

環境について

今回、以下の環境で文字化けが起きることを確認しました。

  • クライアント

    • 64Bit版 Windows 10 Pro / Creators Update(1703)
      • 今月の更新まで適用済み
    • Oracle Instant Client for Microsoft Windows (x64) 12.2.0.1.0
      • Instant Client Package - Basic
      • Instant Client Package - SQL*Plus
        をインストールしてSQL*Plusを実行可能に設定
    • NLS_LANG = Japanese_Japan.JA16SJISTILDE
  • サーバー

    • Windows Server 2012 R2
    • Oracle Database Enterprise Edition 12.1.0.2.0
    • データベースのキャラクタセット = JA16SJISTILDE

テスト用にTEST_TABLEテーブルを用意し、投入したデータは以下の様な感じです。

f:id:stknohg:20170526215041p:plain

現象の確認

とりあえずデータベースに接続して以下のクエリを流してみます。

SELECT VALUE FROM TEST_TABLE ORDER BY KEY;

結果はこんな感じで思いっきり日本語が化けます。
よく見るとログイン時のメッセージも化けています。  

f:id:stknohg:20170526215209p:plain

ちなみにPowerShellからSQL*Plusを実行しても同じ感じになります。

f:id:stknohg:20170526215305p:plain

原因と回避策

原因はCreators Updateで仕込まれたバグの様です。

@takekazuomi さん曰く最新のInsider Previewではこの現象は改善されているそうなので、しばらく我慢すればパッチも出るんじゃないかと思います。

とりあえず現状としては以下の回避策で対処することが可能です。

追記. 従来のコンソールを使う

本エントリを公開した瞬間に@takekazuomi さんよりコメント頂きました。

f:id:stknohg:20170526222749p:plain

コマンドプロンプトのプロパティで従来のコンソールを使うにチェックを入れてコマンドプロンプトを再起動することで本現象を回避することができました。
この方法が一番手っ取り早く確実ですね。

私の調査は一体何だったのかという気持ちでいっぱいですが気にしないことにします....

1. 先頭にダミーカラムを追加する

この現象はコンソールに表示される最初の文字が日本語でなければ良いっぽく、

SELECT '', VALUE FROM TEST_TABLE ORDER BY KEY;

な感じで先頭にダミーカラムを付けて最初にスペースが表示される様にするだけでも問題は解決します。

f:id:stknohg:20170526215543p:plain

とりあえずこれで問題は回避できますが、非常にトホホな気分になります...

2. クライアントの文字セットをUTF8にする

真っ当な回避策としてはクライアント側の文字セットをユニコードにしてしまう方法があります。
今回はUTF8に変更することで対処してみます。

NLS_LANGの文字セットをAL32UTF8に変えればクライアント側の文字コードをUTF8にできます。
これだけだとコマンドプロンプトで文字を表示できないのでCHCPコマンドでコードページも変える必要があります。

実行するコマンドは以下の様な感じになります。

CHCP 65001
SET NLS_LANG=Japanese_Japan.AL32UTF8

この状態であれば下図の様に文字化けを回避することができます。

f:id:stknohg:20170526215645p:plain

ちなみにPowerShellであれば、CHCPコマンドの代わりに[Console]::OutputEncodingの設定を変えることでも対応可能です。

[Console]::OutputEncoding=[Text.Encoding]::UTF8
$env:NLS_LANG='Japanese_Japan.AL32UTF8'

f:id:stknohg:20170526215701p:plain

最後に

残念の一言につきるので早く修正パッチが提供されることを望みます。

PowerShell 6.0のBeta版がリリースされました

公式の案内はこちら。

blogs.msdn.microsoft.com

GitHubのマイルストーンにあった通りBuild 2017に合わせる形のリリースとなりました。

インストールおよびアップデート

GitHubから最新のインストーラーをダウンロードして上書きインストールするか、Linux環境であればyumapt-getを使って最新バージョンにしてください。

stknohg.hatenablog.jp

主な変更点

詳細については先のブログかGitHubのチェンジログを参照してください。

本エントリでは主要な部分だけ解説します。

インストール可能なLinuxディストリビューションが増えました

オープンソース化したAlpha 9時点でインストール可能なディストリビューションは

  • Ubuntu 14.04, 16.04
  • CentOS 7

でしたが、現在は、

  • Ubuntu 14.04, 16.04
  • CentOS 7
  • Debian 8
  • RHEL 7
  • OpenSUSE 42.1
  • Arch Linux

にインストール可能となっています。
またAppImageのバイナリも提供されているので、AppImageが利用可能な環境であればディストリビューションを選ばずにPowerShellを実行することができます。

.NET Standard 2.0への移行

Alpha18までは.NET Core 1.0→1.1上で動作していましたが、Beta1になった時点で.NET Core App 2.0.0(Preview1)上で動作する様になりました。

こちらについては、私自身が.NET Standard 2.0のうま味をよくわかっていないため何とも言えないのですが、PowerShell Moduleのポータビリティが上がるだろうとの事です。

テレメトリの追加

Beta1になってPowerShell CoreにApplication Insightsを利用したテレメトリ(利用環境などの情報収集機能)が追加されました。

現時点では利用者のOS($PSVersionTable.OS相当)とPowerShellのバージョン($PSVersionTable.GitCommitId)を収集しているそうです。

今後ほかの情報も収集して開発に利用する予定となっています。
収集する情報を増やす際は突然増やすことはせずにRFCによる議論を経てから行うとの事です。

そして収集した情報はこちらのダッシュボードで参照することができる様になるそうです。

ちなみに、この情報収集をオプトアウトするには$PSHOMEにあるDELETE_ME_TO_DISABLE_CONSOLEHOST_TELEMETRYファイルを削除してください。

f:id:stknohg:20170510170313p:plain

例としてPowerShell on Linux上で実行するならこんな感じになります。

# PowerShell on Linux
sudo rm $PSHOME/DELETE_ME_TO_DISABLE_CONSOLEHOST_TELEMETRY

f:id:stknohg:20170510171757p:plain

その他変更点

これらの他にチェンジログから個人的に気になる変更点をリストアップしておきます。*1
すべての変更点ではありませんので注意してください。

  • Enable 'ConvertTo-Html' in PowerShell Core. (alpha11)
  • Select-Object with -ExcludeProperty now implies -Property * if -Property is not specified. (alpha12)
  • Enable Implicit remoting commands in PowerShell Core (alpha12)
  • Add parameters -Top and -Bottom to Sort-Object for Top/Bottom N sort (alpha13)
  • Add Get-Uptime to Microsoft.PowerShell.Utility (alpha13)
  • Make Out-Null as fast as > $null (alpha13)
  • New-TemporaryFile and New-Guid rewritten in C# (alpha14)
  • Add -Group parameter to Get-Verb (alpha15)
  • Use MB instead of KB for memory columns of Get-Process (alpha15)
  • Add alias Path to the -FilePath parameter of Out-File (alpha16)
  • Convert Get-FileHash from script to C# implementation (alpha16)
  • Port *-CmsMessage and Get-PfxCertificate cmdlets to Powershell Core. (#3224) (alpha17)
  • Add the -TimeOut parameter to Test-Connection. (#2492) (alpha17)
  • Remove the AliasProperty "Count" defined for System.Array (alpha17)
  • Add -CustomMethod parameter to web cmdlets to allow for non-standard method verbs. (#3142)
  • Allow Windows' reserved device names (e.g. CON, PRN, AUX, etc.) to be used on non-Windows platforms. (#3252) (alpha17)
  • Remove year from PowerShell copyright banner at start-up. (#3204) (alpha17)
  • Add -Extension and -LeafBase switches to Split-Path so that you can split paths between the filename extension and the rest of the filename. (#2721) (alpha18)
  • Implement Format-Hex in C# along with some behavioral changes to multiple parameters and the pipeline. (#3320) (alpha18)
  • Add the OS entry to $PSVersionTable. (#3654) (beta1)
  • Update PowerShell Core to accept the -i switch to indicate an interactive shell. (#3558) (beta1)
  • Change the default encoding and OEM encoding used in PowerShell Core to be compatible with Windows PowerShell. (#3467) (beta1)
  • Change the behavior of Remove-Item on a symbolic link to only removing the link itself. (#3637) (beta1)

今後のスケジュールについて

これまで一切明らかにされていなかった今後のスケジュールやマイルストーンについて以下の声明が出されました。

リリースサイクル

Beta版では約3週間のサイクルで新しいバージョンをリリースするとの事です。

明言はされてませんでしたがAlpha版でも同じくらいのサイクルで新バージョンがリリースされてましたので、今後も変わらずこれまで通りという事でしょう。

リリース候補に向けて

具体的な期限は切られませんでしたが、リリース候補を出すために以下の項目をクリアするとの事です。

  1. 6.0.0-betaのマイルストーンに紐づけられたIssueを解決する

  2. 最低80%のコードカバレッジを達成する
    (現時点では約40%達成)

  3. バージョン6.0.0に向けたすべてのシナリオを実現する

  4. テレメトリに基づいた利用目標を達成する
    (いまいちよくわかりませんが詳細はこれから決める様です...)

これらの項目をクリアしたら即リリースというわけではありませんがリリース時期を予測するのによい指標になると思います。

最後に

とりあえずこんな感じです。

GitHubの更新などをずっと追いかけてきた印象ですが、バージョン6に向けてPowerShellは着実に進化していると感じます。

これからの更新がとても楽しみですね。

*1:邦訳したかったけど量が意外と多かったので原文のままで...

Windows 10でロードアベレージを取得する?

小ネタです。

ふと、「Bash on Ubuntu on Windowsを使えばWindowsでもロードアベレージを取得できるよなぁ…」と思ったので実際に試してみました。

Windowsのロードアベレージ

www.atmarkit.co.jp

上の記事に詳細が説明されていますが、WindowsではUNIXやLinuxのロードアベレージと同等の値を取得することはできません。
類似の値としてパフォーマンスカウンターの\System\Processor Queue Lengthが紹介されており、通常はこれを使うしかありません。

PowerShellでこの値を取得するにはGet-Counterコマンドを使い以下の様にすれば良いです。

(Get-Counter -Counter "\System\Processor Queue Length").CounterSamples.CookedValue

このカウンターはデフォルトのスケールが1なのでCookedValueがそのまま使えます。

また、平均を取るには以下の様な感じすれば一応可能です。*1
(以下のサンプルを実行すると1分間待たされるので注意してください)

# UNIX/Linuxでのサンプリング間隔は5秒だそうなので、それに合わせて1分間の平均を求めます
(Get-Counter -Counter "\System\Processor Queue Length" -SampleInterval 5 -MaxSamples 12).CounterSamples.CookedValue `
    | Measure-Object -Average | Select-Object -ExpandProperty Average

Windows 10でロードアベレージを取得する

Windows 10でWSLを有効にすればWindows内でUbuntuが動作しますので、Ubuntu経由でロードアベレージの値が取得できるはずです。

Ubuntuでロードアベレージを取得するにはtopuptimeといったコマンドや/proc/loadavgを参照すれば可能です。

f:id:stknohg:20170427225852p:plain

f:id:stknohg:20170427230745p:plain

f:id:stknohg:20170427225912p:plain

やり方はいろいろありますが、今回は/proc/loadavgを参照する方法で2パターン試してみました。

方法.1

最初の方法はこんな感じです。

# PowerShell
'cat /proc/loadavg|awk ''{print "@{Load1="$1";Load5="$2";Load15="$3";}"}'';exit;' | bash | iex

実行結果)

f:id:stknohg:20170427230256p:plain

UbuntuのBashで/proc/loadavgの値を取得、awkでPowerShellのHashTableの書式(@{Load1=$1;Load5=$2;Load15=$3;})に成形し、Invoke-Expression(iex)でHashTableに変換しています。

方法.2

もう一つの方法はこんな感じです。

# PowerShell
'cat /proc/loadavg;exit;' | bash | % {$v=-split $_;@{Load1=$v[0];Load5=$v[1];Load15=$v[2];}}

実行結果)

f:id:stknohg:20170427230307p:plain

こちらは、Bashでは/proc/loadavgの値を取得するだけにして、PowerShellで値の成形をする様にしています。

他にもいろいろなやり方があると思います。
BashとPowerShellをどういった塩梅で組み合わせるかを考えるのはとても楽しいです。

残念なお知らせ

ここまで書いておいてアレなのですが非常に残念なお知らせがあります。

このエントリの内容を試している最中にロードアベレージの値が全然変化せず、違和感を感じたので調査してみたところ、以下のIssueが上がっていました。

github.com

現時点ではBash on Ubuntu on Windowsのロードアベレージは0.52 0.58 0.59のダミー値を返すというふざけた状態でした…*2
まだベータ版ですので値が取れないのは仕方ないと思いますが、せめて0 0 0といった自明な値にしておいてほしいものです。

こちらについては気長に待つしかないといったところでしょう。

最後に

最後にとんでもないオチがついてしまいましたがこんな感じです。
本エントリは現時点では全く役に立ちませんが、いずれ役に立つ日がくると信じています。

いまのところはBashとPowerShellを組み合わせて使う一例として見ていただければと思います。

*1:実運用では使えないと思いますが…

*2:しばらく普通に騙されてましたよ…