home / uni / Cygwin Cygwin

 WindowsでUnixライクな環境を実現するパッケージ。元々Cygnusというところがやっていて、それをRed Hatがもらい受けた。現在もRed Hatだが、メインのページは Cygwin になっている。 Unixコマンドの使い方は他にもっと詳しいサイトがあると思うのでそちらを見ていただくことにして、ここでは主にCygwinに特徴的なことについて述べる。

※Cygwin 1.5からCygwin 1.7へのアップグレード (05 Jan 2010)
 Cygwin 1.5からCygwin 1.7になるときに、ファイルシステムのマウントまわりの仕様がかなり変更された。 マウントポイントはレジストリではなく、Uni*と同じように /etc/fstab に格納されるようになった。 ユーザーごとのマウントポイントは /etc/fstab.d/$USER に格納される。

 /etc/fstab はデフォルトでは空っぽだが、/・/usr/bin・/usr/lib・/cygdriveの4つのマウントポイントについては自動的にマウントが行われる。 /etc/fstab に明示的に記述することでマウントオプションを変更できるが、/ だけは override オプションも指定しなければならない。

 /etc/fstab.d/$USER は、Cygwin 1.7にアップグレードした直後に、/bin/copy-user-registry-fstab シェルスクリプトを実行すれば、/etc/fstab.d/$USER にファイルを作ってくれる。 このスクリプトはユーザーごとに実行する必要がある。 次回ログインからは自動でマウントしてくれるようになる。 今すぐにマウントしたければ mount -a とすればよい。

 CYGWIN環境変数にnontsecを指定した人は、この設定は環境変数からマウントオプションに移されたため、注意が必要である。 具体的には、/etc/fstab と /etc/fstab.d/$USER に noacl オプションを追加しなければならない。 /etc/fstab.d/$USER の方は見れば追加する場所はすぐ分かるだろう。 /etc/fstabの方はデフォルトではコメントしか書かれていないファイルなので、mount コマンドでマウント情報を吐き出して、自分で fstab ファイルを作る必要がある。 また、マウントポイント / については、override オプションも指定する必要がある。 /cygdriveから始まるマウントポイント(Win32ドライブの自動マウント)については、それらしき行がコメントアウトされて書かれているので、コメントを外してオプションを追加しておけばよい。

 多分こんな感じになるだろう。

C:/cygwin / ntfs override,binary,noacl 0 0
C:/cygwin/bin /usr/bin ntfs binary,noacl 0 0
C:/cygwin/lib /usr/lib ntfs binary,noacl 0 0
none /cygdrive cygdrive binary,noacl,posix=0,user 0 0

 mountコマンドの実行結果はこんな感じ。

C:/cygwin/bin on /usr/bin type ntfs (binary,noacl)
C:/cygwin/lib on /usr/lib type ntfs (binary,noacl)
C:/cygwin on / type ntfs (binary,noacl)
C: on /cygdrive/c type ntfs (binary,noacl,posix=0,user,noumount,auto)

 あと、Win95の系統はサポートされなくなったので注意。

nontsecな人のための1.7へのアップグレードまとめ:

home / uni / Cygwin 基本

●インストール
 Cygwinのページの Install or update now! のリンクでsetup.exeをダウンロードし、実行する。


↑このアイコン

 実行するとウィザードが出る。普通は次のように設定する。

 ここまで選ぶとSelect Packagesという画面になる。当面必要なものは全て入るので、とりあえずインストールする場合はこのままでよい。あとからパッケージを追加することもできる。

 「次へ」を押すとダウンロードとインストールが始まる。最後にお好みに応じてショートカットを追加の選択を行い完了ボタンを押す。setup.exeは今後も末永く使うので捨てずに分かりやすいところにとっておくこと。

home / uni / Cygwin ●パッケージの追加・削除
 最初にダウンロードしたsetup.exeで追加が行える。既に立ち上がっているCygwinの窓やサービスは止めておくこと(DLLの置き換えなどが行われる場合がある)。設定は以前のものを覚えているので、Select Packagesまでは基本的にEnterをバンバン押していればよい。Select Packagesの画面は最大化できるので、最大化して使うと使いやすい。

 既にインストールされているパッケージは「Current」のコラムにバージョンが入っている。新たにインストールしたいパッケージがある場合は、「New」のコラムをクリックし、インストールしたいバージョンにする。削除したい場合は「New」のコラムで「Uninstall」を選べばよい。

 あとは「次へ」を押していくと、パッケージの追加・削除・更新が行われる。

●パッケージの更新
 セキュリティFixなどがあった場合、パッケージを更新することになるが、この場合もsetup.exeを使う。この場合、パッケージ選択画面はそのままで「次へ」を押せばよい。このような事情があるので、setup.exeは定期的に実行するとよい。
●setupの更新
 setupを実行したときにiniファイルとバージョンが合わない、と言われることがある。 この場合はsetup.exeが更新されている。 新しいsetup.exeをダウンロードしてくればよい。
●使い方
 デスクトップなりスタートメニューなりにアイコンができるので、それを実行すればbashが立ち上がる。あとはUnixとあんまり変わらない。CygwinのbinディレクトリにWindowsのパスを通しておく(c:\cygwin\binをWindowsのPATH環境変数に書き加える)と、コマンドプロンプトから直接Cygwinのプログラムを使うことができる。関連付けを工夫すればコマンドプロンプトからbashのシェルスクリプトを直接実行することも可能。

home / uni / Cygwin ファイルシステムまわり

●Windowsファイルシステムとの関係
 まず、Unixではディレクトリの区切りは \ ではなく / である。これは慣れてもらわないといけない。

 Unixではファイル階層は必ずルートが / で始まり、ファイルとして扱えるものはすべてここにぶら下がる。ディスクドライブ上に複数の領域がある場合、それぞれの領域を / 以下の適当なディレクトリにマウントすることで初めて使えるようになる。また、ネットワークファイルサーバーも / 以下の適当なディレクトリにNFSマウントすることで使えるようになる。このマウントという概念がWindowsから移行すると分かりにくく、なんでこんな面倒なことをするんだろう、と思うのだが、フルパスといったら必ず / から始まるドライブ文字から開放されるというメリットがあり、慣れるとWindowsのファイルシステムの方がイライラするようになる。

 実はNTFSにもマウントと言う概念はある。普通はボリュームをドライブ名にマッピングするのだが、ジャンクションポイントと呼ばれるディレクトリを作って、そこへローカルドライブ(ローカルドライブのみのようだ)を割り当てることができる。ジャンクションポイントはコマンドプロンプトでディレクトリを取るとこんな風になる。

c:\you>dir c:\mnt
 ドライブ C のボリューム ラベルがありません。
 ボリューム シリアル番号は 5C6C-EE28 です

 c:\mnt のディレクトリ

2004/12/16  13:29       <DIR>          .
2004/12/16  13:29       <DIR>          ..
2004/12/16  13:29       <JUNCTION>     dvd
               0 個のファイル                   0 バイト
               3 個のディレクトリ  21,869,391,872 バイトの空き領域

 Unixのファイルシステムはこれをネットワークドライブなどに拡大したものだと思えばよい。Cygwinもこれに準じていて、とにかく / の下にぶら下げないとファイルとして扱えない。

home / uni / Cygwin ●マウント
 ファイル資源を / の下の任意の位置にぶら下げるためには mount コマンドを使う。試しに mount と実行してみると、以下のようになるだろう。
C:\cygwin\bin on /usr/bin type system (binmode)
C:\cygwin\lib on /usr/lib type system (binmode)
C:\cygwin on / type system (binmode)
c: on /cygdrive/c type user (binmode,noumount)

 最初の3行はCygwinがインストール時に設定したものである。Cygwin内で / をアクセスするとWindows的には c:\cygwin をアクセスすることになる(3行目)。同様に、/usr/bin と /usr/lib はそれぞれ c:\cygwin\bin と c:\cygwin\lib をアクセスすることになる。したがって、/bin と /usr/bin は同じ内容になる。Unixではマウントの他にハードリンク・シンボリックリンクというものがあり、こういうことはよくある(そして使いこなすとかなり便利だ)。もし、WindowsのDocuments and Settingsフォルダを真面目にホームディレクトリとして使っている場合は、そのディレクトリを /home/ユーザ名 にマウントする(か、/home/ユーザ名 を実ディレクトリへのシンボリックリンクにする)とよい。

 最後の行は自動的にマウントされたものである。ドライブ文字が割り当てられたモノ(ローカルドライブでもネットワークドライブでもよい)は、自動的に /cygdrive/ドライブ名 という位置にマウントされる。よって、c:\cygwin は / であると同時に、/cygdrive/c/cygwin でもある。もし適当なネットワークドライブを n: に割り当てていたとすれば、Cygwinの中からは /cygdrive/n/... という形でアクセスできる。

 これでとりあえずWindowsから使える資源はすべて使えるのだが、/cygdrive/n/ をいちいち打つのは面倒なので、適当な位置に自分でマウントすることができる。普通は /mnt というディレクトリの下にマウントすることが多い。複数のドライブをマウントする場合は /mnt の下にさらにディレクトリを掘るとよいだろう。例えば、/mnt/n に先ほどの n: を割り当てたければ、あらかじめ /mnt/n を作ってそこへマウントすればよい。/mnt/n は c:\cygwin\mnt\n に相当するので、このディレクトリを作る。作ったら、

$ mount -u n:\\ /mnt/n
とすれば、n: が /mnt/n で見えるようになる。bashからやる場合、\ がエスケープキャラクタなので、\\ と二つ続ける必要があることに注意。-u はユーザーマウントという意味で、このユーザーのみ有効である。-u をつけないとシステムマウントになるが、Administrator権限が必要になる。Cygwinの場合、マウント情報はWindowsのレジストリに記録されるため、再起動しても覚えている。

 Cygwin 1.5までは、マウント状態はレジストリに自動的に記録され、bashを立ち上げなおそうが、Windowsを再起動しようが覚えていたが、Cygwin 1.7からはそのセッションだけに限定されるようになった。 正確に言うと、Cygwinプロセスがシステムからいなくなるとマウントが解除されるようになった。 毎回マウントしたい場合は、システムマウントは /etc/fstab に、ユーザーマウントは /etc/fstab.d/$USER に書いておく必要がある。 Cygwin 1.5から1.7にアップグレードした際に、/bin/copy-user-registry-fstab シェルスクリプトを実行すると、ユーザーマウントポイントが /etc/fstab.d/$USER に出力されるようだ。 このスクリプトはユーザーごとに実行する必要がある。

 この影響で、コマンドプロンプトでマウントを行った場合、mountコマンドの終了と共にCygwinのセッションが終わってしまうため、コマンドプロンプトからのマウントは意味をなさない。 コマンドプロンプトからマウントしたパスを使いたい場合、必ず fstab あるいは fstab.d/$USER にマウント情報を書いておかなければならない。

別解: とりあえずXサーバーなどの常駐するプログラムを立ち上げてからマウントする。

 マウント解除は、

$ umount -u /mnt/n
である。指定するパスは普通Cygwin側のものである。-uはmount時に付けた場合は付ける。付けなかった場合は付けない。

 実はディレクトリは掘らなくてもよいのだが、掘らないとmountが文句を言うので掘った方がよいだろう。なお、ネットワークドライブの場合、実行可能かどうかのチェックがうんぬんという警告が出る(けど多くの場合無視してよい)。

 ネットワークドライブはドライブ文字を割り当てなくても、\\ から始まるURN形式で直接マウントすることもできる。例えば、n: は \\nov\vol1 という名前の共有名だったとすると、

$ mount -u \\\\nov\\vol1 /mnt/n
でも同様にマウントすることができる。ユーザー名とパスワードがローカルホストとリモートホストで違う場合、Windowsの net use コマンドをドライブ名の指定なしで実行しておくとよい。
home / uni / Cygwin ●アクセス権・パーミッション
 Windowsでは非常に多彩で柔軟な(⇔ハナモゲラ)アクセス権を設定することができる。一方、Unixでは基本的に本人・グループ・他人に読み書き実行の権利をON/OFFすることしかできない(⇔シンプル)。Windowsのアクセス権でUnixのパーミッションを実現するのは簡単に見えるが、意外にそうではない。

 例えば、Unixでの「他人はアクセス不可」(パーミッションを644から640に変更)と同じように設定しようと思って、Windowsで「Everyoneアクセス拒否」にすると、本当に誰もアクセスできなくなる。なんだそりゃ。CygwinはUnixのパーミッションがWindowsでもそれっぽく見えるようにかなり複雑なアクセス権を設定する。これがいろいろ問題を引き起こす。

 特にファイルやディレクトリを新たに作った時に問題が起きやすい。Windowsでは親オブジェクトからアクセス権を継承するという機能があるが、Unixではオブジェクト作成時に親と同じパーミッションを与える(正確にはumaskが適用される)という方法で同じようなことをやっている。これが非常に相性が悪い。Cygwinでオブジェクトを新たに作ると、親オブジェクトからのアクセス権継承が切れて、変なアクセス権が付与されてしまう。自分がアクセスする分にはまず問題ないのだが、グループメンバがアクセスする時にたいてい問題が起きる。だから他の人がアクセスして初めて問題が発覚する。タチが悪い。

 こういう理由からWindowsと同じ方法でオブジェクトを作った方がいろいろと楽であることが判明している。そのためには、CYGWIN環境変数にnontsecを設定すればよい。

 Cygwin 1.5まではCYGWIN環境変数にnontsecを設定すればWindowsと同じ方法でオブジェクトを作るようになっていが、1.7からはマウント時に指定するオプションにnoaclと指定すると同様の動作になるようだ。 このオプションはマウントポイントごとに指定できる。 nontsecを指定したからといってEveryoneフルアクセスになるわけではない。Windowsから見るとWindowsで普通にファイルを作った場合と同じようにアクセス権が設定され、Cygwinから見るとレギュラーファイルは644や755のアクセス権に見える。もちろん、他のユーザーからアクセスした場合はWindowsのアクセス権に従ってアクセス可否が決定される。

 同じ理由でCygwinからchown・chmodなどはしない方がよい。コマンドラインでアクセス権調整を行いたい場合は、Windowsのcaclsか、Cygwinのsetfaclを使うとよい。

home / uni / Cygwin 改行コードとテキスト形式

●テキスト形式
 Unixでは改行コードは 0x0a の1バイト、Windowsは 0x0d 0x0a の2バイトである。 UnixのプログラムをそのままWindows上で使うと、改行コードがすべて0x0aになってしまう。 逆に、WindowsのテキストファイルをUnixのプログラムに読み込ませると、改行文字の前に余計な 0x0d が付いているように見えてしまう。 ならば、強制的に改行コードを 0x0a 変換してしまえばいいような気もするが、そうすると今度はバイナリファイル〜画像ファイルや実行ファイルなど〜も変換してしまい、これもまたいろいろと問題が発生する。

 例えばCでプログラムを組むとき、ファイルをオープンするには関数fopenやopenを使うが、Windows環境でプログラムする場合は、これらの関数にテキストモード・バイナリモードを指定することができる。 fopen(fn, "rb"); という常套句がそれである。 例えばfopenならば、モードにtを指定すればテキストモードとなり、改行コードの変換が行われ、bを指定すればバイナリモードとなり、変換は行われない。 Cygwinでもそうなっているし、Cygwin付属のツールもテキストモード・バイナリモードのどちらで使うかがはっきりしている場合はそういう指定になっているようだ。 例えば、コンパイラがテキストモードで実行ファイルを吐き出したら、実行できないのは明らかだから、当然バイナリモードでファイルを出力する。

 では指定しなかった場合はどうなるのか。 デフォルトのモードがバイナリならば改行がおかしくなるし、テキストならばデータファイルが壊れる。 Unixでは元々改行文字が1文字であり、どちらを指定しても変換は行われないので、指定しないことが多い。 結論を言うと、基本的にはマウント時にバイナリモードかテキストモードかを指定できるようになっている。 マウント時にオプション -t を付けるとテキストモードに、付けなければバイナリモードになる。

 Cygwin 1.5まではマウント時にオプション -t をつけるとテキストモードになったが、Cygwin 1.7からは -o text をいうオプションを指定することになる。 この text はfstabに書いておくことも可能である。

 基本的には、と書いたのは、この規則に従わない場合もあるから。リダイレクトやパイプを使った場合などはまた別の規則がある。 このあたりは一応ユーザーズマニュアルに書いてあるので、複雑なシェルスクリプトを書いていて改行コードがおかしくなった場合は一度目を通してみるとよい。

(02 Dec 2015) ※一時期(bash-4.3.33-1〜)テキストモードでマウントしたディレクトリで、改行コードがCR+LFのシェルスクリプト中に $() や & があると正しく動かない、という問題がありましたが、bash-4.3.42-4 で直ったようです。

[ANNOUNCEMENT] Updated: bash-4.3.42-4

home / uni / Cygwin ●tar・gzip・cvs・svn・gitとテキスト形式
 そこそこの規模のあるソースツリーをWindowsマシンからUnix系のマシンに持っていくことを考える。 普通はWindowsマシン上で tar cfz とかで固めて、Unix系のマシン上で tar xfz とかで展開する。 tarの出力をパイプでsshに渡して、ログイン先のマシンでtarで展開すれば、中間ファイルもいらない。
c:\> tar cfz - source-dir | ssh user@unix-host tar xfz -
しかし、tarやgzipはバイナリファイルも扱うプログラムなので、すべてのファイルをバイナリモードでオープンする。 このため、すべてのファイルの改行コードがそのまま、おそらくは 0x0d 0x0a のまま unix-host に送られてしまう。 これは送る前に変換するか、送った後に変換するかしかない。 findとtrを使って地道にやることになるだろう。

 もし、元々のソースツリーがCVSやSubversionで管理されているものならば、tarで固めて送るよりも、unix-host で直接CVSやSubversionのリポジトリからチェックアウトした方が早い。 ただし、Subversionの場合は svn:eol-style 属性を native にしておく必要がある(普通は auto-props 設定でそうする)。

 CVSの場合、リポジトリにアクセスできないホストに送りたい場合は、Windowsマシンでバイナリモードでマウントしたディレクトリにチェックアウトすれば、改行コードがLFのファイルができあがる。 あとはこれをtarで固めて送ればよい。 逆に言うと、CVSをWindows上で使う場合はテキストマウントしたディレクトリ上で使わないと痛い目に会う、ということだ。 主にWindows上でプログラムを書く人は、どちらかというとテキストモードのお世話になることが多いので、ホームディレクトリをテキストモードでマウントし直しておくとよい。

 Subversionの場合、 svn:eol-style 属性が native になっていれば、ディレクトリがバイナリだろうがテキストだろうが、Win32版のsvnコマンドなら改行コードがCR+LFになる(たぶん)。 Windowsマシンでファイルを取得してtarで固めてUnixホストに送りたい場合でも、svn:eol-style さえ native にしてあれば、exportコマンドで --native-eol LF とすればテキストマウントのディレクトリでも改行コードがLFの状態でファイルを取得できる(たぶん)。 Subversionは.svnというディレクトリにリポジトリ側データのキャッシュを作る関係でチェックアウトだとデータ量が倍になってしまうが、exportならば.svnディレクトリができないのでデータ量も減る。 ただし、exportの場合は明示的にレビジョンを指定する必要がある。

 逆に、リポジトリそのものはバイナリモードでマウントしたディレクトリに置いたほうが安全だろう。 Unixマシンから直接smbmountすることもあるかもしれないし、将来Unixマシンにリポジトリを移すことになったときも楽である。 まあ、Subversionの場合は svnadmin dump すればいいのだが。

 Cygwin版gitの場合、バイナリマウントしてないとcloneができない。 したがって、作業ディレクトリ・ローカルリポジトリは必ずバイナリマウントする必要がある。 Win32ネイティブの(Cygwin版ではない)gitならばインストール時に改行コードをどう扱うかを設定できるのと、シェルを選べる(Cygwinがインストールされていても問題ない)ので、どちらかというとネイティブビルドのほうがお勧めかもしれない。

home / uni / Cygwin その他もろもろ

●mintty (10 May 2017)
 昔はWin標準のコマンドプロンプト(通称DOS窓)をコンソールとして使っていたが、いつの頃からかminttyという、PuTTYベースのマトモな端末エミュレータがCygwin標準で付いてくるようになった。

 左上のシステムメニューからいろいろ設定できる。 設定時に[Save]を押すと、設定した値はデフォルトで~/.minttyrcに書き込まれる。 この値は次回起動時に使用される。 現状、GUIだけで設定の作り分けはできない。

 だいたいの項目は起動時にコマンドラインからも設定できる。 設定一覧はman minttyに書いてある。 特に、ロケールと文字コードが設定できることに注目。 Windowsでショートカットを作り、「リンク先」を以下のようにすると、

C:\cygwin\bin\mintty.exe -o Locale=ja_JP -o Charset=eucJP -

端末が扱う文字コードがEUCになることはもちろん、LANG環境変数もja_JP.eucJPになる。 後ろにハイフンを付けておかないとログインシェルとして扱われないようなので注意。 背景色もコマンドラインから指定できるので、SJIS・EUC・UTF-8の3種類、文字コードごとに背景色を変えたショートカットを作っておくと便利。 また、「管理者として実行」にチェックを入れたショートカットも便利。

 設定ファイルをコマンドラインから指定することもできる。 -cオプションで指定したファイルは、起動時に存在していて書き込み可能ならば、GUI設定はこのファイルに保存される。 したがって、適当なファイルをあらかじめtouchして、そのファイルを-cオプションで指定したショートカットを作っておけば、そのショートカットの設定をGUI上でカスタマイズできる。

 コマンドラインからしか設定できない項目もある。 例えば、行間が詰まり過ぎで見づらい場合、オプションとして-o RowSpacing=2などとすると見やすくなる。 これはGUIからは設定できない。

 シェルから直接minttyを起動すると、minttyが終了するまで待たされるので、&を付ける必要がある。 設定も含めてスクリプトにしておくとよい。 そうすると、ショートカットとスクリプトは同じ状態で起動してほしいと思うのが人情。 が、シェルスクリプトをショートカットから起動するととりあえずbashを実行するためにひとつ窓ができて、スクリプトから起動したminttyの窓が出てから、bashのための窓が消える、という挙動になる。

 これはrunコマンドを使うことで解決できる。

C:\cygwin\bin\run.exe C:\cygwin\bin\bash.exe name-of-script -

よりスマートに済ませるには、先ほどの-cオプションによる設定ファイルを使えばよい。 ショートカットとスクリプトで共通の設定ファイルを使い、コマンドラインには余計なことは書かないようにすればよい。 設定もGUIから可能になる。

home / uni / Cygwin ●TIPS

コマンドプロンプトのstartみたいなことはできないの? → cygstartをどうぞ。

DOSバッチやシェルスクリプトでパス名変換したいんだけど → cygpathをどうぞ。

lsで日本語のファイル名が文字化けする → 日本語のファイル名はやめましょう。 環境変数LANGを ja_JP.sjis にしてみる。

lessで日本語が化ける → お手軽には less -r。きちんと使うにはUTF-8を使う。

CygwinでもWindowsでも使えるシンボリックリンク(ショートカット)を作りたい → CYGWIN="$CYGWIN winsymlinks" ln -s target symlinkname


Copyright (C) 1997-2017 akamoz.jp

$Id: cygwin.htm,v 1.20 2017/05/20 02:28:49 you Exp $