creating NTFS native symbolic link in cygwin #2

以前 Cygwin でシンボリックリンクを作るにはどうすればいいか調査したことがあった

月日は流れ、ついに Windows 10 では(開発者モードに限り)特権のエスカレーションを経ることなく一般ユーザのままシンボリックリンクを作れるようになるそうな。

へえ。しかし個人的にはもうどうでもいいトピックだったりする。というのも一応 Cygwin は入れているが、もはや Windows 上で何か開発するということが殆どない。

ちなみにその更新がもたらされる Windows 10 Creators Update は、2017年3月にリリースの予定だそうな。

creating NTFS native symbolic link in cygwin

以前 cygwin 上で、Windows Vista 以降の NTFS ネイティブなシンボリックリンクを作るために逡巡したことがあって、一応できたのだが、それは諸々の環境を整えた上で最終的には [cci]cmd /c mklink[/cci] を呼ぶというものであった。

これだとメッセージが mklink のそれになってしまうし、コードページの不整合が起きる(つまり UTF-8 な端末で呼ぶとメッセージが文字化けする)というどうでもいいけどどうでもよくない不都合もある。それを置いても、やはり cygwin の中からコマンドプロンプトベースの実行ファイルを呼び出すのはなんともイケてない。なんとかならないか。

さて Windows 側のシステム環境変数 [cci]CYGWIN[/cci] に設定する値によって、cygwin の動作を制御することができるのだが(ドキュメント)、その中に winsymlinks という項目がある。これを [cci]nativestrict[/cci] という値にすることによって解決できた。ちなみにこの項目は [cci]lnk[/cci]、[cci]native[/cci]、[cci]nativestrict[/cci] の 3 つの値を割り当てることができるのだが、

  • lnk: シンボリックリンクとして Explorer が認識する .lnk ファイルを作成する
  • native: シンボリックリンクとして NTFS ネイティブなそれを作成する。作成が不可能な場合(NTFS じゃないとか、権限がないとか)は、lnk として振る舞う
  • nativestrict: native と同様に ネイティブなシンボリックリンクを作成するが、作成が不可能な場合はエラーを返す

というわけで、ナウい cygwin で NTFS ネイティブなシンボリックを作成するには

  1. Administrators グループに属する別のアカウントを作成する
  2. 普段使用するアカウントを Administrators グループから外し、Users に含めるようにする(これにより、UAC ダイアログでは単なる権限のエスカレーションの確認だけでなく、管理者アカウントのパスワードを入力を求められるようになるが、慣れるしかない)
  3. ローカルセキュリティポリシーを起動し、[cci]セキュリティの設定 -> ローカルポリシー -> ユーザー権利の割り当て[/cci] の中にある [cci]シンボリック リンクの作成[/cci] に普段使用するアカウント名を追加する
  4. システム環境変数 [cci]CYGWIN[/cci] に [cci]winsymlinks:nativestrict[/cci] を追加する

という手順になる。

PHP in cygwin

普段 Windows 上で作業しているといっても、実際は cygwin の端末の中でちくちくしているわけだ。

一方で、Windows 向けの PHP をインストールもしている。そうすると cygwin の中から PHP スクリプトを呼び出したくなる時もある。どうすればいいだろうか。

純 Windows 環境側の path 環境変数で、すでに php.exe にはパスを通してある。また cygwin は起動時にその path を継承するので、とりあえず cygwin 上で

$ php -f C:\path\to\scriptというのはできる。次に shebang を通して実行させたい。つまり #!/usr/bin/php と 1 行目に書いた php スクリプトを実行させたい。

うちの環境では、cygwin 上の php.exe の位置は [cci]/cygdrive/c/Program Files (x86)/php/current/php.exe[/cci] だ。そこでまず、コマンドプロンプトで > cd C:\cygwin\bin
> mklink php.exe "C:\Program Files (x86)\php\current\php.exe"
などとしてみた: 失敗。Windows では実行形式を指すシンボリックリンクを実行したとき、argv[0] が真の実行形式ファイルを差さないようだ。それはシンボリックファイルを指したままだ。だから、実行形式を指すシンボリックリンクを実行した場合、実行形式の存在するディレクトリを起点にして設定ファイルを読み込んだりする処理はことごとく失敗する。うちの環境の php の場合、php.exe の隣においてある php.ini が読み込まれない。

そういうわけで /usr/bin/php として

#!/bin/sh
exec "/cygdrive/c/Program Files (x86)/php/current/php.exe" "$@"

てな感じのシェルスクリプトを置くと動く。

また、php スクリプト側を

#!/usr/bin/env php


としてもいい。あんまりこの env のトリック好きじゃないけど、実質的にはいちばん楽かなー。

vim 7.4 and cygwin

vim 7.4 がリリースされた。たぶん Cygwin 版もすでに更新されてるんじゃないかなと思い、Cygwin のセットアップを公式へ取りに行った。

すると今まで単に setup.exe として提供されていたインストーラが x86 版と x64 版にわかれているじゃないか。あれ? そういえば Cygwin って 32bit アプリケーションだったっけ? とタスクマネージャを見ると確かに *32 が付いている。

x64 版への移行ってどうするんだろ?

 * * *

とりあえず x86 版のセットアップを動かしてみたら vim は 7.3 のままだった。がぼーん。

ということで、単に Cygwin だけを更新した。

ln -s #2

Windows Vista から NTFS にシンボリックリンク機能が追加されているけど、管理者権限でしか使えないから cygwin が対応してない云々というエントリを以前 書いた

実を言えば、ちょっとググれば、ローカルセキュリティポリシーエディタをたちあげて、「シンボリックリンクの作成」ポリシーに任意のアカウントを追加すれば使えるようになりますぞーというソリューションはすぐ出てくる。出てくるので、そのとおりにやったのだが…なぜか、やはり権限が足りねーよと cmd.exe に怒られるままなのである。謎だ。というのが 1 年前のことだ。

で、今何気なく再度ググってみたらこんなことが。つまり、上記ポリシーにアカウントを追加したとしても、そのアカウントが Administrators グループに入っている場合は別の機構が権限をフィルタリングしてしまい、結果、シンボリックの作成はやはりできないのだそうな。なに、それ。意味がわからない。

回避するには、次のいずれかを試す:

  1. UAC を完全に切る。もちろんおすすめできない。
  2. シンボリックリンクの作成権限を与えたいアカウント A を Administrators から外し、Users に含める。つまり管理ユーザから一般ユーザにする。もしローカルマシンにアカウントが A しかない場合は、先に別の管理ユーザを作成しておく必要がある。

というわけで 2. をやってみた。ほー一般ユーザにすると UAC のダイアログで管理ユーザのパスワードを求められるのか。なんか……原始的。sudo をパクればいいのに。

それにしても 1 年前はなんで見つからなかったのかなーあれだけググったのになー。

ちなみにだからといって、cygwin の ln -s が NTFS ネイティブなシンボリックリンクを作ってくれるようには、やはりならない。しかし ln -s として呼ばれたら /cygdrive/c/Windows/system32/cmd.exe /c “mklink <dst> <src>” 辺りを裏で呼び出すラッパを作れば対応できそうである。と思ったら、すでにそれっぽいのを作っている人がいた。あとで試してみる。

cygwin broke #3

Cygwin 版の Subversion がぶっこわれている件。
http://comments.gmane.org/gmane.os.cygwin/134334
によると、TortoiseSVN のアイコンキャッシュとの相性が悪いという。svn の実行形式そのものがアイコンキャッシュなんて知るよしもないはずだが、.svn 内の sqlite データベースファイルを TortoiseSVN 側が掴みっぱなしになってるとかそんな感じか。

キャッシュが問題なら、キャッシュを切ればいいのだろうと TortoseSVN 側で設定を変更した。キャッシュを切ってもアイコンオーバーレイ自体はそのままなのね。そのかわりキャッシュしない分多少更新に時間がかかるのか? それなら併せて、アイコンオーバーレイを施すドライブ、含めるパスなんかを設定してオーバーレイ範囲を限定すればまあ体感的なパフォーマンスはあまり変わらなくなるかな。

ということでそうした。いまのところコマンドラインからのコミットなんかも普通に行えているようだ。

というか Subversion って sqlite 使ってたの知らなかった。内部のデータベースって BerkleyDB とか fsfs とかじゃなかったっけ…?


$ file ~/Projects/wasavi/wasavi/.svn/wc.db
wc.db: SQLite 3.x database, user version 29

へー。

cygwin broke #2

Cygwin が壊れたせいなのか、アップグレードしたせいなのか、Subversion の調子もおかしくなった。エラーメッセージを見る限り、Subversion 内部で使っている sqlite に対して正しくクエリを投げられていないようだ。


$ ldd /usr/binsvn
(snip)
cygsqlite3-0.dll => /usr/bin/cygsqlite3-0.dll (0x6ead0000)

だそうなので、cygsqlite3-0.dll に何か問題がある?

Cygwin のインストーラは、各パッケージについて、直前の安定版をインストールすることもできる。現在インストールしてある。3.7.12.1-1 に代えて、3.7.3-1 に戻せばもしかしたら直るかもしれない。

しかしまあ、Cygwin の Subversion が使えなくても TortoiseSVN でなんとかなるのでこのまましばらく放置してしまうかもしれない。

cygwin broke!

Opera で Adobe のとあるページを見たら、Windows ごと固まってしまったのである。マウスポインタは動くが、表示されているものは単なる絵になってしまった。何も反応しない。Ctrl+Shift+Esc (タスクマネージャのショートカット) も効かず、Ctrl+Alt+Del も効かない。

しかたがないので電源落とした。

Opera のバグかは定かではない。今日はそもそも PC の調子が悪かった。スリープから起こした時点から妙に PC 全体が重かったのだ。まるで 128MB しかメモリがない PC がスワップしながらかろうじて動作しているみたいだった。Opera は単に不安定な状態に最後の止めを刺しただけなのかもしれない。

で、困ったのは Cygwin が起動しなくなってしまったことなのだ。なにやら cygreadline7.dll のベースアドレスが違うよ的エラーが出る。readline まわりが初期化できないだけっぽいので ash は起動することは起動するのだが、なんだか気持ち悪い。

Cygwin が正しく起動しなくなったとき、それを解決するのはコマンドプロンプトで /bin/rebaseall である。というかぐぐっても rebaseall 以外の解法が見つからない。そんなわけで、Cygwin 関連のプロセスをすべて落とした上で管理者権限のコマンドプロンプトで ash を起動して rebaseall したのだが、しかしなお Cygwin は起動しない。rebaseall -v してみても cygreadline7.dll はリベースされてないようなのでさもありなんという感じだ。

ということで割と困ってしまったのだが、Cygwin の setup.exe を起動してみたところ、libreadline パッケージが新しくなっているようなので単に Cygwin 自体をアップグレードしたらとりあえず ash 自体は起動するようになったようだ。ふーん。うーん?

教訓: Cygwin がぶっこわれて、rebaseall してもダメなときは、起動しない原因となっている dll を含むパッケージを再インストールしてみる

ln -s

何かアプリケーションを作っているときは、たいていブラウザとエディタとターミナルを行ったり来たりしている。もっともターミナルと言っても素のコマンドプロンプトが使いやすいとは言えない(ckw とか nyaos とか、あるいは PowerShell を極めればそうではないのかもしれない)ので実際は cygwin なのだが。

で、ほとんどの場合 cygwin で間に合うのだけど、唯一シンボリックリンクの作成だけが管理者権限で実行したコマンドプロンプトじゃないと行えない。現在の cygwin では NTFS ネイティブのシンボリックリンクにある程度は対応している。ls もリンクを追跡する。ただし「ネイティブなシンボリックリンクの」作成はできない。ln -s はあるが、それが作るシンボリックリンクは cygwin でしか認識されない独自形式なのだ。

なぜこうなっているのかと言えば、シンボリックリンクの作成はどういうわけか管理者権限が必要だからだ。そのため cygwin 側としては「作成もできるようにしたいけど管理者権限が不要になるまでペンディング」という状態らしい(とメーリングリストか何かで見た記憶があるのだが場所を失念した)。

この制限が早く取り除かれればいいなあと思う今日この頃。