CentOS6でElectronベースNightmareを動かす

結論: Cent7を使いましょう

------------------- ↓ 余談はここから ↓-------------------
ヾ(・ω<)ﾉ"　三三三●　ⅱⅲ コロコロ♪

----

PhantomJSのラッパーからスタートしたNightmareというヘッドレスブラウザがある
v1からv2になった時にPhantomJSからElectronベースになった。
PhantomJSについては当方の過去記事でさんざんやったので、
あえてNightmareを使う必要は感じなかったが、
ベースが変わったのなら話は別だ。

ということでさっそく使ってみようとしたが、
インストールで躓いたでのそこを書いてみる。

構成としてはX11をインストールしたサーバーとか持ってないので、
手元にあるCentOS6.7のXvfb上にelectronを動かす流れで。

まず、調べ始めると以下のような記事が出てきた。


[HeadlessなLinux環境でNightmare(v2)を動かすためにしたこと](http://qiita.com/imunew/items/f1cf5e2553fc77df28ed)
> CentOS6.xでは、Electronは動かない

(ﾟДﾟ)!?

開始５秒で終了。。。

いやいや、まだ慌てるときじゃない。
とりあえず、インストールを走らせてみよう。

```shell-session
$ sudo yum install xorg-X11-server-Xvfb
パッケージ xorg-X11-server-Xvfb は利用できません。
  * おそらくの意味: xorg-x11-server-Xvfb
エラー: 何もしません
```
(ﾟДﾟ)ファ!?

その他エラーが大量に出た。
これは・・・。。。


苦心の末何とか動くところまで持って行けた。
しかし、ことのほかハードルが高く、
glibcをソースからビルドして差し替える事態に。
正直、CentOS7に変えた方が良い。

------------------- ↓ 本題はここから ↓-------------------
ヾ(・ω<)ﾉ"　三三三●　ⅱⅲ コロコロ♪

----

## CentOSを6.8に更新

上記サイトにはglibcのバージョンが問題だと指摘しているが、
まず手元にあるCentのバージョンアップから始めてみることにした。

```shell-session
$ sudo yum update
http://mirror.centos.org/centos/6/SCL/x86_64/repodata/repomd.xml: [Errno 14] PYCURL ERROR 22 - "The requested URL returned error: 404 Not Found"
他のミラーを試します。
To address this issue please refer to the below knowledge base article

https://access.redhat.com/articles/1320623

If above article doesn't help to resolve this issue please open a ticket with Red Hat Support.

```
(ﾟДﾟ)!?????

今度はなんか別のエラーが出た。
たすけてーエロい人～

以下のサイトを発見。
[CentOS 6.7のyum updateでエラー](https://www.pistolfly.com/weblog/2016/05/httpmirror-centos-orgcentos6sclx86_64repodatarepomd-xml-errno-14-pycurl-error-22-the-requested-url-returned-error-404-not-found.html)
どうやらCentOS Software Collectionが6系と7系で違うらしい。
CentOS6 : yum install centos-release-SCL
CentOS7 : yum install centos-release-scl
小文字の方に差し替える必要がありそうだ。

とうことでOSをCentOS6.7から6.8にバージョンアップ

```shell-session
$ sudo yum remove centos-release-SCL
$ sudo yum update
$ sudo yum install centos-release-scl
$ sudo yum update 
```

## glibcのビルド
コマンドは大したことないが、
ビルド時間は尋常じゃなくかかる。
サーバのスペックに自信がなければ、
寝る前にビルドすることをお勧めする。

インストール先は/usr/localにする

### glibcのビルド
```shell-session
$ wget http://ftp.gnome.org/pub/gnome/sources/glib/2.32/glib-2.32.4.tar.xz
$ tar Jxvf glib-2.32.4.tar.xz
$ cd glib-2.32.4
$ ./configure
$ make
$ sudo make install
```

### gccのビルド
```shell-session
$ wget http://ftp.tsukuba.wide.ad.jp/software/gcc/releases/gcc-4.8.4/gcc-4.8.4.tar.gz
$ tar xvfz 
$ cd gcc
$ ./configure
$ make # ←時間に余裕があるときにビルドするように(筆者は５時間ほどかかった)
$ sudo make install # ←対象ファイルはひとつだけなので手動で切り替えも可
```

### LD_LIBRARY_PATHに/usr/local/libを登録
```shell-session
$ sudo vi /etc/ld.so.conf.d/0default.conf
/usr/local/lib/
/usr/lib/
```

### ldconfig実行
```shell-session
$ sudo ldconfig
$ sudo ldconfig -p | grep libstdc++.so  # 登録確認
libstdc++.so.6 (libc6,x86-64) => /usr/lib64/libstdc++.so.6 
libstdc++.so.6 (libc6) => /usr/local/lib/libstdc++.so.6    ←これが含まれればOK
libstdc++.so (libc6) => /usr/local/lib/libstdc++.so
$ sudo ldconfig -p | grep libgobject  # 登録確認
libgobject-2.0.so.0 (libc6,x86-64) => /usr/local/lib/libgobject-2.0.so.0     ←これが含まれればOK
libgobject-2.0.so.0 (libc6,x86-64) => /lib64/libgobject-2.0.so.0
libgobject-2.0.so (libc6,x86-64) => /usr/local/lib/libgobject-2.0.so
libgobject-2.0.so (libc6,x86-64) => /usr/lib64/libgobject-2.0.so
```


## Xvfbをインストール

さて、最初に戻って仮想X11ディスプレイXvfbをインストールする。
あと、各種x11系のフォントと日本語フォントも入れておく

```shell-session
$ sudo yum install xorg-x11-server-Xvfb "xorg-x11-fonts*"
$ sudo yum -y groupinstall "Japanese Support"
```
インストールの確認

```shell-session
$ which xvfb-run
/usr/bin/xvfb-run
```

## nodejsのインストール
nightmareもelectronはnodejsベースのデスクトップアプリフレームワーク。
なのでnodejsは別途インストールが必要。

nodejsに関してはバージョンアップが頻繁にあるので、
yumで入れずにnodebrewを使う。
perlが必要なのであらかじめ入れておくように。

```shell-session
$ curl -L git.io/nodebrew | perl - setup
$ cat >> ~/.bashrc
export PATH=$HOME/.nodebrew/current/bin:$PATH
export NODE_PATH=$HOME/.nodebrew/current/lib/node_modules/
$ source ~/.bashrc
```

Nodejsをインストールする
最新バージョンを入れておく

```shell-session
$ nodebrew install-binary stable
$ node -v
v7.1.0
$ npm -v
3.10.9
```


## nightmareのインストール
electronとnightmareを追加する。
ついでにxvfbの起動ツールxvfb-maybeをインストールする。

```shell-session
$ npm install -g --save-dev electron nightmare
```
nightmareのページにある動作確認サンプルを動かしてみる

```shell-session
$ vi example.js
var Nightmare = require('nightmare');
var nightmare = Nightmare({ show: true });

nightmare
  .goto('http://yahoo.com')
  .type('form[action*="/search"] [name=p]', 'github nightmare')
  .click('form[action*="/search"] [type=submit]')
  .wait('#main')
  .evaluate(function () {
    return document.querySelector('#main .searchCenterMiddle li a').href
  })
  .end()
  .then(function (result) {
    console.log(result)
  })
  .catch(function (error) {
    console.error('Search failed:', error);
  });
$ DEBUG=* node example.js
nightmare queuing process start +0ms
nightmare queueing action "goto" for http://www.yahoo.com +127ms
nightmare queueing action "type" +13ms
nightmare queueing action "click" +0ms
nightmare queueing action "wait" +0ms
nightmare queueing action "evaluate" +0ms
nightmare queueing action "screenshot" +1ms
nightmare running +1ms
nightmare electron child process exited with code 1: general error - you may need xvfb +143ms
nightmare electron child process not started yet, skipping kill. +2ms
```

## 仮想Xウィンドウ越しに実行
```shell-session
$ xvfb-run node example.js
```

URLを適当なローカルサイトに変えたら、
ちゃんとアクセスしてるっぽい

はっきり言って環境に選択肢がある人はさっさと別のOS用意してやることを推奨。

------------------- ↓ 後書はここから ↓-------------------
ヾ(・ω<)ﾉ"　三三三●　ⅱⅲ コロコロ♪

----

尋常じゃなく苦労したのはやっぱりgcc周りだろう。
正直、こんだけ苦労してやる必要あったのかと思えるぐらい。

ここではこの場で発生したエラーを紹介しよう

## nightmare実行後のlibXssエラー
```shell-session
$ DEBUG=* node nightmare.js
・・・
  nightmare running +1ms
electron:stderr /home/dozo/.nodebrew/node/v5.5.0/lib/node_modules/electron/dist/electron:
 error while loading shared libraries: libXss.so.1:
 cannot open shared object file: No such file or directory +63ms
  nightmare electron child process exited with code 127: command not found 
   - you may not have electron installed correctly +7ms
  nightmare electron child process not started yet, skipping kill 
```

スクリーンセーバモジュールが足りないらしい
それを入れればクリア

```shell-session
$ sudo yum install libXScrnSaver-devel
```

## nightmare実行後のGLIBCXX_3.4.15エラー
```shell-session
$ DEBUG=* node nightmare.js
・・・
  nightmare running +1ms
  electron:stderr /home/dozo/.nodebrew/node/v5.5.0/lib/node_modules/electron/dist/electron: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.15' not found (required by /home/dozo/.nodebrew/node/v5.5.0/lib/node_modules/electron/dist/electron) +201ms
  electron:stderr /home/dozo/.nodebrew/node/v5.5.0/lib/node_modules/electron/dist/electron: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.14' not found (required by /home/dozo/.nodebrew/node/v5.5.0/lib/node_modules/electron/dist/electron) +2ms
  electron:stderr /home/dozo/.nodebrew/node/v5.5.0/lib/node_modules/electron/dist/electron: /usr/lib64/libstdc++.so.6: version `CXXABI_1.3.5' not found (required by /home/dozo/.nodebrew/node/v5.5.0/lib/node_modules/electron/dist/electron) +1ms
  electron:stderr /home/dozo/.nodebrew/node/v5.5.0/lib/node_modules/electron/dist/electron: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.15' not found (required by /home/dozo/.nodebrew/node/v5.5.0/lib/node_modules/electron/dist/libnode.so) +15ms
  nightmare electron child process exited with code 1: general error - you may need xvfb +72ms
  nightmare electron child process not started yet, skipping kill. +2ms
```

これマジきつかった～。
このサイトなかったら詰んでた

[CentOS6 の libstdc++ を更新する](https://www.saintsouth.net/blog/update-libstdcpp-on-centos6/)

今回はldconfigでドバーっと登録したけど、
神経質な人は上記ページのようにシンボリックリンクを差し替えるとよい


## nightmare実行後の undefined symbol: g_bytes_unref エラー
```shell-session
$ DEBUG=* node nightmare.js
・・・
  nightmare running +1ms
  electron:stderr /home/dozo/.nodebrew/node/v5.5.0/lib/node_modules/electron/dist/electron: symbol lookup error: /home/dozo/.nodebrew/node/v5.5.0/lib/node_modules/electron/dist/electron: undefined symbol: g_bytes_unref
```

長時間のビルドの末実行した後に出たエラーだったので気絶しそうになったわ。
glibcのバージョン2.32以降じゃなきゃダメらしく、
yumで入れた2.28では対応不可だった。
こっちはビルドしてからどうしようって感じやった。