rcmdnk's blog

20150124_mobaxterm_200_200

WindowsでUnix環境を提供してくれる MobaXermですが、 用意されている/etc/profileの中で.bashrcを呼んでいるために ちょっと動作が思い通りにならなかった件。

Sponsored Links

MobaXterm

MobaXtermはCygwinの様にWindowsローカルにUnix環境を提供してくれるアプリです。 BusyBoxベースで本体自体は非常に軽く、またX11サーバーも付属しているので すぐにGUIも使うことが出来ます。

MobaXtermの/etc/profile

このMobaXtermで設定を色々いじっている時、どうも動作が思い通りにならない、ということがあって、 調べてみると/etc/profileの最後の方が

/etc/profile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...

. /etc/bash_completion
function OpenIniFile {
echo "Opening \"C:\Users\user\DOCUME~1\MobaXterm\MobaXterm.ini\"..."
/bin/cygstart.exe "`cygpath -u "C:\Users\user\DOCUME~1\MobaXterm\MobaXterm.ini"`"
}
[ -e "/home/mobaxterm/.bashrc" ] && . /home/mobaxterm/.bashrc
[ -e "/etc/sessionsaliases.sh" ] && . /etc/sessionsaliases.sh

fi
fi
. /etc/baseprofile
ls /etc/profile.d >/dev/null 2>/dev/null
[ -d "/etc/profile.d" ] && . /etc/profile.d/*.sh 2>/dev/null

こんな感じになっていました。

ここで

[ -e "/home/mobaxterm/.bashrc" ] && . /home/mobaxterm/.bashrc

という行が途中にあります。

/etc/profileは全ユーザー共通設定用ファイルでログイン時に読み込まれます。 その後、$HOME/.bash_profileと言った個人ファイルが読み込まれます。

また、$HOME/.bashrcはbashシェルを立ち上げる時に読み込まれます。

通常、これらの設定は共通で良いもので、 $HOME/.bash_profile側に

.bash_profile
1
2
3
if [ -f ~/.bashrc ];then
  . ~/.bashrc
fi

と書いておき、ログイン時にも.bashrcの内容をそのまま反映させるのが定石となっています。

ここで、MobaXtermの場合を見てみると、 /etc/profileの中で.bashrcを呼んでいますが、 その後.bash_profileも呼ばれるため上の設定をしていると .bashrcが二重で読み込まれてしまいます。

まあそれ自体はそれ程問題では無いんですが、 ちょっと問題なのは.bashrcが最初/etc/baseprofile等の他の共通セットアップファイル よりも先に呼ばれてしまうことです。

これらの共通設定を変更しようとした場合、最初は設定されておらず、その後設定されてる 様な状態でチェックが面倒です。

通常使っててそれ程気になるところでは無いかもしれませんが、 知らないと思い通りにならないこともあるので注意です。

さらに問題なのはここで/etc/baseprofileが呼ばれてますが、 この中ではエイリアスの設定などが入っています。

通常、こういったエイリアス設定はbashシェル立ち上げ時に読み込まれる/etc/bashrc の方に書いてあります。

ですが、MobaXtermには/etc/bashrcは無く、これらの設定は全て/etc/profile 側で呼ばれています。

見た感じ、MobaXtermはシェルの立ち上げの様な作業を無視しています。

これは結構問題があって、シェルスクリプトを実行するとその中では 通常設定されている様なエイリアスが使えないことになります。

さらにはGNU screenやtmuxのセッション立ち上げもシェルの立ち上げでしかないので これらが設定されていません。

/etc/baseprofileを見てみると、

/etc/baseprofile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash.exe

alias cls='echo -e "\ec\e[3J"'
alias clearall='echo -e "\ec\e[3J"'

alias "compress"="/bin/toybox.exe compress"
alias "count"="/bin/toybox.exe count"
...
alias "cal"="/bin/busybox.exe cal"
alias "cat"="/bin/busybox.exe cat"
...
alias apt-cyg="/bin/apt-cyg"
alias apt-get="/bin/apt-cyg"
...

みたいな感じのエイリアスがあります。

これらのエイリアスがシェルスクリプトの中で無効になるのですが、 ただ、デフォルトで/binにはPATHが通って居るのでapt-cygなどはここでは問題ありません。

また、catとかですが、これらも/bin/にあります。 これらは/bin/busybox.exeへのシンボリックリンクになっていますが おそらくbusybox.exeの中では呼ばれたコマンド名をチェックして 動作を変更する機能があり、busybox.exe catと引数として与えた時と 同じ動作をするようになっているんだと思います。

ので、これも問題なし。

最初のclsといった画面をクリアするようなエイリアスですがこれはシェルスクリプト内では使えません。

他にも下の方に関数など一部シェルスクリプト内では使えないものがありますが、 これらはそもそもMobaXtermをよく知らないと知りもしないものなのでそれ程気にならないかな、と。

ということで、MobaXtermは共通設定ファイルにちょっと癖があります。

もちろん、/etc/bashrcを自分で作って設定を移動させたりもできますが、 それだと毎回MobaXtermをインストールするたびに行わないといけないので余りよくありません。

その辺気をつけて使うか、やはり設定を書き換えてしまうか、ちょっと面倒な仕様です。

実際に起こった問題

今回これに気づいたのはHOMEをCygwinと共通にしようとしたところからでした。

MobaXtermでは設定でHOMEの場所を変更することが出来ますが、 これをCygwinのHOME(C:\cygwin64\home\user)にしてみました。

CygwinとMobaXtermではソフトウェアの仕様が違うため /usr/binなどは別にしたいので rootディレクトリはそのままにしておきます。

HOMEにソフトウェアをコンパイルして置いてたりする場合は同様に問題が起こりますが、 今は自作シェルスクリプトとかしか無いので大丈夫かな、ということで。

ただ、一つ問題があって、Cygwinではapt-cygHOME以下に置いています。

MobaXtermもapt-cygを使ってパッケージ管理出来るのですが、 こちらはプレインストールされていて、Cygwin用のapt-cygを MobaXterm用に改変したものが使われています。

CygwinとHOMEを共用にした場合、 $HOME/usr/bin/apt-cygがPATHの中で最優先されます。

ただし、上にも書いたとおり、apt-cygはエイリアスされていて そちらが優先されるため最初は/bin/apt-cygが使われます。

ただ、apt-cygはシェルスクリプトで、installなどの時には 更に中で再帰的にapt-cygを呼んでいます。 この時、シェルスクリプト内になるため、エイリアスが反映されず PATHの中で再優先されたものが使用されてしまい問題が起こります。

/home/mobaxterm/usr/bin/apt-cyg: line 152: arch: command not found
Error: GnuPG is not installed. Prease install gnupg package or use -X option.

こんなエラーが途中で出てきてインストールに失敗します。

これを解決するためには、

.bashrc
1
2
3
4
5
6
7
if [ "$HOME" = "/home/mobaxterm" ];then
  unalias apt-cyg >& /dev/null
  hash -r
  function apt-cyg () {
    PATH=/bin:$PATH /bin/apt-cyg "$@"
  }
fi

こんな設定を書いておくとなんとかなります。 エイリアスだとダメなので、PATHの設定をapt-cygの場合だけ強制的に変えて コマンドを実行する関数を作っています。

上にも書いたとおり.bashrcは二度呼ばれますが、 unaliasをする際、最初に呼ばれるときはまだ設定されてないのでエラーが出るので /dev/nullに吐き出しています。

また、GNU screen等の中でエイリアス等の設定をしたいのであれば、

. /etc/baseprofile

も上の中で呼んでしまえば良いと思います。 (ログイン時にはこのスクリプトが計3回も呼ばれる事になりますが。。。)

綺麗にやるにはやはり共用設定自体を弄る必要がありますが、 できればそちらは弄りたくないので手元でやるとするとこんな感じです。

Sponsored Links
Sponsored Links

« 携帯の更新月が来たのでFREETELに乗り換えた Androidでストレージアクセスに問題がある場合、Battery Mixが問題の場合がある »