Windows

2017年4月 6日 (木)

PCの時計が1時間進む問題が完全に解決した

前回の続き。 PCの時計が1時間進んでいる問題ですが、 私のPCに関しては問題は完全に解決しました。 わーい。

  • 前回のあらすじ
  • 現状の確認
  • PCメーカーのサポートに問い合わせた→解決
  • 考察など
  • まとめ

前回のあらすじ

  • 自分のPCの時計が1時間進んでいた
  • 原因はPCのファームウェアの設定のせいと確信(thanks to 「「PCの時計が1時間ずれている」の原因 」)。 要するに、四半世紀前ならともかく、現在においてはまったく意味のない"Daylight Savings Enable"がなぜか有効になっているPCがあるということですね。
  • 突如、Microsoftが「修正した」とのニュースが→「えっ?」

現状の確認

Microsoftが修正したとのニュースに「ほんまかいな」と思いつつ、 1日ほど様子を見てました。 しかし、修正は落ちてきませんし、 ツールで覗くとReal-Time Clockの"Daylight Savings Enable"のビットは立ったままです。

念のため、以下の手順で実験をしてみました。

  1. PCのLANから切り離す。WiFiも無効にする(タイムサーバーとの同期を防ぐため)。
  2. Windows上で現在時刻を2017年4月3日午前1:55にセットする。
  3. PC電源を電源を切り、10分放置する。
  4. (10分後に)電源を入れる。
  5. Windows上で時刻を見る。

この結果、時刻は午前2:05頃になっているはずですが、実際には午前3:05頃になっていました。 "Daylight Savings Enable"の仕様通り、午前2時がスキップされています。

(あれ、4月2日だったっけな。 手元に残したメモには4月3日ってあるけど、 "Daylight Savings Enable"の仕様を厳密に解釈すると4月2日が正しいような気がする。 でも、もう直ってしまったので再現させて検証できない… まあ、午前2時がすっ飛ぶ現象が起きたのは確か。)

つまり、時計がずれる問題は直っていない。

PCメーカーのサポートに問い合わせた→解決

ここで意を決して、 PCメーカー(富士通)のサポートに問い合わせを投げました。 問題のPCは富士通 LIFEBOOK WA3/Wです。 これが昨日の夜。

で、今日返事がきました。

(意訳)BIOSアップデートしなはれ。

あー、確かに。 サポートに問い合わせる前に確認するべきでした。 最近、ドライバもほとんどWindows Updateで更新されるので忘れてたよ。

で、サポートページでBIOSを探すと新しいものがありました。 Readmeを見ると、ちゃんと載っているじゃないですか。

■ 5.改版履歴(修正項目)

...略...

(1.20)

  • パソコンの安定性を改善しました。
  • ごく稀に、4月と10月にパソコン内蔵の時計が1時間ずれることがある問題を修正しました。

わーい。 さすがFMVサポート。 こんなくそ面倒くさい問い合わせ分かってもらえるんだろうかと思って、 こんなツイートしてたんですけど、

えらそうなこと言ってほんますいませんでした。

BIOSアップデート後、"Daylight Savings Enable"はちゃんとDisableになっているし、 上記実験をしたら、ちゃんと再起動後の時間が午前2:05になってました。

直った。

考察など

Microsoftが修正したってのは何?

何でしょうねえ… どこかにコミュニケーションミスがあったのかも。 英語サイトを色々検索したんだけど、「修正した」ってニュースは他に無さげだし。 「PCの時計が1時間ずれている」の原因 を書いた人は、 その続編(「PCの時計が1時間ずれている」の原因の解説)で Microsoftのタイムサーバーのマシンでこの現象が発生したんじゃないか、と言ってます。 うーん。 でも、そうだとすると、Windowsの時刻の同期間隔はデフォルトで一週間と聞いているので、 「影響を受けたPCの時計は、日本時間4日未明までに自動で直っているという。」(「PCの時計が1時間ずれる」グローバルで発生「修正した」とMS)なんて言えないんじゃないかな。 よくわからない。

どうして今回だけ騒ぎになった?

これも分からない。 ただ、検索してみると、過去にも時間がずれたという声はあるし、 私も、前に時間がずれて「あれー」と思いながら直したことをぼんやり思い出したし、 実は以前から結構発生してたのではなかろうか。 今回、声が目立ってニュースにも取り上げられたということかも。

あと、最近広く採用されたBIOSにそういう設定のものがあったのかも知れない。

メーカーはもっと広く知らせるべきでは

と思うんだけど、 BIOSアップデートだとするとあんまり安易に勧められないしなあ。 Windows Updateでなんとかならんのだろうか。 ボードのファームウェアとなるとWindows Updateレベルでは難しいのかな。

結局、PC側の原因で問題が発生するのはどういう場合?

  • RTCの"Daylight Savings Enable"がEnableで、
  • RTCがずれるタイミングでPCが動いておらず(停止 or スリープ)、
  • その後PCを起動した場合(電源投入 or スリープ解除)

は確実に起こるかな。 OSがRTCと同期するとずれた時刻がOSに伝わる。

PCが稼働中にRTCがずれた場合はよくわからない。 OSがRTCに書き込む機会があるかどうかに依存するでしょう。

Windowsだけの問題?

いや、違うと思う。 ボード上のRTCがずれるんだから、 ずれた後に起動すれば例えばLinuxでも時間がずれるでしょう。

ただ、Linuxとかの場合、 どういうタイミング・方法でntpサーバーと同期しているのか知らないので、 その影響はよくわからない。 Windowsより短い期間で同期しているマシンが多いような気がする。 知らんけど。

まとめ

PCの時計がずれて直っていない人は、 PCメーカーからBIOSの更新が出ていないか確認してはどうでしょうか。

ただ、 BIOSアップデートは無条件にお勧めできるものでもないので、 アップデートするかどうかは注意事項をよく読んでからお決めください。

2017年4月 4日 (火)

PCの時計が1時間進む問題が発生したので調べてみた(もう答は出た、と思ったけどなんか混迷している)

昨日(4月3日)、私のPCの時計が1時間進んでいるのに気が付きました。 どうやら、同じ目にあっている人が多数いたようです。

「PCの時計が1時間ずれている」報告多数 (ITMedia)

気持ち悪いので少し調べてみました。 なんですけれど、今日タイムライン上で以下の記事を知りました。 答はこれで決まりでしょう。 (と思ったんだけど、今ちょっとわけわからん状態になっている。「で、どうするよ」の項で後述)

「PCの時計が1時間ずれている」の原因 (Tactful Answer)

ですが、せっかく簡単な実験などしていたので、 書き残しておきます。

  • 観察
  • 実験
  • で、どうするよ

観察

4月3日夜、家の帰ってPCをスリープから復帰させてしばらくして、時計が1時間ずれていることに気づきました。 家にPCが数台ありますが、自分のノートPC1台のみ時計が進んでました。

で、イベントログの「システム」でスリープ前後を見ると、 以下のようなログが残っていました。

時刻 ログ
2017/04/03 0:32:53
システムがスリープ状態になります。

スリープの理由: アプリケーション API
2017/04/03 0:32:54
システムがスリープ状態から再開されました。
2017/04/03 20:57:35
システム時刻は ‎2017‎-‎04‎-‎02T15:32:54.726613700Z から ‎2017‎-‎04‎-‎03T11:57:35.500000000Z に変更されました。

変更の理由: システム時刻がハードウェア クロックと同期されました。

時刻はUTCで出ていますが、 日本時間に直すと、 4/03 0:32にスリープしています。 その後、スリープから復帰し、直後にハードウェアクロックと同期しています。 この際のハードウェアクロックの時刻は20:57です。 「再開しました」ログのタイムスタンプが0:32:54なのは、クロック同期前なので、スリープ時点の時刻が出てしまっているのでしょう。

記録されたスリープ時の時刻は前夜の記憶通りで正しいものです。 一方、PCを再開したのは20時前でした。 つまり、復帰時にハードウェアクロックが1時間進んでいる。

復帰時のハードウェアクロックが進んでいるので、 OSではなくPCのクロックの問題なんだろうと思って、 以下のようなツイートをしました。

実験

で、今朝(4/04)、ちょっと実験をしてみました。 出勤前に、PCに以下の操作をしました。

  1. PCをLANから切り離す(WiFiも無効にする)
  2. PCを再起動し、Windowsは起動させず、BIOS画面で時間を4/02 23:30にする
  3. 電源を切る

夜、帰宅後に電源を投入し、そのままBIOS画面を出して時間を確認しました。 すると、予想通り、朝ずらした時間から予期される時間よりも1時間進んでいました。

LANに繋がず、OSも動かしていない状態で時計が進んだので、 OSもタイムサーバーも無関係。

この結果は、 冒頭に紹介した記事(「PCの時計が1時間ずれている」の原因 )の説明と整合します。

で、どうするよ

先の記事の説明に従って自分のPCを調べたところ、 確かにPCの"Daylight Savings Enable"設定が有効になっていました。 これが有効だと、4月と10月にPCのクロックがずれます。 つまり、この先も半年ごとに時間がずれることになります。 自分はツールで設定を変更するとして、 一般ユーザーとかどうするんだろうか。 これは多分工場出荷時の設定がこうなっているんだろうから、 メーカーのサポートに連絡した方がいいんだろうか、 とか思っていたところ、 Microsoftが修正(!)したとのニュースが。

「PCの時計が1時間ずれる」グローバルで発生「修正した」とMS (ITMedia)

いったい、どうやって? Windowsから"Daylight Savings Enable"を無効化してくれるのか? まさか、強制的に時刻同期させて終わりじゃないよな? 半年後またずれるし。

疑いをもちつつWindows Updateを試みましたが、 なにも落ちてきません。 念のため、先のツールで再チェックしましたが、 "Daylight Savings Enable"は有効のままです。

謎。しばらく様子見。

あともう一つ疑問があって、 なんで今回のみ騒ぎに? そういえば、このPCにしてから時計がずれていたことが以前にもあって、 「あれー」と思いながら時計を合わせたような覚えがぼんやりとあるんだけど、 今回これほど騒ぎになったのはなんでだろう? 最近よくPCに採用されているボードがこの設定になっているとか?

2017年3月 7日 (火)

OAナガシマのおっさんの話(Visual Studio 20周年記念)

Visual Studioは今年で20周年だそうで、 #MyVSStory などというハッシュタグもできていました。

おおっと思ったので、こんなことを書きました。

で、OAナガシマのおっさんのことをちょっと思い出したので、書き残しておこうかなと思います。 実はそんなによく知らないし、 人柄を表すようなエピソードとかも無いんだけど、 大昔、おっさんを店頭で見かけていた頃の話。

OAナガシマとは

私が沼津に来たのは90年代始めの頃です。 地元の人に「沼津のパソコンショップならここ」と教えてもらったのがOAナガシマでした。 「OAナガシマ」という店名からして、 OA事務機器屋が出自なのでしょう。 (そういえば、当時DOS/V雑誌に怪しげな広告を載せていた「大西ジム」も高砂の商店街の文房具屋(ジム = 事務)でした。何回か行ったことある。今検索したら、まだ元気でやっているらしい)

その頃の店は沢田のバイパス沿いにあり、まあ、いわゆるDOS/Vショップでした。 世界的には、ちょうどPC/AT互換機上でWindowsがブレイクした頃です。 日本ではNECやら富士通やら東芝やらが独自規格のパソコンを出しており、 それらは結局PC/AT互換(いわゆる「DOS/V機」)になっていくのですが、 その時点ではDOS/Vはまだ立ち上がりかけの頃でした。 Windowsが盛り上がっており、海外で面白そうな機器やソフトが出るのに、 日本は独自規格のせいでなかなか利用できない。 Windows 3.1とか、USで発売されてから国内発売されるまで1年以上かかったなあ。 各社版の対応に手間取っている、とかの噂でした(本当かどうかは知らない)。 「鎖国状態」とか言われたりしてましたね。今ならガラパゴスか。 お好きな方はPC/AT互換機を個人輸入したりしてましたが、 そういう「DOS/V」世界の窓口がDOS/Vショップでした。 秋葉原ならたくさん店もあるんでしょうが、 地方なもんで、 近所にOAナガシマがあるのはとてもありがたかった。

なんか、DR-DOS買ったこととか思い出した。 冷やかしのつもりで店番してたおっさんに声をかけたら、 勢いに乗せられて気づいたら買ってて、 しばらくDR-DOS使ってたよ。

さて、時は1992年

Windowsはまだ16-bitの3.xの時代。 ちょうどアメリカでVisual Basic 1.0(これがまたちょっとした衝撃だった)が出た翌年。 私は「某言語でVisual Basicみたいのを作ろう」というプロジェクトに配属されました。 当時のWindows開発環境は、コマンドラインベースのMicrosoft C 6.0 + Windows SDK。 デバッガ(Code View)はこんな感じ。 (Microsoftのフォーラムの質問にCode Viewの画面イメージがあったので引用)

Code Viewの画面

せっかくWindowsがGUIを導入したのに、開発環境はキャラクタベースです。 ついでに言うと、会社支給のパソコンはFMRという独自規格。 それに富士通が出しているFMR用のDOSとWindowsとWindows SDKを入れて頑張るわけです。 (ちなみに、富士通の「DOS/V機」であるFMVは翌年秋の発売でした)

そんな中、 このプロジェクトが調査用に購入していたソフトウェアの中にQuick C for Windowsがあって、 これを動かしてみて私は衝撃を受けました。 フルGUIだし、「統合」されていて、ビルドからデバッグまでその上ですべてできる。 Windowsが普及し始めたころで、当時はWebとかもまだ広がってないためググるわけにもいかず、 Petzold本とかを頼りにプログラムを書いて色々挙動を確認するんですが、 この「ちょっと書いて動かしてデバッガで状況を見る」ということがGUI上で一目瞭然にストレスなくがんがん回せる。 生産性、という言葉では気が済まない、なにかパラダイムシフトのようなものが頭の中で起こりました。 目から鱗。

巧みな操作で計算機リソースを効率的に使う、 というのがスマートだと思っていました(まわりの達人的な人はほとんど共用ワークステーションとかにぶら下がってたし)。 しかし、考えたらこれは「パーソナル」なコンピュータなので、 CPUを自分の都合のためにぶん回すのは大正義である、 いや、自分が仕事を遂行するためにぶんぶんぶん回すべきである。 能天気にカーソルキー押しっぱなしてスクロールするのはCPUを無駄に使う頭悪そうなやり方だけど、 それで簡単に目的の場所に行けるならいいじゃないか。 「パーソナル」用機械を好きに使ってさっさと仕事しろよ、ということに思い至ったのでした。

人によってはVisual Basicが目から鱗だったりするようですが、 私はQuick C for Windowsだったなあ(いやまあ、Visual Basicも凄かったけど)。

ということで、 同じく調査用に海外から購入してたGateway 2000のマシン(鉄の筐体、純白の4DX2-66V)を占有し、 DOS/VとWindowsを入れ、Quick Cでごりごりプログラムを書いていました。

そんなこんなしているうちに

アメリカでVisual C++ 1.0が出ました。 「むっちゃ欲しい」と思うわけです。 IDEも進化しているみたいだし、CもC++になっているし。 でも日本では発売していない。

で、とある日曜日にOAナガシマに行ったら、 なんということでしょう。 置いてあるんですね。 でかい箱がでーんと置いてある。 おっさん、どこからモノを引っ張ってきたんだと思いました。 しかも、US価格から想定した値段よりかなり安い。 バッタもんじゃなかろうかとも疑ってまじまじと見てみましたが、どう見ても本物。 結局買いました。 両手でないと持てない大きさで、重かった。 開けてみると、中にはみっしりとWindows APIのマニュアルが入ってた。

当時の写真を探したら、箱が写っているものが一枚ありました。 あまりに部屋が乱雑で全景を出すのはアレなので、一部切り出しますが、箱の奥行をお察しください。

Visual C++の箱

探してみたら、フロッピーディスクまだありましたよ。

Visual C++のインストールフロッピーディスク

安かった理由は謎です。 仕入れ経路で誰か何か間違えてたか。 実はアップグレード版か何かだったりして。

ともかく、 Visual C++というアイテムを手に入れた私は絶好調でぶいぶいいわせながら開発したのでした。 当時まだ私物ソフトの使用禁止とかルール化される前でしたね。 まあ、仕上げには会社設備のMSCでコンパイルするようにはしてたけど。

その後

Visual C++はVisual Basicと統合されてVisual Studioになりました。

一方、 OAナガシマの方は、どんどん店が増えていきました。 本店は沢田から今ある大諏訪に移り、 ZOAという名前で静岡県以外にも店を出すようになりました。 今の正式な社名は「株式会社ZOA」のようですね。 その頃にはもうおっさんを店頭で見ることはなくなりました。 そういえば、Windows 2000の発表時には、 マイクロソフトの発表資料に他のメーカーやショップに並んで、 おっさんのコメントが載っていたなあ。 今検索して探し出したプレスリリースには社名しか出ていないけど、 当時のリリースではこのコメントがおっさんの名前入りで出てて、Webニュース経由で見てのけぞった記憶がある。

そして、一、二年前、 店の営業時間を確認するためにOAナガシマのサイトを見に行って、 間違って「会社概要」を開いてしまったら、 代表者の名前がおっさんじゃなくなっていました。 引退したのかな、とも思ったのですが、 気になったのでIRを見てみたら、 2013年の夏におっさんが亡くなったとの知らせが出ていました。

昔の沢田の店も、 去年更地になり、 ポルシェの店になりました。

その頃(もう四半世紀前)からすると、 PCをめぐる状況も、 OSやソフトや開発環境のあり方もずいぶん変わりました。 一方、その頃作っていたそのソフトは、 幸運にも気に入ってくれた人が結構おり、 バージョンを重ね、 まだ稼働しているものもあります。 ソフトウェアが世に出るのはいろんな人の仕事やら偶然やらが積み重なった結果なのですが、 あのソフトには「おっさんがVisual C++をどっかから引っ張ってきてくれた」という要素も入っているのです。

ということで、 おっさんのご冥福をお祈りします。 と同時に、Visual Studio 20周年おめでとうございます。

2017年1月26日 (木)

認証プロキシをなんとかするためにツールを作っている話

【要約】認証プロキシをなんとかするためにツールを作ってGitHubで公開した。

経緯

社内ネットワークからhttp/httpsで外部に出る際にはプロキシを通さなければならない、 という環境は多いと思います。 こういうプロキシの中にはユーザー名とパスワードを入れないと通してくれないタイプのものがあります。 認証プロキシというやつですね。 これは本当に頭痛のタネです。

さすがにブラウザとかは認証プロキシに対応しているのですが、 これに対応していないソフトウェアも結構あります。 今時いろんなソフトウェアがhttp/httpsで通信していまして、 特に開発系のツールは必要なコンポーネントをhttp経由で自動的に取ってくるみたいな動作をすることが多いのです。 こういうソフトウェアの多くが素の状態では認証プロキシを通らない。 家で試すと特に問題なく動くツールが、 会社環境だと意味不明なエラーで動かなくなったりします。

ここ二三年、 わけのわからないエラーが出るたびに、 どれが引っかかっているのか調べ、 その設定方法を調べ、 ちまちまと設定しては乗り切っていました。 結果、あちこちの設定ファイルに認証プロキシのパスワードが埋め込まれて、 なにかが間違っているような気がするわけですが、 まあ、仕方ないね。

が、最近Visual Studio 2017 RCのアップデートが認証プロキシ環境内で帰ってこなくなり、 対処方法が皆目わからないという事態が発生するに至って、 我慢の限界を越えました。 こんなもん、やっとれるかーーーーーーーー。

というわけで

ツールを作りました。

これはWindowsのデスクトップ上でローカルプロキシとして動作します。 動かすと、現在のユーザーのプロキシ設定を書き換え、 自分をプロキシとして登録し、 ソフトウェアからの通信を中継します。 で、本来の認証プロキシが認証を要求すると、 通信元のソフトウェアに帰ることなく認証情報をつけてリクエストを再送信します。 結果として、 ソフトウェアが普通のプロキシにふつうに対応していれば、 そのまま通信できます。 中継はタスクトレイのアイコンから簡単にON/OFFできます。

これは認証プロキシを回避するものではありません。 認証プロキシに対応していないソフトウェアのhttp/https通信を中継して、 正しく認証プロキシを通すようにするものです。

効能としては以下の通り。

  • 認証プロキシ環境内で認証プロキシ非対応ソフトウェアを利用することができます。
  • 認証プロキシのパスワードをあちこちに書かなくてすみます。 パスワードは暗号化された状態で設定ファイル一箇所にあれば十分です。 (まあ、元々認証プロキシのパスワードはあんまり安全でないやり方でやりとりされますので、気休めではありますが)
  • 仮想化ソフトウェア(Hyper-Vなど)が定義したマシン内ネットワークに対する(通常)プロキシとして利用できます。 これを利用すると、 「プロキシの設定を埋め込んだままのイメージを公開してしまった!」という事故をやらかしても、 パスワードが埋め込まれないため、多少状況はましになります。

GitHub上で公開しています

設定ウィンドウとかまだ実装できていないけど、 とりあえず役立つ程度には動いているので(Visual Studio 2017 RCのアップデートもできたし)、 tu公開します。 モノはGitHub上にあります。 ツール名は「認証プロキシ爆発しろ!(英語名は MAPE: May Authentication Proxy Explode)」です。

ipponshimeji/MAPE (GitHub)

詳細な説明とかは、 以下のページから。

目次 - 認証プロキシ爆発しろ! (GitHub)

手っ取り早くどういうものか知りたい方は、特に以下のページを。

認証プロキシでお困りの方はお試しくださいまし。

ちなみに

Windows環境で認証プロキシをなんとかするにはFiddlerを使う技とかもありますが、 以下の理由から独立したツールを作りました。

  • Fiddlerを使う場合、Fiddlerのスクリプトをいじる必要(しかもちょっと複雑)があり、 非開発者な人に「これを使えばなんとかできます」とか言いにくい。
  • 自動構成スクリプトでプロキシが設定されている環境では、 Fiddlerのプロキシ設定書き換えは「次で始まるアドレスにはプロキシを使用しない」を設定してくれない。 認証プロキシが設置されているような環境では自動構成スクリプトを利用していることが多いでしょうから、 これは面倒の元になりがちです。

なお、Fiddler自体は便利なデバッグツールとして利用させていただいております。

【2017年4月11日追記】

上にはこう書きましたが、 「次で始まるアドレスにはプロキシを使用しない」に相当する設定がありました。 すいません。

2016年9月28日 (水)

Windows 10上のコンテナでLinuxイメージもWindowsイメージも同時に扱えるようになった(追記あり)

8月4日のエントリ「Windows 10のコンテナ機能とDocker for Windowsを共存させる上での問題点」に書いたように、 Windows 10 Anniversary Update(version 1607)ではコンテナ機能が使えるようになりましたが、 Windowsイメージを動かすエンジン(Windows 10 Container)とLinuxイメージを動かすエンジン(Docker for Windows)は共存できませんでした。

が、どうやらDocker for Windowsは、 ベータ26以降、 LinuxイメージもWindowsイメージも動かすことができるようになったようです。

Run Linux and Windows Containers on Windows 10

【2017年1月21日追記】 1.13.0以降、ベータでなくとも(Stable版でも)Docker for WindowsでLinux/Windows両方のコンテナが扱えるようになりました。

ということで、Windows上の各コンテナエンジンをいったんアンインストールして、 Docker for Windowsのページからベータ版をダウンロードしてインストールしました。 すると、上記ブログのアニメーションGIFの通り、 Docker for Windowsのタスクトレイアイコンから出るメニューに「Switch to Windows Containers...」が現れ、 これを選択するとdockerコマンドがWindows向けエンジンとつながるようになりました。 やったー。

が、まあ、Windowsイメージについては、 8月4日の別エントリ「Windows 10のコンテナ機能(Docker for Windowsじゃないよ)が動かない話と気になった点」に書いた ”The process cannot access the file because it is being used by another proces”問題が再現して動きませんでしたけど。 これ、解決しないなあ。

あと、Windows 10のコンテナ機能は、 開発者向け機能という位置づけです。 念のため。 運用向けには、今週”Microsoft Ignite 2016”で発表されたWindows Server 2016上のコンテナを使えということでしょう。

Igniteと同時に発表されたDockerのブログを見ると、 Windows版コンテナはDockerが深くかかわっているようですね。 "containers on Windows Server 2016 are powered by Dock"だと書いていますし、 "Docker containers run natively on Windows"と"container"ではなく"Docker container"と言い切っています。 2014年秋に「MicrosoftとDockerが協力してWindows Serverにコンテナを実装するよ」という発表をしていましたが、 出てきたモノは思ったよりDockerそのものらしい。

ということで、 Docker for WindowsがLinuxイメージの扱いとWindowsイメージの扱いを統合してくれる、 というのは自然な流れなのかな。

2016年8月 4日 (木)

Windows 10のコンテナ機能とDocker for Windowsを共存させる上での問題点(追記あり)

覚え書き。

前回のエントリで書いたように、 Windows 10 Anniversary Update(version 1607)では二種類のコンテナツールを利用できます。 (Windows 10 コンテナはまだ動かせていないけど)

ツールコンテナで動かすイメージ提供者
Windows 10 コンテナWindowsイメージMicrosoft
Docker for WindowsLinuxイメージDocker

これらを共存させ、 dockerコマンドで操ることができれば、 Windows 10上でLinux環境もWindows環境もさくさく立ち上げることができて便利だと思うわけです。

で、両者が共存できるか試してみました。

結論から言えば、「両者を同時に動かすことはできない」なんですが、 試して分かった点について書き留めます。

【2016/09/28 追記】 Docker for Windowsのベータ26以降、Docker for WindowsでLinuxイメージもWindowsイメージも両方取り扱うことができるようになりました。 「Windows 10上のコンテナでLinuxイメージもWindowsイメージも同時に扱えるようになった」を参照。

コンテナ機能の構造

これらのツールを、ざっくり以下の二つの部分に分けます。

  • CLI部分(要するにdockerコマンド部分)
  • エンジン部分(Docker Engine)

エンジン部分は両者ともサービスとして稼働し、 Hyper-Vを間に挟んでコンテナを動かします。 Windows 10コンテナはWindowsのイメージを動かしますし、 Docker for WindowsはLinuxのイメージを動かします。

Windowsコンテナには本来のコンテナに近い形態の「Windows Server Containers」と、 コンテナホストとコンテナのカーネルをHyper-Vで分離する形態の「Hyper-V Containers」があり、 Windows 10コンテナでは「Hyper-V Containers」のみがサポートされています。

両エンジンのWindowsサービスとしての名前は以下の通り。

  • Windows 10コンテナ: Docker Engine(いかにも仮の名前っぽいので、そのうち変更されそう)
  • Docker for Windows: Docker for Windows Service

一方、 CLI部分は両者ほぼ同じです。 Windows 10コンテナの方が少し新しいぐらい。 実際、 CLI部分を両者交換しても、 動作に影響はありませんでした。

ちなみに、docker versionコマンドを実行すると、 以下のような結果になります。

Windows 10コンテナの場合。

PS C:\Temp> docker version
Client:
Version: 1.13.0-dev
API version: 1.25
Go version: go1.6.3
Git commit: 87e48ec
Built: Wed Aug 3 20:33:19 2016
OS/Arch: windows/amd64

Server:
Version: 1.13.0-dev
API version: 1.25
Go version: go1.6.3
Git commit: 87e48ec
Built: Wed Aug 3 20:33:19 2016
OS/Arch: windows/amd64

Docker for Windowsの場合。

PS C:\Temp> docker version
Client:
Version: 1.12.0
API version: 1.24
Go version: go1.6.3
Git commit: 8eab29e
Built: Thu Jul 28 21:15:28 2016
OS/Arch: windows/amd64

Server:
Version: 1.12.0
API version: 1.24
Go version: go1.6.3
Git commit: 8eab29e
Built: Thu Jul 28 21:15:28 2016
OS/Arch: linux/amd64

問題点

両者ともCLIとエンジンの間の通信は名前付きパイプを通して行っています。 この名前付きパイプの名前が"//./pipe/docker_engine"に固定されています。 ざっと見、この名前を変更できる設定を見つけることはできなかった。

なので、 一方のエンジンが稼働中に、 もう一方のエンジンを起動しようとすると、 「名前付きパイプのオープンに失敗した」エラーで起動失敗します。 イベントログを見てみると、 "fatal: open //./pipe/docker_engine: Access is denied." とか出てます。

ということで、 両者を同時に稼働させることができません。 私は、両方のサービスの起動方法を「手動」に設定して、 手動でエンジンを切り替えてます。

あと、 直接不具合は経験していないけど、 両者ともに作業フォルダとして%ProgramData%\Docker以下を使うことがあるようで、 両者の作業が干渉しないかちょっと心配。

今後どうなる?

うーん。

CLI側はdockerコマンドの-Hオプションに名前付きパイプの名前を指定すれば、 それと通信するようになるんじゃないかな。

とすると、どちらかのエンジンが使う名前付きパイプの名前を変更するのかなあ。 デフォルトはどっちになるんだとか、 面倒にならなければいいんだけど。

希望としては、 同一のdockerコマンドで、 LinuxイメージもWindowsイメージも、 どっちのエンジンとか気にせずに操れるようになればうれしいんだけれども。

Windows 10のコンテナ機能(Docker for Windowsじゃないよ)が動かない話と気になった点

覚え書き。

Windows 10 Anniversary Updateが公開され、 それに伴い、Windows 10のコンテナ機能も一般利用可能になりました。

で、Windows 10のコンテナ機能を使ってみようとしてみたところ、

  • 手順通りにやっても動かない点
  • 気になった点

があったので、それを書き留めておきます。

Windows 10のコンテナ機能とは

Windows 10のコンテナ機能とは、

  • Microsoft純正の、
  • docker互換である、
  • 「Windowsコンテナ」(Windows Server 2016の機能)の、
  • サブセットをWindows 10に載せたものであり、
  • (プレビューではない「正式」なWindows 10としては)Windows 10 Anniversary Update(version 1607)以降で利用できます (でもまだ仕上がってない感触)。

前回のエントリで動かした Docker for Windowsとはまた別物です。

ツールコンテナで動かすイメージ提供者
Windows 10 コンテナWindowsイメージMicrosoft
Docker for WindowsLinuxイメージDocker

でも、どちらもdockerコマンドでコントロールできます。

Windows 10のコンテナ機能の有効化方法

コンテナ機能を利用できるのは、 Windows 10 (version 1607)のProまたはEnterpriseです。

有効化手順は、 「Windows コンテナーに関するドキュメント」の中の 「Windows 10 の Windows コンテナー」 の通り。

問題点

上記の「Windows 10 の Windows コンテナー」の手順中の、 「3.コンテナーの基本イメージのインストール」が動きません。

この手順は、 最初のイメージとしてNano Server(最小構成のWindows Server 2016)ベースイメージをダウンロードし、 それを登録するものです。 現状のWindows 10のコンテナ機能は、 リポジトリからのpullが実装されていないため、手動でこれを行うわけですね。

手順には以下のコマンドを実行しろとありますが、

docker load -i nanoserver.tar.gz

実際に実行してみると、エラーになります。

PS C:\Temp>docker load -i nanoserver.tar.gz
58684737b3d1: Loading layer [==================================================>] 358.4 MB/358.4 MB
re-exec error: exit status 1: output: ProcessUtilityVMImage C:\ProgramData\Docker\windowsfilter\facecd91a2eee5e77d3046e9
a4b63daffe037fc96725e6d6ca5b847ebde016ce\UtilityVM: The process cannot access the file because it is being used by anoth
er process.

素直に受け取ると、 一時ファイルをクローズせずに次の工程へ渡している単純ミスっぽいけど。

回避法

見つけられていません。 まあ、どうせすぐ直すだろうと諦めた。

MSDNの「Windows Containers」フォーラムで同じ問題が報告されていましたので、 Voteしました。

re-exec error when trying to load nanoserver image (MSDN "Windows Containers" Forum)

でも他にVote無いんだけど、みんなちゃんと動いているのかな。

他に気になる点

Windows 10のコンテナ機能に対し、 ユーザー権限(非管理者権限)でdockerコマンドを実行するとエラーになります。 こんな感じ。

PS C:\Temp> docker version
Client:
Version: 1.13.0-dev
API version: 1.25
Go version: go1.6.3
Git commit: 87e48ec
Built: Wed Aug 3 20:33:19 2016
OS/Arch: windows/amd64
An error occurred trying to connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.25/version: open //./pipe/docker_engin
e: Access is denied.

Docker Engine相当のものがWindowsサービスとして動いており、 それと通信するための名前付きパイプのアクセス権が管理者に限定されているのでしょう。

dockerコマンドによって危険なコンテナを動かすこともできますし、 dockerコマンドに管理者権限が必要だというのは分かります。 まあ、もうちょっとユーザー向けなエラーメッセージ出したほうがいいんじゃない、というのはあるけど。

でも、 Linuxでのdockerの使われ方を参考にするなら、 グループを作ってそのグループのユーザーのみアクセスできる、 という形態にしないと、 使い勝手が悪くなるんじゃないかなあ。

一方、 Docker for Windowsは、 現状ユーザー権限でdockerコマンドが問題なく動いてしまいます。 こっちはこっちで心配になる。

Docker for Windowsで"Network timed out"と言われてイメージを取ってこれない問題

覚え書き。

問題点

典型的には、 「Getting Started with Docker for Windows」の「Step 4. Explore the application and run examples」の手順にある、

PS C:\Work> docker run hello-world

を実行しようとすると、以下のようなエラーが出ます。 (問題の個所を赤字にしている)

PS C:\Work> docker run hello-world
Unable to find image 'hello-world:latest' locally
Pulling repository docker.io/library/hello-world
C:\Program Files\Docker\Docker\Resources\bin\docker.exe: Network timed out while trying to connect to https://index.dock
er.io/v1/repositories/library/hello-world/images. You may want to check your internet connection or if you are behind a
proxy..

See 'C:\Program Files\Docker\Docker\Resources\bin\docker.exe run --help'.

今回はリポジトリからイメージをpullしようとしているところだけど、 外部のネットワークに接続に行く局面で同じ問題が出るのではないかな。

発生条件

今回問題が起きて、対処した環境は以下。

  • OS: Windows 10 Pro (x64) version 1607 (build 14393.10)
  • Docker for Windows 1.12.0 (「プログラムと機能」上で表示されるバージョンは2.0.5968)

回避法

IPv6を無効にしたら通るようになりました。

Docker for WindowsはHyper-V必須ですので、 「コントロールパネル」-「ネットワークとインターネット」-「ネットワーク接続」へ行くと、 Hyper-V関連の接続を含めて色々な接続があります。 そこで、実際に外部に直接繋がっている接続の「プロパティ」を開き、 「ネットワーク」タブの「インターネットプロトコルバージョン6 (TCP/IPv6)」のチェックを外しました。

備考

なんでIPv6を無効にしてみる気になったかというと、 ログファイル(Docker for Windowsの「Diagnose & Feedback」から出せる)に以下が出ていたからです。 (注目点を赤字にしています。各行のヘッダ部は省略)

Found dns server xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx
Forward DNS query on udp to xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:53
Exchange error: dial udp: too many colons in address xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:53

※ "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx"は実際には私のマシンのDNSアドレス

内部でアドレスをどういう形式で持っているかわからないけど、 これ、"[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]:53"となっているべきだよなあ。 というわけで、なんかバグってるんじゃなかろうかと疑いました。

余談

Docker for WindowsはPrivate Beta時代から試しているんだけど、 実はずっとまともに動かせていませんでした。 今日、Windows 10 Anniversary Updateを入れて、 新機能のWindows 10のコンテナ機能を試すついでにまじめに調べてみました。

で、今度はWindows 10のコンテナ機能の方がまだうまく動かせていない。orz

2016年7月20日 (水)

xUnit.netのテストがTest Explorerに出てこない

覚え書き。

xUnit.netを使っていてテストエクスプローラーにテストが出てこない、 というのはたまに起こって毎回原因探しに苦労するんだけど、 今回は条件がはっきりしているので記録しておく。

問題点

通常、 以下の手順でxUnit.netのテストを書いてビルドすると、 Visual Studioの「テスト エクスプローラー」上に記述したテストが自動的にリストアップされるはずだが、 それが出てこない。

  • Visual Studio 2015 Update 3で、
  • C#の「クラス ライブラリ(ポータブル)」プロジェクトを作り、
  • NuGetで以下のコンポーネントを追加し、
    • xunit 2.1.0
    • xunit.runner.visualstudio 2.1.0
  • xUnit.netのテストを記述する
  • プロジェクトをビルドする

発生条件

「クラス ライブラリ(ポータブル)」の「ターゲット」として以下を選択すると発生するっぽい。

  • 以下の二項目のみを選択する。または、
    • .NET Framework 4.6
    • Windows Universal 10.0
  • 以下の三項目のみを選択する。
    • .NET Framework 4.6
    • Windows Universal 10.0
    • ASP.NET Core 1.0

どうも、 ターゲットを上記条件にすると、 プロジェクトがNuGet 3を使う構成になるようです。 そうなった場合に、 テストがテストエクスプローラーに出てこなくなるみたい。 一部の設定がうまく組み込まれないのかねえ。

ちなみに、 ターゲットを「.NET Platform Standard」にしても プロジェクトがNuGet 3構成になるようです。 この場合、xunit 2.1.0を組み込もうとしても、 「Some packages are not compatible with .NETStandard」と文句を言われてそもそも組み込めません。 最新のプレリリースである、"xunit 2.2.0-beta2-build3300"ならば組み込むことができました。 それでもテストエクスプローラーにテストは出ないけど。

回避法

見つけられませんでした。

まあ、当面ターゲットを".NET Framework 4.5" + "Windows 8" + "ASP.NET Core 1.0"ぐらいにしておいて、 様子を見ますかねえ。

今後Portable Class Libraryは.NET Platform Standardベースになっていくだろうし、 プレリリース版で.NET Platform Standardに対応しようとしている感じなので、 待っていればそのうち対応されるんじゃなかろうか。 知らんけど。

2016年5月12日 (木)

Microsoft Bot Frameworkを使ってSlashのbotを作ってみた(前編)

連休中にMicrosoft Bot FrameworkでBotを作って、 家族内の連絡に使っているSlackのチームに突っ込んでみました。 まずは、特に工夫もない単純なBotだけど。 その話などぼちぼち書いてみます。

Microsoft Bot Frameworkとは

Microsoft Bot FrameworkはBuild 2016において"Conversations as a Platform"の一要素として発表されました。 賢いBotが人間の相手をして、仕事を色々とこなしてくれれば、 GUIとかとはまた違った便利なインターフェイスなるだろう、 そういうBotを作ろうぜ、 という話ですね。

Botを作る話はFacebookも最近発表しました。 Facebookの話がFacebook Messengerを対象にしているのに対し、 Microsoft Bot Frameworkは様々なメッセージングサービスを相手にします。 Botサービスを一つ立ち上げておいて、 それを各種サービス(Email, Slack, Skype, Facebook Messenger, etc.)に繋ぎます。 LINEも対応予定だと言っていたなあ。 現状のメニューには出てなかったけど。

以下の図がよく説明で引用される図です。

Bot Frameworkの説明図

Bot Framework Overviewから

Bot Frameworkは大きく以下の三つの要素からなります。

  • Bot Builder SDKs: Botを簡単に開発できるようにするSDK
  • Bot Connector: 作ったBotをメッセージングサービスに繋ぐサービス(SaaS)
  • Bot Directory: (将来予定)Botを流通させるためのサービス

BotとBot Connectorの関係はこんな感じ。 BotはBot Builder SDKで作らなくても、 インターフェイスを満たせばBot Connectorで繋げることができます。

Bot Frameworkの構成図

Bot Framework Overviewから

メッセージングサービスにBotを送り込む枠組みはこれでよいとして、 「賢い」Botを実装するためには、 賢く状況を認識できるようにしなければなりません。 そのための道具立てが"Conversations as a Platform"のもう一つの要素である"Microsoft Cognitive Services"です。 色々な認識を行うためのサービスが揃っています。 その中のEmotion APIは先月簡単に動かして見ました(前編, 後編)。

さて、ということでSlack上で動くBotを作ってみます。 今編では、まずBot Builder SDKを使ってBot本体を作ります。 次編でBot Connectorを使ってそれをSlackに接続します。

どういうBotを作るか

ファーザーBotを作ります。 以下のセリフをランダムに返します。

  • いいです。
  • わしもですか?
  • みんなもですか?
  • わしがですか?

これは、 「神聖モテモテ王国」のファーザーが発行した紙幣(壱萬ラブ)の四コマ中のセリフです。 これをランダムに返してくれると、 いい感じに壊れた雰囲気になるでしょう。

言語の選択とSDKの準備

まず、言語を選択します。 現状用意されているのはC#またはNode.jsです。 ここではC#を使います。 C#を使う場合は、 Visual Studio 2015 Update 2以降が必要です。 Node.jsを使う場合は、Node.jsとエディタだけでできそう。

C#版SDKは実質的にはテンプレートのみです。 テンプレートのzipファイルをユーザーレベルのテンプレートの置き場所に置くだけです。 具体的には説明の通り。

プロジェクトの作成

ここでVisual Studioを起動し直すと、 「新しいプロジェクト」のC#のプロジェクトテンプレートの中に「Bot Application」テンプレートが現れるようになります。

「新しいプロジェクト」ダイアログ

ここからプロジェクトを新規作成すると、 プロジェクト構成はこんな感じになります。 ASP.NETのWeb APIがベースっぽいですが、 かなりシンプルになっています。

プロジェクト構成

ソースコードの修正

ソースコードの中心部は以下です。 テンプレートの初期実装は入力メッセージの文字数を答えるものですね。

namespace FatherBot {
  [BotAuthentication]
  public class MessagesController: ApiController {
    /// <summary>
    /// POST: api/Messages
    /// Receive a message from a user and reply to it
    /// </summary>
    public async Task<Message> Post([FromBody]Message message) {
      if (message.Type == "Message") {
        // calculate something for us to return
        int length = (message.Text ?? string.Empty).Length;

        // return our reply to the user
        return message.CreateReplyMessage($"You sent {length} characters");
      } else {
        return HandleSystemMessage(message);
      }
    }

これを以下のように変更します。 まあ、まずはシンプルな内容で。

namespace FatherBot {
  [BotAuthentication]
  public class MessagesController: ApiController {
    private static readonly string[] replies = {
      "いいです。",
      "わしもですか?",
      "みんなもですか?",
      "わしがですか?"
    };
    private Random random = new Random();

    /// <summary>
    /// POST: api/Messages
    /// Receive a message from a user and reply to it
    /// </summary>
    public async Task<Message> Post([FromBody]Message message) {
      if (message.Type == "Message") {
        string reply = replies[this.random.Next(replies.Length)];

        // return our reply to the user
        return message.CreateReplyMessage(reply);
      } else {
        return HandleSystemMessage(message);
      }
    }

ビルド

このままプロジェクトをビルドします。 実は、このソースだと「Postメソッドについているasyncの意味が無いぞ」という趣旨の警告をC#コンパイラが出します。 通常、Postメソッドの中では色々仕事をするだろうから、きっと非同期メソッドを呼び出すことだろう、 ということでテンプレートは非同期スタイルでPostメソッドを生成してます。 しかし、現状の内容だと同期的な処理しかしていないので無意味なわけですね。

でもまあ、実害はないので無視しましょう。 asyncを取り除くとそれはそれで同期スタイルに直さなければならなくて手間だし。

デバッグ実行

で、これをデバッグ実行すると、 ブラウザ上にスタートページが表示されます。

スタートページ

このページを開いている間、 Botサービスは動いており、 ページを閉じるとBotサービスのデバッグ実行が終了する、 だったと思うんだけど、 ページ閉じてもデバッグセッションが終了しないな。 ASP.NETのデバッグってそういう動きだったっけ?

まあともかく、 Botサービスを起動している間に、 その動作を試します。 それには、 Bot Framework Emulatorを使うと便利です。

Bot Framework Emulatorは 説明ページのリンクからインストールできます。 なんと、最近ほとんど見ないClickOnceアプリケーションですよ。

Bot Framework Emulatorを使うと、 こんな感じでBotの動きをチェックすることができます。 Bot Framework Emulator側で入力を与えつつ、 Visual Studio側でデバッグを行うことができるわけです。

Bot Framework Emulator

Bot Framework Emulatorを正しくBotに接続させるためには、 Emulatorの上部の帯にある"URL", "App Id", "App Secret"を正しく指定しなければなりません。

"URL"はBotを動かしているアドレスです。 先ほど開いたスタートアドレスのページのアドレスバーを見れば見当が付くでしょう。 注意点としては、BotのAPIのパスは(テンプレートそのままだと)サイトのルートではなく、"/api/messages"になるところですかね。

"App Id", "App Secret"によってBotはクライアントからの接続を認可します。 この値はプロジェクト中のWeb.configで設定されています。

現時点では、 テンプレートから生成された仮の値が入っています。 BotをBot Connectorに登録する際には、 ちゃんとした値を入れることになるでしょう。

スタートページ

次回、BotをBot Connectorに登録し、Slackから利用可能にします。