.zshenv で PATH を管理したら罠にハマった
Spacemacs を起動すると、.zshrc
で PATH
の設定をするな、と怒られた。ので、.zshenv
に記述を移すと、今度は不具合が起きた。emacs を以下のページの設定をして呼び出すと ~/bin/emacs
を実行していたのが、 .zshenv
に PATH を移したことによって /usr/local/bin/emacs
を呼び出すようになってしまった。
解決したのでメモする。
原因の特定
$ echo $PATH
をすると、/usr/local/bin
が ~/bin
より優先的に読み込まれていた。
なので、試しに .zshenv
に
PATH="$HOME/bin"
としてみても、
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/karur4n/bin
と出力された。
????????? なんで ???????
調べてみると、シェルログイン時に /etc/profile
を読み込んでいて、そこにある path_helper
が問題を引き起こしていた。
/etc/profile
... ... if [ -x /usr/libexec/path_helper ]; then eval `/usr/libexec/path_helper -s` fi ... ...
path_helper
はバイナリファイルなので、なにをしているかは man
で知る。
$ man path_helper
path_helper(8) BSD System Manager's Manual path_helper(8)
NAME path_helper -- helper for constructing PATH environment variable
SYNOPSIS path_helper [-c | -s]
DESCRIPTION
The path_helper utility reads the contents of the files in the directo- ries /etc/paths.d and /etc/manpaths.d and appends their contents to the PATH and MANPATH environment variables respectively. (The MANPATH envi- ronment variable will not be modified unless it is already set in the environment.)
Files in these directories should contain one path element per line.
Prior to reading these directories, default PATH and MANPATH values are obtained from the files /etc/paths and /etc/manpaths respectively.
要は path_helper
は、特定のファイルにディレクトリを書いておくと、それを PATH として読み込んでくれるものである。
PATH の値が取得される /etc/paths
を見る。
/etc/paths
/usr/local/bin /usr/bin /bin /usr/sbin /sbin
これが、上記の $ echo $PATH
時に勝手に読み込まれたものと一致していたので、path_helper が今回の問題の引き金だと断定した。
El Capitan からできなくなった対処法
似たような話があって、対策法も書いてあった。
これは、以下を実行して path_helper から実行権限をなくすアプローチ。
$ sudo chmod -x /usr/libexec/path_helper
で、めでたしめでたし、じゃなくて El Capitan からは rootless っていうセキュリティで、ユーザが /System
, /bin
, /sbin
, /usr
に変更を加えられないようになっている、sudo しても。homebrew で騒ぎになったアレ。
Mac - HomebrewはEl Capitanへアップグレードする前に入れておく - Qiita
なので、これはできない。
解決した
どうやって解決したかと言うと、zsh には path_helper を呼び出していた /etc/profile
を読み込まない設定があるので、それを有効にする。
.zshenv
setopt no_global_rcs
これでよい。試しに、PATH を表示してみる。
.zshenv
setopt no_global_rcs PATH="$HOME/bin"
$ echo $PATH ~/bin
やったー 🎉
ただしこれまでのように、/usr/local/bin
などが自動で読み込まれることはなくなったので、各自、PATH を読み込む必要がある。
よかった〜〜。
参考
Tower of babel をした
ついさっきやったので、メモ。
知らない人のために説明すると、Tower of babel は Babel っていう JavaScript の次世代仕様を扱えるようになるツールを使って、ES 6 での変更点を知ろうっていうレッスンプロダクト。
- 1時間ちょっとで全部終わった
- ES 6 をクラス構文とアロー関数しか把握してなかったから、だいぶタメになった
- 答えが分からなくなったら、/excercises の中の各レッスンの
/solutions
を見れば良い - modules_default_export と destructure は答えを見た
- さくっと終わるし、手を動かしてやる実践モノで、かなりよいチュートリアルだった
Spacemacs をターミナルから起動する
- ※ Spacemacs に限った内容ではありません。
- ※ Spacemacs を GUI で使う場合の話です。
- ※ Spacemacs じゃなくて Emacs の話じゃん、ですが検索のためにこういうタイトルにしています。
先日、Qiita にて Spacemacs というものを知った。これは Vim を使っている人が Emacs に移行をするため、という目的もある Emacs 設定集である。Spacemacs について詳しくは以下の Qiita のエントリか 公式のドキュメントを読んでほしい。
キーバインドが選べて vi にすると、Evil という Emacs 上で vim をエミュレートするプラグインが有効化されて Vim ユーザでもエディットの面ではほとんど違和感なく扱える。
UI がおしゃれだし、vi のキーバインドだし、Emacs なんかすごそうなので、少し Spacemacs を使おうという気になった。
で、ここで問題。Spacemacs の起動の方法。
Vim は以下のように起動してターミナル上で使う。
$ vim foo.txt
Emacs と同じく GUI エディタである Atom もターミナルから起動できる。
$ atom foo.txt
Emacs はターミナルで起動すると、ターミナル上に展開される。
$ emacs foo.txt
CUI で起動するとせっかくの綺麗さが損なわれるので、GUI で起動したいんだけど、Emacs のアイコンから起動して メニューバーの File から目的のファイル・ディレクトリを開くのめちゃくちゃめんどくさい。
ターミナルで作業しているときにパッと開きたい。
本題
2015/12/16 open コマンドの方法は問題があって、書き換えました
↓↓↓
↑↑↑
railwaycat さん作の perl スクリプトと ptb さん作のシェルスクリプトがある。perl が動作しない環境の人はシェルスクリプトの方を使うといいです。
これ、何をしているかというと引数で渡されたファイルをテンポラリファイルとして作成してそれを open
コマンドを使って Emacs で開く。
system("touch $args") if ($tmpfiles); system("open -a /Applications/Emacs.app $args");
open コマンド
OS X の open コマンドは、ターミナルからファイルやディレクトリを、それを開くデフォルトのアプリケーションで開く、というもの。
-a オプション
-a とは application のオプションで、これをつけると、アプリケーションを開くよーという意味になる。
例えば、アプリケーション名だけを書けば /Applications ディレクトリの中から探して開いてくれる。
-a をつけない場合は以下のように呼び出すということ。
$ open /Applications/emacs.app
また、これでもよい。
$ open -a /Applications/emacs.app
で、-a オプションを使うとアプリケーションに引数を渡せるので、そこでパスを書く。
これなら foo.txt を開くし
$ open -a emacs foo.txt
以下なら、現在のディレクトリを開く。
ただこれだけだと存在しないパスを引数として渡した場合、エラーになる。ので、事前にテンポラリファイルが作られる。
導入
$HOME/bin
などにパスを通して、そこにスクリプトを実行可能にして配置する。
$HOME/bin
にパスを通す。
.bashrc, .zshrc...
export PATH="$HOME/bin:$PATH"
スクリプトを配置
$ cd ~/bin
$ vi emacs
~/bin/emacs に ↓ をコピペする。
実行可能にする
$ chmod +x emacs
これで
Emacs.app をターミナルから起動できる。
おまけ
プロジェクトごとに Emacs を起動したい場合がある。いま現在の設定だと、現在 Emacs が開いている対象と違う対象を渡すと、同じプロセスで新たに渡した対象を開く。
新しい対象を渡した場合、Emacs のプロセスも新しく立ち上げてほしい場合、以下のように書き換える。
~/bin/emacs 17行目
system("open -a /Applications/Emacs.app $args -n");
$args の後ろに -n が追加された。
-n オプションは、もし指定したアプリケーションがすでに立ち上がっていた場合、別プロセスで起動させるもの。お好みで。
おわり
べつに Spacemacs, Emacs に関した話じゃないし、Emacs をこれから使っていくわけではないです。
参考
http://macwiki.osdn.jp/wiki/index.php/%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89/open