Docker: busybox のイメージサイズはなぜ小さい

まあ、このあたりは初心者なので新しい発見が多いわけですが…

この前も使った busybox ですが、サイズがやたらと小さいことに気づきました。

$ docker images
 REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
 busybox       latest    c55b0f125dc6   11 hours ago   1.24MB

えっ、busybox って一通りの基本コマンドが揃っていたような、と思ったわけです。普通 /bin とかこのサイズで収まらないでしょう、と。で、調べてみるとそもそも busybox って十徳ナイフのようなコマンドとして組み込み用に存在していてそれを Docker 用イメージにしたのですね。

Linux の man ページには以下のようにあります。

NAME
        BusyBox - The Swiss Army Knife of Embedded Linux

つまり、複数のコマンドを一つの実行ファイルにし共有できるところを共有・最適化することによりこのサイズを実現しているわけです。そして起動時にどのような名前で呼ばれたかによって動作を変えると。

試しに busybox を起動して中身を確認してみます。

$ docker run -i -t busybox:latest
/ # ls -li /bin
total 449684
  84754 -rwxr-xr-x  400 root     root       1149184 May  3 21:57 [
  84754 -rwxr-xr-x  400 root     root       1149184 May  3 21:57 [[
  84754 -rwxr-xr-x  400 root     root       1149184 May  3 21:57 acpid
  84754 -rwxr-xr-x  400 root     root       1149184 May  3 21:57 add-shell
  84754 -rwxr-xr-x  400 root     root       1149184 May  3 21:57 addgroup
  84754 -rwxr-xr-x  400 root     root       1149184 May  3 21:57 adduser
  84754 -rwxr-xr-x  400 root     root       1149184 May  3 21:57 adjtimex
  84754 -rwxr-xr-x  400 root     root       1149184 May  3 21:57 ar
(...省略)

ls に ‘-i’ オプションをつけて inode 番号を表示するようにして /bin の中身を見ました。上の例で一番最初の数字が inode 番号ですが、これはファイルシステム上のどのファイル実体を指しているかを表しています。このように 400 の実行ファイルの inode 番号が同じに表示され (注)、これらの実行コマンドファイルの実体が同じものであることがわかります。ちなみにこの 400 という数はオーナー (root) の前に表示されているリンク数 (400) からもわかりますね。

busybox のサイズの小ささと共に 400 もの機能をひとまとめにしていることに感嘆するわけです。

(注: /bin の中で getconf だけ別の inode 番号を持っていました)

参考: https://busybox.net/

WSL 2 複数インスタンス同一 IP アドレス

WSL 2 で複数の distribution (ここではこれを WSL の「インスタンス」と呼ぶことにします) を導入して同時に起動すると同じ IP アドレスを使うのです。ちょっと直感に反していたのでまとめておきます。

まず前提として WSL の複数インスタンスを使うという話ですが、wsl.exe の export/import 機能を使えば同じバージョン Ubuntu でも複数のインスタンスを作成できます。ここでは元々の名前の Ubuntu というインスタンスとそれを export/import して作った Hetarena というインスタンスがあるものとして説明します。

その 2つ、Ubuntu と Hetarena を同時に起動して ifconfig で IP アドレスを確認すると、あら不思議、同じ IP アドレスを持っています。さらに Ubuntu で Apache を起動して Hetarena で netstat で listening しているポートを確認すると、なんと 80/TCP をリッスンしているではないですか!

さらにさらに Ubuntu で mysql を起動して Hetarena から以下のコマンドを打ってみると何と接続できて Ubuntu のデータベースの内容を確認することができます。

mysql -u myid -D mydb -h 127.0.0.1 -p

ちなみにホスト指定を ‘-h localhost’ とすると Unix ソケット経由の接続を試みこれはエラーとなります。ファイルシステムは明らかにインスタンス毎に独立しているし、ps コマンドを打ってみても他方のプロセスが見えるということはなさそうです。

ググってみると関連した issue が見つかり、そこで関係者により以下のように説明されていました。

All of the WSL 2 distros run on the same virtual machine, which has a singular virtualized networking interface controller.

https://github.com/microsoft/WSL/issues/4304

「WSL 2 の複数ディストロは同一 VM 上で動作する」って訳してもチンプンカンプンになりそうですが、面白い実装ですね。

Docker で WSL 2 エンジン有効化後、既存 Hyper-V ボリュームアクセス不可問題

まあ、当たり前と言えば当たり前なんですけどね。私は Docker に関して一般ユーザーなので、 ‘Use the WSL 2 based engine’ を有効化したとたんにこれまで使用できたボリュームにアクセスできなくなって焦りました。そんなときどうするかという話です。今更という感じの話題かも知れませんが…。

シナリオとしては以下の通りです。

  1. これまで Docker Desktop for Windows を Hyper-V backend で使用してきた。
  2. メリットが多いというので WSL 2 backend に切り替えた。
  3. 切り替えた後は既存ボリュームにアクセスできない!

さて、この時どうするかなのですが、まず焦らず もう一度 Hyper-V backend に戻します。backend を切り替えるだけでは Hyper-V 上の Docker サービス用 VM が削除されたりするわけではないので Docker Desktop で設定を元に戻せばこれまでの image や volume がまた使用できるようになります。

続いて volume の内容をエクスポートします。以下のように busybox を使用して Windows のファイルシステムと Docker ボリュームをマウントした後、ボリュームの内容を tar.gz ファイル on Windows ファイルシステムとしてエクスポートします。

(ボリュームを確認)
C:\>docker volume ls
 DRIVER    VOLUME NAME
 local     myvolume
(ボリュームをエクスポート)
C:\>docker run -v myvolume:/src -v C:\Temp:/dest -i -t busybox
 / # tar -zcvf /dest/volume-backup.tgz src
 / # exit

C:\>

あとは WSL 2 backend に切り替え新規ボリュームを作成してから .tgz を戻せばよいです。私の場合は WSL の Linux ファイルシステム上に適当に展開して ‘-v /home/blogger323/dockervol:/mnt’ のように bind mount するようにしました。

ちなみにですが、WSL 2 backend に切り替えた後のボリュームは以下のパスで Windows からアクセス可能です。

\\wsl$\docker-desktop-data\version-pack-data\community\docker\volumes

参考情報:

Migrating existing containers from Hyper-V to WSL2 technology

追記: リソース消費量を抑えるには (2021.5.2)

WSL 2 を Docker エンジンとして選択すると、Docker 用の WSL distribution として以下のように docker-desktop、docker-desktop-data の 2つが新たに作成されます。

C:\>wsl.exe --list -v
  NAME                   STATE           VERSION
* Ubuntu                 Running         2
  docker-desktop         Running         2
  docker-desktop-data    Running         2 

上のリストで Ubuntu は元から使っていた distribution ですが、WSL integration の設定でこの Ubuntu と Docker を統合すると Docker を使っているときはこれら 3つの WSL 環境が起動することになります。本文では WSL integration の設定を行う想定で bind mount するとしましたが、WSL 用メモリの使用量は多くなりがち (参考)なので統合せず Docker volume を作ることで起動する WSL 環境を docker 関連の 2つのみにするという選択肢もありだと思います。

その場合も、本文最後に書いたパスを用いて Windows から直接 volume 内のファイルにアクセスすることが可能です。

更に追記 (2021.5.15):
よく考えると Docker Desktop を使わずに WSL で Linux 版 Docker を動かせばよいような気がしてきました。

WSL 2 で Windows から Linux マシンをどう参照するか問題

WSL 2 に mysql や apache を入れて Windows のプログラムから接続したくなることがあります。さてどうしましょうか。

build 18950 以上であれば localhost 指定で OK

Windows 10 build 18950 以上であれば Windows のループバックアドレス (localhost) のポートから自動的に Linux マシンにポートフォワードしてくれます。ですので Linux で Apache を動かして Windows のブラウザから http://localhost/ と指定してアクセスすることができます。

参考記事: https://www.atmarkit.co.jp/ait/articles/1909/09/news020.html

生のアドレスでアクセスしたい時もある

ただ、Web アプリ関連でリダイレクト等が絡むと localhost を使った URL では動かないケースがあるようです。私もそのあたりが原因でハマりかけたので開発時は Linux マシンのアドレスを使ってアクセスしています。ここで困るのが Linux マシンの IP アドレスを固定できないことです。調べた限りでは方法がなさそうです。

そこで策として考えられるのが、Windows の hosts ファイルを Linux マシン起動後に更新してホスト名を固定する方法です。世の中にはこれを Windows サービス化された方がいらっしゃいます。

https://github.com/shayne/go-wsl2-host

私の場合はこれだけのためにサービスを増やすのも大ごとのように感じてしまい、以下のような簡単なスクリプトを作って WSL 起動後に Windows 管理者権限で実行しています。元々 hosts ファイルはいじっておらず空のままだったので完全に置き換える動作にしていますが、ちょっと変えれば静的レコード+動的レコードみたいな使い方もできると思います。ご参考まで。

Linux 側 IP アドレス表示スクリプト

$ cat /usr/local/bin/genhosts
#!/bin/sh
IP_ADDR=hostname -I
while read -r line; do
  echo $IP_ADDR $line
done < /usr/local/etc/wslhosts

Windows 側から参照したいホスト名を記述するファイル

hetarena.com 開発環境の例ですw

$ cat /usr/local/etc/wslhosts
hetarena-dev.com
en.hetarena-dev.com
ura.hetarena-dev.com

Windows 側スクリプトファイル

以下の内容の .cmd ファイルを作って WSL 起動後に管理者権限で実行します。

wsl.exe genhosts > C:\Windows\System32\drivers\etc\hosts 

すると以下のような hosts ファイルが生成されます。

172.27.43.123 hetarena-dev.com
172.27.43.123 en.hetarena-dev.com
172.27.43.123 ura.hetarena-dev.com

これで Windows ブラウザから http://hetarena-dev.com を参照したりすることができます。

その他

  • WSL 2 のファイルシステムを参照したいときは ‘\\WSL$\’ を Explorer から開けばよいですね。
  • 逆に Linux から Windows を参照する場合は “ホスト名.mshome.net” というホスト名が使用できます。

関連情報: WSL2 Set static ip? 
https://github.com/microsoft/WSL/issues/4210

Microsoft SPLA と仮想化について

サービスプロバイダーライセンス (=SPLA) と仮想化環境と組み合わせたときに必要なプロセッサライセンス数を Microsoft に確認する機会があったので、覚書としてまとめておきます。 Microsoft の日本語ページを見てもさっぱりわからないので多少は役に立つでしょう。

今回の記事は Windows Server のプロセッサライセンスと SQL Server のコアライセンスについてです。 ユーザー数に応じた従量課金のサブスクライバーライセンスというのもありますが、サービス提供者からするとプロセッサ/コアライセンスの方が扱いやすいと思います。

ライセンス体系はバージョンによって変更する可能性があるので、最終的にはこの記事を鵜呑みにせずご自身で確認することをお勧めします。 Microsoft パートナーコールセンターに問い合わせると丁寧に教えてもらえます。

プロセッサライセンス

ちょっと前は Server 2008 R2 Enterprise のプロセッサライセンスというものが存在していてその上なら仮想インスタンス (仮想マシン = VM) をいくつまで動かせます、というのがありました。 しかし、現行の Server 2012 版ではこの Enterprise がなくなって Standard か Datacenter かという選択になります。 ライセンス上は Server 2012 ですが、ダウングレードして Server 2008 R2 を使用することができます。 面倒な手続きはなく、後述のプロダクトキーの発行時に 2008 R2 を指定するだけです。

Datacenter を買えば 1物理プロセッサ上であれば VM 数は無制限なのですっきりします。 問題は Standard の場合の考え方です。

今回の例として図のような VMware vSphere HA を使った構成を考えます。 2プロセッサ/台の物理サーバーを 2台使っています。 VM の数は 3つで正常時は 2つの物理サーバーに分散されて配置されます。 白が現在稼動している VM で、破線はフェイルオーバーしたときに動く可能性がある位置を示しています。

VMs

この場合、各物理サーバーで最大 3VM が動くことになります。 各々の物理サーバーで必要なライセンス数はこの最大値である 3VM で数えなければならないとのことでした。 すると 3VM × 2プロセッサで 6 Standard ライセンスが各々のサーバーに必要となります。 従って全体で必要なのは 3VM × 2プロセッサ × 2台で 12 Standard ライセンスとなります。

この構成で 12 なのかあ、という感じですが、SPLA ライセンスは想像よりも安価だったことは付け加えておきます。

ちなみに 6VM/物理サーバーを超えると Datacenter の方がお得になります。 これは Microsoft 説明資料 (英語 PDF)の p.16 にも説明されています。 最初は Standard で始めて後から Datacenter にアップグレードすることも可能とのことでした。 まあ、月額で課金なのでそれができるという話もあります。

英語ならばこの他にもサービスプロバイダー向け資料が整っているので興味があれば見ておくと良いと思います。

SQL Server

Windows Server はプロセッサ数がカウントの対象でしたが、SQL Server の方はコアライセンスとなっていて、CPU のコア数が問題になってきます。 そして仮想環境では SQL Server が稼動する VM に割り当てられている仮想コア数分の Core ライセンスを購入すればよいとのことでした。 ただし、最低が 4コアなので、2コアしか使わなくても 4コア分のライセンスを購入する必要があります。

こちらも HA だと 2倍かと思いきや、Active – Stanby 構成であれば稼動している VM のコア数でよいとのことです。 後から見つけましたが、英語の資料 (PDF) にも書かれています。

キーの発行

プロダクトキーの発行はライセンス認証窓口で行います。 SPLA という案内はないのですが、音声案内でボリュームライセンスの発行を選ぶと受け付けてもらえます。 SPLA 契約番号が必要です。 ちなみに SQL Server の方はプロダクトキーは不要です。

Windows Server 用プロダクトキーに関しては KMS キーと MAK キーの選択が必要です。 私はこの区別がわかっていなくて説明をしてもらう必要がありました。 KMS が使えるのは KMS クライアント 5台 + KMS ホスト 1台 = 計 6台の Windows Server 構成からなので、5台までは MAK キーでの発行となります。 複数の VM に導入する場合も、1つの MAK キーの発行でオッケーとのことでした。


2013.7.11 追記

図と説明で数が合っていなかったので訂正しました。

PowerShell の学び方

Windows の管理用スクリプトは VBScript から PowerShell スクリプトの時代に変わっています。 PowerShell で書くスクリプトについてなかなか馴染めませんでしたが、最近ようやっとその理由がわかったので、同じような境遇の方へのヒントとなるようにまとめてみました。

PowerShell はコマンドレットの実行環境

まず私の犯した大きな間違いは PowerShell を VBScript のようにプログラミング言語と捉えてしまったことです。 VBScript の置き換えでこれまで通り各オブジェクトを操作するのだろうと考えてしまいました。

しかし、そう捉えてしまうのは誤りです。 そうではなくコマンドレットの実行環境と捉えるのが正しいです。 PowerShell はその名の通り、perl よりも sh の立場なのです。

そう捉えればスクリプトセンターのラーニング領域から探し出せるリファレンスっぽいものが「Windows PowerShell Quick Reference」とかいうたった 2ページのチープなガイドのみなのも納得できます。 Unix で sh の文法だけでなく各コマンドを知っていることも重要なように、「コマンドレット」の使い方を知っていないとまずいのです。 私は、スクリプトセンターで PowerShell の情報を探すよりもどのようなコマンドレットがあってそれぞれ何があるかを把握すべきだったのです。 コマンドレットのリファレンスはこちらにあります。

実行時に注意すること

先のリファレンスと同じサイトで提供されている「Getting Started」もざっと目を通しておくのがよいと思います。 特に気をつけねばならないのは必要なモジュールをインポートしないと目的のコマンドレットを使えないことがあるというところです。

例えば Active Directory を操作するスクリプトを書く場合は以下の一文が必要となるでしょう。

Import-Module ActiveDirectory

オブジェクトの操作

先の Quick Reference にも書いてありますが、.Net Framework のオブジェクトは [] で括ってつかいます。 static なメソッドはそのまま呼べますね。

$tmpText = [system.io.path]::GetTempFileName()

また PowerShell では .NET Framework クラスの名前空間は system になっているので、’system.’ を省略することもできます。

$tmpText = [io.path]::GetTempFileName()

オブジェクト生成であれば New-Object コマンドレットを使います。 以下は COM オブジェクトの例ですが、.NET Framework クラスであれば -TypeName パラメータを指定します。 詳しくはNew-Object のリファレンス参照ということで。

$ie = New-Object -COMObject InternetExplorer.Application
$ie.Navigate2("www.microsoft.com")
$ie.Visible = $true

いかがでしょう。 これでだいぶ PowerShell が身近になったのではないでしょうか? 特に管理用スクリプトはサンプルのコピペ実行では危険で、内容をきちんと理解し、修正できなければなりません。 結局は自分で手を動かして覚えていくしかないのですが、オブジェクトのリファレンスの他にコマンドレットのリファレンスを参照できるようになればかなり楽になると思います。

PHP for Windows でイベントログを出力する

Windows 版の PHP を使うことがあり、アプリケーションからイベントログに出力するのに手こずったので、ポイントをメモ書きしておきます。 環境は IIS 7.5 (Windows Server 2008 R2) と PHP 5.4 です。

インストール

インストールについても簡単に触れておきます。 Microsoft より PHP on IIS というページで PHP を Windows 上で動かすための情報が公開されています。 この中に「PHP on Windows ガイドライン」が提供されているのでこれに従って進めれば PHP が稼働する IIS サイトを構築することができます。

それなりのボリュームになっていますが、メインはインストール関連の第2章とベストプラクティスの第5章です。 FastCGI と Non Thread Safe 版 PHP の組み合わせというのがポイントです。 5章の「PHP 実行プロセスのリサイクル設定」はちゃんとやっておきましょう。

実行権限

さて、本題に入って行きます。 Windows 版 PHP の syslog 関数の出力先はイベントログになっていますが、そのままでは IIS 上の PHP アプリケーションからは出力できませんでした。 以下のパラメータが php.ini で指定されていると IIS 上の PHP は仮想ユーザーの権限で実行されます。

fastcgi.impersonate=1

先のガイドラインには上のように 1に設定するよう書かれていますが、これを 0に設定してアプリケーションプールにイベントログ出力可能なユーザーを割り当てるのも一つの方法です。 しかし、今回は fastcgi.impersonate=1のまま仮想ユーザーにイベントログ出力の権限を与えることにしました。

「仮想」ユーザーなので実体となるユーザーはないのですが、代わりに相当するグループ IIS-IUSR にイベントログ出力権限を与えます。 この方法も結構面倒なのですが、詳細は Microsoft の Technet に書かれているのでここでは簡単に触れるにとどめます。 リンク先の手順を参考にして IIS-IUSR (S-1-5-17) に 0x3 (読み取り+書き込み) を設定します。

まず以下のコマンドで現在の設定が出力されるので、これを保存しておきます。 ファイルにリダイレクトすると良いでしょう。

wevtutil.exe gl application /f:xml

続いて権限設定変更のコマンドを入力します。 これで IIS-IUSR グループにもイベントログを出力する権限が追加されます。

wevtutil.exe sl application /ca:O:BAG:SYD:(A;;0xf0007;;;SY)(A;;0x7;;;BA)(A;;0x7;;;SO)(A;;0x3;;;IU)(A;;0x3;;;SU)(A;;0x3;;;S-1-5-3)(A;;0x3;;;S-1-5-33)(A;;0x1;;;S-1-5-32-573)(A;;0x3;;;S-1-5-17)

ここまでで以下のようなコードを使ってイベントログを出力できるようになります。

  openlog("My Message", LOG_PID, LOG_USER);
  syslog(LOG_INFO, "Hello, World");
  closelog();

「説明が見つかりません」エラーをなくす

これでイベントログには出力されるようになりましたが、イベントビューアーで確認したときに説明欄に以下のようなメッセージが表示されてしまいます。 ちなみに ID 2 は LOG_INFO を指定した場合で、priority を変えると変化します。

ソース “PHP-5.4.8” からのイベント ID 2 の説明が見つかりません。このイベントを発生させるコンポーネントがローカル コンピューターにインストールされていないか、インストールが壊れています。ローカル コンピューターにコンポーネントをインストールするか、コンポーネントを修復してください。

これを避けるためにはレジストリエディターで以下のように EventMessageFile と TypesSupported というキーを作成します。 この例では PHP 5.4.8 を想定しています。

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\Application\PHP-5.4.8]
"EventMessageFile"=hex(2):43,00,3a,00,5c,00,70,00,68,00,70,00,35,00,5c,00,70,\
  00,68,00,70,00,35,00,2e,00,64,00,6c,00,6c,00,00,00
"TypesSupported"=dword:00000007

EventMessageFile は php5.dll のフルパスを示す REG_EXPAND_SZ (展開可能な文字列値) です。 上の例では C:\php5\php5.dll になっているのですが、適宜変更して設定します。 TypesSupported は REG_DWORD の 7です。 これはサポートされているタイプを表すフラグですが、詳しくはMicrosoft のリファレンスを参照してください。

これで「説明が見つかりません」エラーが消えると思います。

イベントビューアー上で PHP のログを確認しやすくする

イベントビューアーを使ってログを確認する時に、PHP のログのみ拾うためのカスタムビューを作っておくと便利です。 以下のようにイベントソースに PHP-5.4.8 のような PHP バージョン文字列を設定します。 イベントソースはカンマ区切りで複数設定できます。 これを設定すると左のツリーの「カスタムビュー」の下から簡単に保存したビューが選べるようになり便利です。

カスタムビューの設定

Linux のログイン認証に Active Directory を使う

Linux の認証に Active Directory を使うよう設定することがありました。 備忘録としてまとめておきます。

何ができるようになるのか

今回は WinBind という Samba のコンポーネントを使って Linux と Active Directory を連携させます。 これを使用すると Linux 上のユーザー/グループ管理に Active Directory を用いることができるようになります。 具体的には以下のことができるようになります。

  • Active Directory に登録されたアカウントとグループを使って Linux にログインすることができるようになります。
  • 事前に個々のユーザーを各 Linux サーバーへ登録する必要はありません。 /etc/passwd や /etc/groups は全くいじりません。 また、ホームディレクトリは sshd 等で最初にログオンしたときに自動生成されます。
  • Active Directory の RID をそのまま uid/gid として用います。 これにより、複数の Linux サーバー上でも一意の uid/gid を使ってユーザー/グループを識別することができます。
  • passwd コマンドを使って Active Directory に登録されているパスワードを変更できます。

uid/gid の扱いについて補足します。 Active Directory 上のユーザー/グループを Linux 上の uid/gid にマップさせる方法はいくつか用意されていますが、今回は Active Directory の RID (SID のドメイン内相対識別部分) を用いる方法を採用します。 idmap_rid と呼ばれる方法です。 ただし、マルチドメイン環境では RID は一意にならないため、シングルドメイン環境での運用が前提となります。 マップ方法にはその他にも tdb (テーブルによるマッピング。デフォルトの方法) や ad (AD 上のユーザー属性を読む。いちいち属性を設定しなければならず管理が面倒) 等があります。 信頼関係を構築していたりマルチドメイン環境ではこれらが必要となりますので興味があれば調べてみてください。

設定方法

設定方法については実は Microsoft の「Active Directory を使用して Linux クライアントを認証する」という記事に詳しく解説されています。 ビルドの部分は飛ばして良いので、まずこれを読んでいただければと思います。 ここではこの記事を補足のみ書きます。

DNS 関連

DNS は Windows ドメインの名前が引けるように /etc/resolv.conf を設定しなければなりません。 一番簡単なのは DNS として Windows のドメインコントローラーをしてしまうことでしょうが、環境によっては DNS サーバーの構成を見直す必要が出てくるかもしれませんね。 また、ホスト名はきちんと設定しておきましょう。 「localhost」という名前のコンピューターが AD に登録されてしまった、などということのないように…。

ホームディレクトリの自動作成

先に紹介した Microsoft の記事中 /etc/pam.d/system-auth の pam_mkhomedir の umask の指定はちょっと怪しい感じがします。 例えば自分のみアクセス可能 (700) なホームディレクトリを作成するには以下のようにします。

session     optional      pam_mkhomedir.so skel=/etc/skel umask=0077

krb5.conf の設定

system-config-authentication を実行した後は krb5.conf で kdc = * となってしまうと思いますが、このままではまずいようです。 以下のようにドメイン名を指定します。

[realms]
 EXAMPLE_DOMAIN.LOCAL = {
  kdc = example.local
 }

Windows の DNS にはドメイン名の A レコードも用意されており、ドメインコントローラーのホスト名を使うよりもこの例のようにドメイン名を使った方が可用性が高くなります。 (マニュアルを見るとこのケースは設定がなくても動作しそうですが、未検証です)

端末エミュレータ上で動作する設定ツール

先の記事では system-config-authentication が使用されていますが、X が利用できない場合、authconfig-tui や authconfig コマンドを利用することができます。 下は authconfig-tui の画面です。

authconfig-tui

ID マップについて

ID のマップについてもう少し詳しく説明します。 Windows の RID とは SID の一部でそのドメインの中で一意となるオブジェクトの識別子です。 Windows で通常発行される RID は 500 以降なのでそれをそのまま uid/gid 使います。 以下は SID の例ですが、このうちの最後の 500 が RID となります。 RID はユーザー/グループ等のオブジェクトが作成されるたびに連番で割り当てられていきます。

S-1-5-21-917267712-1342860078-1792151419-500

以下は 500 以上の RID についてそのまま uid/gid としてマップするための smb.conf の設定です。

idmap domains = EXAMPLE_DOMAIN        (samba 3.3 以降はこの行は削除)
idmap config EXAMPLE_DOMAIN:backend   = rid
idmap config EXAMPLE_DOMAIN:base_rid  = 500
idmap config EXAMPLE_DOMAIN:range     = 500 - 10000

今回はこの RID をそのまま uid/gid として使いますが、もちろん Linux のローカルユーザー/グループと衝突しないようにしなければなりません。 すなわち 500 以上の uid/gid は Linux システム上に存在していないという前提です。 もし、Linux 上のローカルアカウントで 500 以上の uid/gid も使うのであれば range をうまく調整する必要があります。 「Administrator (= 500) のマップなど不要!」というケースは多いかも知れませんが、ログイン時に所属グループがきちんと gid にマップできないとログインできないので、’Domain Users’ (= 513) がマップできないと恐らく困ると思います。

うまく行けば id コマンドで以下のようにユーザー情報を取得できるようになるはずです。 AD 上に RID = 1110 で ad_user というアカウントが登録されている想定です。

$ id ad_user
uid=1110(ad_user) gid=513(domain users) 所属グループ=513(domain users) context=user_u:system_r:unconfined_t

ちょっと考えればわかりますが、そのままでは AD ユーザー全員がログインできるようになってしまいます。 アクセス制御は Windows のグループを用い、認証を行う各サービスで適切に行わなければなりません。 例えば ssh ログインを制限するのであれば /etc/ssh/sshd_config に AllowGroups の設定を入れます。 あるいは pam_winbind のオプションに require_membership_of というパラメータがあるので、これを使ってそもそもの連携するグループを絞ってしまっても良いかもしれません。(ただし動作未検証)

ちなみに smb.conf の設定ではネストされたグループの扱いのためのフラグもあります。 デフォルト値は Yes です。

winbind nested groups = Yes

Linux と Windows の混在環境では、このように Active Directory を活用することができます。 一発でうまく設定できないかも知れませんが、ハマった時は一時的に tdb を利用して問題を切り分けしてみると良いと思います。

Windows ファイルサーバーと Git

「Windows 環境に居ると Git を使いたくてもサーバーが無いし…」なんて思ってませんか? Windows の共有フォルダの環境でもちゃんと Git は動きます。 Windows サーバー上に使用可能な共有フォルダーがあればそれで十分使い始めることができます。 サーバー上でサービスやプログラム等を動かす必要はありません。 さっそく始めてみましょう。

Git for Windows を選択しよう

最近の状況だと、Windows で使用する Git と言えば msysGit なのですが、初心者には落とし穴があります。 msysGit の公式ページを見ると、「Git for Windows」と「msysGit」という 2つの配布パッケージがあります。 英語の説明なのでちゃんと見ない人もいるかも知れませんが (?)、一般ユーザー向けは「Git for Windows」と書かれた方なので、「Git for Windows」をダウンロードして使いましょう。 実際のところ、これまでに書かれているほとんどの記事で msysGit と説明されているものは「Git for Windows」のことを指していますが、公式ページ上で「msysGit」と説明されているものは、Git をハックしたい人向けのパッケージなので注意しましょう。

今回は家庭用 NAS を導入して個人で Git を使うために私のやったことをまとめていますが、パーミッション設定をきちんと行えば仕事で使う Windows サーバー上に複数人が使用する Git リポジトリを置くことは可能だと思います。

共有フォルダの参照の仕方

Git for Windows のインストールは簡単です。 デフォルト値の通り、PATH の設定は「Use Git Bash only」、改行コードについては「Checkout Windows-style, commit Unix-style line endings」を選んでおけばよいでしょう。 それと怒られる前にメールアドレスと名前を設定しておきます。

git config --global user.email "youraddress@example.com"
git config --global user.name "Your Name"

ここまで出来てしまえば、後は共有フォルダを以下の形式で参照してベアリポジトリを作るだけです。

//servername/folder/sub_folder/repository

コマンドラインなら以下のようになります。

ローカルのリポジトリを共有フォルダにおく:
$ git clone --bare myproj //server/disk/git/myproj.git

サーバ上に新たにリポジトリを作成:
$ git init --bare //server/disk/git/myproj.git

Git for Windows の GUI

Git for Windows の GUI もそれなりに使えるので、私は結構愛用しています。 リポジトリの複製では、「//server/folder」形式の文字列がローカルと判定されてしまうので、明示的に「全複写」を選んでおくと警告を避けることができます。 (以下、サーバ名は「dragon」です)

ちなみにコマンドラインを使っている分には git clone で特に警告やエラーとならないので、—-no-hardlinks オプションをつけたりする必要はなさそうです。

GUI を使って差分確認すると、改行コードの差は無視 (diff でいう —-strip-trailing-cr オプション) してくれるので手元に CRLF のファイルと LF のみのファイルが入り交じっていても何とかなりますし、エンコーディング指定で SJIS や EUC のファイルも差分確認できるので、特に外部コマンドを設定しなくてもテキストファイルの確認には十分な気がします。

ただし、リポジトリ履歴確認画面 (gitk) では、エンコーディングの指定ができないようです。  gitk でエンコーディングを指定する方法はこちら。

おまけ

本題とはずれますが、関連して実行した作業を簡単にまとめておきます。

CVS からの移行

私は Subversion をスキップして Git 環境に来たので、CVS リポジトリからのインポートが必要でした。 まずは必要なパッケージをインストールします。

# yum install git-cvs

以下のコマンドでカレントディレクトリの下に CVS のモジュール 1つ分の Git リポジトリ (module.git) を作成します。 CVS モジュールごとに実行しなければなりません。

$ git cvsimport -v -d /usr/local/cvsroot -C module.git modulename

まあ、今どきこの情報を必要としている人はいないかも知れませんが。

Windows 共有フォルダを Linux でも参照する

私の環境では I-O DATA の HDL2-A4.0 がファイルサーバーです。 これは Windows と AppleShare にしか対応していないのですが、Linux マシンからもマウントして使いたいので、/etc/fstab に以下のエントリを作成しました。

//dragon/disk    /mnt/dragon    cifs    password=,noauto    0 0

とりあえず今は買って来たままのパスワードなしの状態で使っています。 起動時の自動マウントはしないように noauto を付けていますが、NAS が 24時間稼働であればこれを外しても良いでしょう。 このように fstab に書いておけば mount コマンド実行が楽になります。

# mount /mnt/dragon

Active Directory 環境の確認手順

Active Directory (AD) の環境を調査するときにどこを見ればよいかの覚書です。 何も把握できていないのに既に導入業者と没交渉、という感じのお客様環境を調べる時に使えます! Windows Server 2003/2008 のドメインコントローラ上で調べることを想定していますが、2003 の場合 Support Tools を必要とする内容もあります。 Windows Server 2003 の時代に書いた (けど放置していた) ものを手直ししています。

フォレスト名、ドメイン名の確認

まず、そのコンピュータが属しているドメインは「コンピューター」のプロパティで確認できます。

関連するドメインを見たい場合は「ドメインと信頼関係」ツールを起動するとドメインが一覧表示されます。 フォレスト名は「ドメインと信頼関係」ツールでツリー最上階層 (「Active Directory ドメインと信頼関係」) のコンテキストメニューから選べる「フォレストの機能レベルをあげる(or 機能レベルの昇格)」の画面で確認できます。

ドメインコントローラの一覧

ドメインコントローラの一覧を得る方法として、まず考えられるのは「Active Directory ユーザとコンピューター」ツールで「Domain Controllers」OU 内の Computer オブジェクトを見ることです。 ここがドメインコントローラを格納する規定の位置です。 Computer オブジェクトのプロパティを確認すれば使用 OS 等の情報も得られます。

しかし、実際はディレクトリをカスタマイズして、これ以外の OU にドメインコントローラ (DC) オブジェクトを動かすこともできます。 その場合は、ディレクトリを検索しなければなりません。 先のリンクのように VB スクリプトを流す他、同じ内容を ldp.exe で検索するという手もあります。 ldp.exe でドメインコントローラのディレクトリサービス (ポート 389番) に対し bind 実行後、以下のように検索すると良いでしょう。(ドメイン名 example.com の場合)

Base Dn: CN=Configuration,DC=example,DC=com
Filter: (objectClass=nTDSDSA)
Scope: Subtree

いずれにせよ、DC オブジェクトが素直に「Domain Controllers」OU 内に無い環境では他にもいろいろなカスタマイズをしている可能性があるので、注意が必要であることに違いありません。 適切な人を見つけ出しヒアリングすることを検討する必要があるでしょう。

それと「Active Directory ユーザとコンピュータ」ツールは「表示」-「拡張機能」を有効にしておきましょう。 2008 だと LDAP 上の任意の属性が確認できるようになっていて便利です。

機能レベル

フォレストの機能レベルとドメインの機能レベルがありますが、それぞれ「ドメインと信頼関係」ツールの「フォレストの機能レベルをあげる」画面と「ドメインの機能レベルをあげる」画面で確認できます。

操作マスタ (FSMO)

各マスタによりどこを見るかが異なります。 同じ画面で操作マスタの転送もできます。

RID、PDC、インフラストラクチャ

「ユーザーとコンピュータ」ツールでドメインを選んで「操作マスタ」メニューを選択します。

ドメイン名前付け

「ドメインと信頼関係」ツールの最上階層を選択後、「操作マスタ」メニュー選択。 ドメイン名前付けマスタはフォレストに 1台です。

スキーマ

「スキーマ」ツールで行いますが、デフォルトではツールがメニューに登録されていないので、使用する前に登録が必要です。

  1. regsvr32 schmmgmt.dll を実行
  2. MMC を起動して「スナップインの追加と削除」「Active Directory スキーマ」を追加
  3. 簡単に呼び出せるように、「名前をつけて保存」で system32\schmmgmt.msc と保存し、これに対するショートカットを作っておく。

スキーマもフォレストレベルでの管理です。 ちなみに、スキーママスタの役割を転送をするにはフォレストルートドメインの Schema Admins グループに入っているユーザでないとダメです。

GC (グローバルカタログ)

「サイトとサービス」ツール内、サーバ配下にある「NTDS Setting」のプロパティの「全般」タブで「グローバルカタログ」にチェックが入っているかどうかを見ます。

ネットワークトポロジ関連

「サイトとサービス」ツールで確認します。 ここで重要なのは以下のような項目です。

  • サイト
  • サイトリンク
    通常「Inter-Site Transports」-「IP」の下のものが重要で「コスト」と「レプリケートの間隔」をチェックしておきます
  • サブネット
  • AD 接続オブジェクト (Connection)
    サーバ配下の「NTDS Settings」の下にあります。たいていは 「<自動生成>」 されています。

KCC (Knowledge Consistency Checker) が「Active Directory 接続」オブジェクトを作ります。 手動で作ることもできますが、後の管理を考えると自動作成に任せた方が良さそうです。 KCC をすぐ動作させたいときは以下のコマンドを実行します。

repadmin /kcc

「NTDS Settings」のコンテキストメニュー、「すべてのタスク」から「レプリケーショントポロジの確認」を実行します。 各サイトにサイト間トポロジジェネレータの役割を持つ DC が存在します。 これは dcdiag.exe で確認できます。

信頼関係

「ドメインと信頼関係」ツールで確認します。 ってこれは迷うこともないですね。

インストール時指定した項目関連

データベースとログ

とりあえず既定のデータベースファイルは以下の通りです。

C:\WINDOWS\NTDS\Ntds.dit

ログファイルも規定ではこのフォルダに作成されます。 領域が足りなくなってきたときは、後から Ntdsutil.exe で位置を変更することができます。 ただし、ディレクトリサービス復元モードでの起動が必要です。 (2008 ではサービス停止のみでオッケーとのこと)

実際の位置は以下のレジストリ値で確認できます。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters

DSA Database file (データベースファイルのフルパス名)
Database backup path (データベースバックアップファイルフルパス名)
Database log files path (ログ用フォルダ)

SYSVOL

SYSVOL の位置も以下のレジストリキーで確認できます。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters\SysVol

SYSVOL (SYSVOL フォルダのパス)

復元モードのパスワード

このパスワードは忘れたら確認のしようがないのですが、覚えていれば ntdutil.exe で変更することは可能です。

ネットワーク関連

DNS 関連

DNS 経験者が Windows の DNS サーバを扱う時に、最初わかりづらいのは AD 統合ゾーンだと思います。 AD 統合ゾーンを使えば Windows の複製機能でゾーン情報をサーバ間共有できるので、ゾーン転送の設定が不要になります。 ただし、AD 統合ゾーンはドメインコントローラ上で DNS サーバを動かす場合のみ使うことができます。

AD 統合ゾーンは同期されますが、それ以外のゾーンの内容やフォワーダの設定などはサーバごとに確認する必要があります。

DHCP 関連

Windows サーバ上で DHCP サーバを用いるときは、Active Directory で承認されていなければなりません。 この仕組みは DHCP のベンダー固有オプションを利用して実装されているようで、Windows 以外の DHCP サーバを利用するときは当てはまりません。

承認されたサーバーについては、DHCP 管理ツールで「DHCP」のコンテキストメニュー「承認されたサーバーの管理」から確認できる他、以下のコマンドを実行することで一覧表示することもできます。

netsh dhcp show server

まとめ

自分が Active Directory を触り始めたときにわかりにくかったことをまとめたものなので、これが全てと言うつもりはありませんが、それなりに役立つのではないかと思います。