Homebrewでnodebrewのインストールに失敗した時の対処(Perl, CPAN絡み)

## 最初に結論から
`brew install nodebrew`がエラーになったのですが、原因は以下の複合的なものでした。

* nodebrewのインストールは内部でPerlが走る
* `brew install nodebrew`では、Mac標準の`/usr/bin/perl`が決め打ちで動く
  * Homebrew版の`/usr/local/bin/perl`が入っていても使われない
* Homebrew版Perlの`cpan`コマンドで各種モジュールがインストールされていた
  * CPANモジュールのインストール先はデフォルトの`~/perl5`配下
  * Mac標準のPerlからも同じ`~/perl5`のモジュールが参照される
  * バージョン間非互換のため、Mac標準Perlを使うとエラーが頻発する
	  * Mac標準Perl: v5.18.2 (El Capitan 10.11.6)
	  * Homebrew版Perl: v5.24.1

インストール時に`~/perl5`ディレクトリを変名することでエラー回避できました。

```
~ % mv perl5 perl5_bk
~ % brew install nodebrew
(略)
==> Using the sandbox
==> Downloading https://github.com/hokaccha/nodebrew/archive/v0.9.6.tar.gz
Already downloaded: /Users/$USER/Library/Caches/Homebrew/nodebrew-0.9.6.tar.gz
==> /usr/local/Cellar/nodebrew/0.9.6/bin/nodebrew setup_dirs
==> Caveats
Add path:
  export PATH=$HOME/.nodebrew/current/bin:$PATH

To use Homebrew's directories rather than ~/.nodebrew add to your profile:
  export NODEBREW_ROOT=/usr/local/var/nodebrew

Bash completion has been installed to:
  /usr/local/etc/bash_completion.d

zsh completion has been installed to:
  /usr/local/share/zsh/site-functions
==> Summary
🍺  /usr/local/Cellar/nodebrew/0.9.6: 8 files, 38.0K, built in 2 seconds
~ % mv perl5_bk perl5
```

根本的にはこんな風にライブラリがバッティングしてる状況を何とかすべきなんですけど、今はPerlに深入りする余裕がないのでおいおい。。。

この結論に至るまで相当時間かかってしまったのですが、数年後に自分で読み返して「あの時と比べて俺は成長したな〜」と涙することが出来るように、詳細な調査記録を書いてみました。ダラダラ長いですが、興味あれば読んでみてください。

## ハマるまでの経緯

[remark-lint](https://github.com/wooorm/remark-lint)をインストールしようと`npm install`を初めて叩いたらエラーになりまして、 **入っているnodeとnpmを一旦削除してnodebrewを新規インストールしたい** と思ったのがそもそも。

[Titaniumで自動インストールされたnodeやnpmが/usr/local配下に残っていた件](http://qiita.com/the_red/items/aeee6d328995f557cfbf)

> しかしこの後、Homebrewからnodebrewをインストールしようとして別途ハマるのですが、また別記事で書きまーす。

の続きです。

参考にさせてもらった[この記事](http://akiyoko.hatenablog.jp/entry/2015/06/20/132239)にも書いてありましたが、nodebrewの公式なインストール方法は以下のコマンドです。

```
$ curl -L git.io/nodebrew | perl - setup
```

でもRuby環境を作った時は`brew install rbenv`でrbenvを入れたし、大元のインストールは極力Homebrewからやりたいなーというこだわりが僕にはありました。そしてこの記事のようにサクッとできるはずでした。。。
[Node.jsの管理をHomebrewからnodebrewに変える]
(http://qiita.com/takeshi81/items/805f504503cd93151ca6)

しかし、エラー発生。

```
~ % brew install nodebrew
Updating Homebrew...
==> Auto-updated Homebrew!
(略)
==> New Formulae
(略)
==> Updated Formulae
(略)
==> Renamed Formulae
(略)
==> Deleted Formulae
(略)

==> Using the sandbox
==> Downloading https://github.com/hokaccha/nodebrew/archive/v0.9.6.tar.gz
==> Downloading from https://codeload.github.com/hokaccha/nodebrew/tar.gz/v0.9.6
######################################################################## 100.0%
==> /usr/local/Cellar/nodebrew/0.9.6/bin/nodebrew setup_dirs
Last 15 lines from /Users/$USER/Library/Logs/Homebrew/nodebrew/01.nodebrew:
2017-02-28 09:40:02 +0900

/usr/local/Cellar/nodebrew/0.9.6/bin/nodebrew
setup_dirs

Usage: DynaLoader::dl_find_symbol(libhandle, symbolname) at /Users/$USER/perl5/lib/perl5/darwin-thread-multi-2level/XSLoader.pm line 89.
Compilation failed in require at /System/Library/Perl/5.18/darwin-thread-multi-2level/POSIX.pm line 11.
BEGIN failed--compilation aborted at /System/Library/Perl/5.18/darwin-thread-multi-2level/POSIX.pm line 17.
Compilation failed in require at /usr/local/Cellar/nodebrew/0.9.6/bin/nodebrew line 666.
BEGIN failed--compilation aborted at /usr/local/Cellar/nodebrew/0.9.6/bin/nodebrew line 666.

READ THIS: http://docs.brew.sh/Troubleshooting.html
```

## エラーとの格闘

どうやらインストール時にPerlプログラムが走ってて、その中でエラーになっているっぽい。
しかも`/System/Library/Perl/5.18/darwin-thread-multi-2level`と出てるので、HomebrewのPerlではなくMac標準のPerlが動いているっぽい。

### nodebrewでよくあるエラー？

英語サイト含めて色々と検索してみても、nodebrewのインストールでこんなエラーが起きたという情報が全く見つからず。。。

### Homebrewでよくあるエラー？

やはり全く情報見つからず。。。

### perlでよくあるエラー？

nodebrewに限らずPerlのエラーとして検索したところ、こんなのを見つけた。
[MacのSecurity Update 2009-001でperlが動かんくなった]
(http://journal.soffritto.org/entry/334)

この人はPerlの最新ソースを落として`make install`とかしてるけど、そもそもバージョンも違うのでこれで直るかわからんし、ハイリスク・ローリターンだと思って別の方法を検討。

### Homebrewのログと設定をしっかり確認

さっきのエラーメッセージに載っていたログファイルを全部見てみると、やはり`/usr/bin/perl`が指定されている。

```
~ % cat /Users/$USER/Library/Logs/Homebrew/nodebrew/01.nodebrew
2017-02-28 09:40:02 +0900

/usr/local/Cellar/nodebrew/0.9.6/bin/nodebrew
setup_dirs

Usage: DynaLoader::dl_find_symbol(libhandle, symbolname) at /Users/$USER/perl5/lib/perl5/darwin-thread-multi-2level/XSLoader.pm line 89.
Compilation failed in require at /System/Library/Perl/5.18/darwin-thread-multi-2level/POSIX.pm line 11.
BEGIN failed--compilation aborted at /System/Library/Perl/5.18/darwin-thread-multi-2level/POSIX.pm line 17.
Compilation failed in require at /usr/local/Cellar/nodebrew/0.9.6/bin/nodebrew line 666.
BEGIN failed--compilation aborted at /usr/local/Cellar/nodebrew/0.9.6/bin/nodebrew line 666.

HOMEBREW_VERSION: 1.1.10
ORIGIN: https://github.com/Homebrew/brew
HEAD: 69d1cedd12d37d6a9535fbba17d2129b165c08f8
Last commit: 13 days ago
Core tap ORIGIN: https://github.com/Homebrew/homebrew-core
Core tap HEAD: f58aa629a583e8e4c15cff2661c0d2a9f80c3078
Core tap last commit: 63 minutes ago
HOMEBREW_PREFIX: /usr/local
HOMEBREW_REPOSITORY: /usr/local/Homebrew
HOMEBREW_CELLAR: /usr/local/Cellar
HOMEBREW_BOTTLE_DOMAIN: https://homebrew.bintray.com
CPU: quad-core 64-bit ivybridge
Homebrew Ruby: 2.0.0-p648
GCC-4.2: build 5666
Clang: 8.0 build 800
Git: 2.10.1 => /Applications/Xcode.app/Contents/Developer/usr/bin/git
Perl: /usr/bin/perl
Python: /usr/bin/python
Ruby: /usr/bin/ruby => /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby
Java: 1.8.0_112
macOS: 10.11.6-x86_64
Xcode: 8.2.1
CLT: 8.2.0.0.1.1480973914
X11: N/A

HOMEBREW_CC: clang
HOMEBREW_CXX: clang++
SDKROOT: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk
MAKEFLAGS: -j4
CMAKE_PREFIX_PATH: /usr/local
CMAKE_INCLUDE_PATH: /usr/include/libxml2:/System/Library/Frameworks/OpenGL.framework/Versions/Current/Headers
CMAKE_LIBRARY_PATH: /System/Library/Frameworks/OpenGL.framework/Versions/Current/Libraries
MACOSX_DEPLOYMENT_TARGET: 10.11
PKG_CONFIG_LIBDIR: /usr/lib/pkgconfig:/usr/local/Homebrew/Library/Homebrew/os/mac/pkgconfig/10.11
ACLOCAL_PATH: /usr/local/share/aclocal
PATH: /usr/local/Homebrew/Library/Homebrew/shims/super:/usr/bin:/bin:/usr/sbin:/sbin
~ %
```

一方Homebrewのconfigを見てみると、`/usr/local/bin/perl`が指定されている。

```
~ % brew --config
HOMEBREW_VERSION: 1.1.10
ORIGIN: https://github.com/Homebrew/brew
HEAD: 69d1cedd12d37d6a9535fbba17d2129b165c08f8
Last commit: 13 days ago
Core tap ORIGIN: https://github.com/Homebrew/homebrew-core
Core tap HEAD: f58aa629a583e8e4c15cff2661c0d2a9f80c3078
Core tap last commit: 80 minutes ago
HOMEBREW_PREFIX: /usr/local
HOMEBREW_REPOSITORY: /usr/local/Homebrew
HOMEBREW_CELLAR: /usr/local/Cellar
HOMEBREW_BOTTLE_DOMAIN: https://homebrew.bintray.com
CPU: quad-core 64-bit ivybridge
Homebrew Ruby: 2.0.0-p648
GCC-4.2: build 5666
Clang: 8.0 build 800
Git: 2.11.0 => /usr/local/bin/git
Perl: /usr/local/bin/perl => /usr/local/Cellar/perl/5.24.1/bin/perl
Python: /usr/local/bin/python => /usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/bin/python2.7
Ruby: /Users/$USER/.rbenv/shims/ruby => /Users/$USER/.rbenv/versions/2.4.0/bin/ruby
Java: 1.8.0_112
macOS: 10.11.6-x86_64
Xcode: 8.2.1
CLT: 8.2.0.0.1.1480973914
X11: N/A
```

ってことはnodebrewのパッケージ作者があえて`/usr/bin/perl`を使うように設定してる？


### brew install nodebrewで/usr/local/bin/perlを使えないか？

ログを読んだ流れでかなり調べてみたけど分からなかったので諦める。
パッケージ作者が設定してたとしたらユーザーが変えるのは不可能かも。
Homebrewの設定周り詳しくないので、この辺わかる人いたら教えてくださいm(. .)m

### nodebrewインストーラのソース確認

```
Compilation failed in require at /usr/local/Cellar/nodebrew/0.9.6/bin/nodebrew line 666.
BEGIN failed--compilation aborted at /usr/local/Cellar/nodebrew/0.9.6/bin/nodebrew line 666.
```

問題の666行目を確認したかったけど、インストール失敗した後は上記ソースがロールバックで消えちゃってたので確認できず。

### brew installは諦めて普通のインストール

この決断まで相当時間かかってしまった。。。
デフォルトの方法では、当然PATHの最優先である`/usr/local/bin/perl`が動くのでインストール成功。

```
~ % curl -L git.io/nodebrew | perl - setup
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:--  0:00:02 --:--:--     0
  0     0    0     0    0     0      0      0 --:--:--  0:00:03 --:--:--     0
100 24340  100 24340    0     0   5872      0  0:00:04  0:00:04 --:--:--  5872
Fetching nodebrew...
Installed nodebrew in $HOME/.nodebrew

========================================
Export a path to nodebrew:

export PATH=$HOME/.nodebrew/current/bin:$PATH
========================================
~ %
```

### nodebrewインストーラのソース確認 再度

まだ諦めきれず、粘る。
上記でダウンロードしたインストーラが`~/.nodebrew`ディレクトリ内に残ってたので、問題の666行目が読めた。
`use POSIX`で落ちている！

```
~ % cat -n ~/.nodebrew/current/bin/nodebrew | sed -n 664,667p
   664	package Nodebrew::Utils;
   665
   666	use POSIX;
   667	use Cwd 'getcwd';
```

### Perlでエラーになったソース確認

もう意地なのでログに出ていたPerlのソースも読んでみる。Perlも少し齧ったことある程度なんですけど。。。
さっきの`use POSIX`で呼ばれたソース

```
Compilation failed in require at /System/Library/Perl/5.18/darwin-thread-multi-2level/POSIX.pm line 11.
BEGIN failed--compilation aborted at /System/Library/Perl/5.18/darwin-thread-multi-2level/POSIX.pm line 17.
```
```
~ % cat -n /System/Library/Perl/5.18/darwin-thread-multi-2level/POSIX.pm | sed -n 11,17p
    11	use Fcntl qw(FD_CLOEXEC F_DUPFD F_GETFD F_GETFL F_GETLK F_RDLCK F_SETFD
    12		     F_SETFL F_SETLK F_SETLKW F_UNLCK F_WRLCK O_ACCMODE O_APPEND
    13		     O_CREAT O_EXCL O_NOCTTY O_NONBLOCK O_RDONLY O_RDWR O_TRUNC
    14		     O_WRONLY SEEK_CUR SEEK_END SEEK_SET
    15		     S_ISBLK S_ISCHR S_ISDIR S_ISFIFO S_ISREG
    16		     S_IRGRP S_IROTH S_IRUSR S_IRWXG S_IRWXO S_IRWXU S_ISGID S_ISUID
    17		     S_IWGRP S_IWOTH S_IWUSR S_IXGRP S_IXOTH S_IXUSR);
```
`use Fcntl`関数で落ちてる。
以下はその先なのかな？

```
Usage: DynaLoader::dl_find_symbol(libhandle, symbolname) at /Users/$USER/perl5/lib/perl5/darwin-thread-multi-2level/XSLoader.pm line 89.
```
```
~ % cat -n /Users/$USER/perl5/lib/perl5/darwin-thread-multi-2level/XSLoader.pm | sed -n 89,91p
    89	    if ($boot_symbol_ref = dl_find_symbol( 0, $bootname , 1 )) {
    90	        goto boot; #extension library has already been loaded, e.g. darwin
    91	    }
```
最終的に`dl_find_symbol()`の引数がふたつで十分ですよー！と叱られてるのですね。

### .zshrcを編集

```
export PATH=$HOME/.nodebrew/current/bin:$PATH
```
結局よく分からんしこれで終わりにしようと思い、上記のnodebrew設定をするため`.zshrc`を開いて、ファイル内を`"PATH"`で検索したらびっくり。
いつの間にかこんな処理が追加されている。`brew install perl`の仕業っぽい。

```
PATH="/Users/$USER/perl5/bin${PATH:+:${PATH}}"; export PATH;↲
PERL5LIB="/Users/$USER/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB;↲
PERL_LOCAL_LIB_ROOT="/Users/$USER/perl5${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT;↲
PERL_MB_OPT="--install_base \"/Users/$USER/perl5\""; export PERL_MB_OPT;↲
PERL_MM_OPT="INSTALL_BASE=/Users/$USER/perl5"; export PERL_MM_OPT;↲
```

めっちゃエラー出てた場所なので、これをコメントアウトしたらうまくいくんじゃね？(深く考えず手当り次第モード。。。)

```
#PATH="/Users/$USER/perl5/bin${PATH:+:${PATH}}"; export PATH;↲
#PERL5LIB="/Users/$USER/perl5/lib/perl5${PERL5LIB:+:${PERL5LIB}}"; export PERL5LIB;↲
#PERL_LOCAL_LIB_ROOT="/Users/$USER/perl5${PERL_LOCAL_LIB_ROOT:+:${PERL_LOCAL_LIB_ROOT}}"; export PERL_LOCAL_LIB_ROOT;↲
#PERL_MB_OPT="--install_base \"/Users/$USER/perl5\""; export PERL_MB_OPT;↲
#PERL_MM_OPT="INSTALL_BASE=/Users/$USER/perl5"; export PERL_MM_OPT;↲
```


```
~ % rm -rf .nodebrew/
~ % brew install nodebrew
(略)
Usage: DynaLoader::dl_find_symbol(libhandle, symbolname) at /Users/$USER/perl5/lib/perl5/darwin-thread-multi-2level/XSLoader.pm line 89.
Compilation failed in require at /System/Library/Perl/5.18/darwin-thread-multi-2level/POSIX.pm line 11.
BEGIN failed--compilation aborted at /System/Library/Perl/5.18/darwin-thread-multi-2level/POSIX.pm line 17.
Compilation failed in require at /usr/local/Cellar/nodebrew/0.9.6/bin/nodebrew line 666.
BEGIN failed--compilation aborted at /usr/local/Cellar/nodebrew/0.9.6/bin/nodebrew line 666.

READ THIS: http://docs.brew.sh/Troubleshooting.html
```
デスヨネー。アキラメヨー。

## Qiita書き始める

とにかく今回ネット上に情報が全然なかったので、後世に向けて「Homebrewにこだわるな！curl使え！」「そもそもTitaniumが悪いのよ！」って情報を残したくなって、初めて自分でQiitaを書き始める。
長くなったので[前の記事](http://qiita.com/the_red/items/aeee6d328995f557cfbf)だけ一旦公開。

次に本記事に取り掛かり、「最初に結論から書こう」と思って要点をまとめながら再度エラーログを見ていたところ、、、

### やっと根本原因に気がつく

* 問題の`/Users/$USER/perl5/lib/perl5`は、Homebrew版Perlの`cpan`コマンドで入れたパッケージの格納先だ！
* Mac標準のPerl使ってるのに、Homebrew版PerlのCPANライブラリを見てやがる！
* そりゃ別バージョンのライブラリ参照したらエラーも起きて当然やわ！
* てことは **単に`/Users/$USER/perl5`ディレクトリを変名すればいいんじゃね？**

```
~ % mv perl5 perl5_bk
~ % brew install nodebrew
(略)
==> Using the sandbox
==> Downloading https://github.com/hokaccha/nodebrew/archive/v0.9.6.tar.gz
Already downloaded: /Users/$USER/Library/Caches/Homebrew/nodebrew-0.9.6.tar.gz
==> /usr/local/Cellar/nodebrew/0.9.6/bin/nodebrew setup_dirs
==> Caveats
Add path:
  export PATH=$HOME/.nodebrew/current/bin:$PATH

To use Homebrew's directories rather than ~/.nodebrew add to your profile:
  export NODEBREW_ROOT=/usr/local/var/nodebrew

Bash completion has been installed to:
  /usr/local/etc/bash_completion.d

zsh completion has been installed to:
  /usr/local/share/zsh/site-functions
==> Summary
🍺  /usr/local/Cellar/nodebrew/0.9.6: 8 files, 38.0K, built in 2 seconds
~ % mv perl5_bk perl5
```

嗚呼、、、どんだけ時間かけとんねん俺。。。orz

「デフォルトのPerlと後から入れたPerlのCPAN混在」って観点だと、こんな記事も見つかりました。僕がハマった現象そのまんまではないですけどね。
[Perlのバージョンが違うとCPANがモジュールをインストールする先も違うよ](http://basicwerk.com/blog/archives/1468)

## エピローグ

あとはもうね、涼しい顔してサラッと行きましょ。

```
~ % nodebrew install-binary stable
Fetching: https://nodejs.org/dist/v7.6.0/node-v7.6.0-darwin-x64.tar.gz
Warning: Failed to create the file
Warning: /Users/$USER/.nodebrew/src/v7.6.0/node-v7.6.0-darwin-x64.tar.gz: No
Warning: such file or directory

curl: (23) Failed writing body (0 != 941)
download failed: https://nodejs.org/dist/v7.6.0/node-v7.6.0-darwin-x64.tar.gz
```
OMG!!!(#ﾟДﾟ)

でも情報はすぐ見つかった。
[nodebrew install が Failed to create the file と怒られる。]
(https://blog.yug1224.com/archives/5693a5e0fef2539c7d5b149d)

自分でディレクトリ作る必要があるらしい。不親切すぎる。。。

```
~ % mkdir -p .nodebrew/src                                                 [0:54:05]
~ % nodebrew install-binary stable                                         [0:54:15]
Fetching: https://nodejs.org/dist/v7.6.0/node-v7.6.0-darwin-x64.tar.gz
######################################################################## 100.0%
Installed successfully
~ % nodebrew use stable                                                    [0:54:44]
use v7.6.0
~ % exec $SHELL -l                                                         [0:56:00]
~ % node -v                                                                [0:56:06]
v7.6.0
~ % npm -v                                                                 [0:56:10]
4.1.2
```

おっし！そしてこの先が最初にやりたかった[remark-lint](https://github.com/wooorm/remark-lint)のインストール！

```
~ % npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

(中略)

About to write to /Users/$USER/package.json:
{
  "name": "$USER",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}


Is this ok? (yes)
~ % npm install --save remark-cli remark-lint remark-preset-lint-recommended
npm WARN deprecated isarray@2.0.1: Just use Array.isArray directly

> fsevents@1.1.1 install /Users/$USER/node_modules/fsevents
> node install

(中略)

npm WARN $USER No description
npm WARN $USER No repository field.
~ % ./node_modules/.bin/remark -v
remark: 7.0.0, remark-cli: 3.0.0
~ %
```

動いたー！！！！！(´；ω；｀)

## そして真のボス、remark-lintとの格闘へ。。。

今回インストールした[remark-lint](https://github.com/wooorm/remark-lint)が何故そもそも必要だったかというと、AtomでMarkdownを編集するときにLinter使いたかったからなんですね。普通に[linter-markdown](https://atom.io/packages/linter-markdown)というプラグインを入れるだけでLinter自体は使えるんですけど、`.remarkrc`で警告をカスタマイズしようとすると、別途remark-lintのインストールが必要という仕様なのです。

無事npmが入り、remark-lintも入ったので一件落着と思いきや、Atomのlinter-markdownプラグインとの連携でまた壮絶にハマるのでありますが、それはまた[次の記事](http://qiita.com/the_red/items/3e6294244cb81e91c121)で。。。