いつかエンジニアになりたい

Nothing is too late to start

Hugoで生成した記事をGitHub Pagesで公開する(1)

概要

  • 現在、会社では、GHEを利用しており、「GitHub Pages」が利用できる
  • あまり「GitHub Pages」を利用したことがなかったので、今回、情報を整理してみる
  • 今回の記事では、「GitHub Pages」に整理し、次回の記事で Hugo を利用した記事を公開してみる

GitHub Pages

GitHub Pages」とは

f:id:berukann:20180812150655p:plain

  • GitHub Pages」は、GitHubのレポジトリから直接、静的サイト*1ホスティングできるサービスです
  • GitHub社から提供されており、基本的に無料で利用することができ、OSSのドキュメント等で利用されていることが多いです
  • GitHub Pages」は、静的ページホスティングサービスであるため、PHPRubyPythonなどのサーバーサイドのコードは動作しません

GitHub Pages」の種類

  • GitHub Pages」は、大きく分けて以下の二種類があります
    • ユーザ・グループページ:ユーザ、グループに紐づくページ。ユーザ、グループごとに1つだけ作成できる
    • プロジェクトページ:プロジェクトに紐づくページ。レポジトリごとに1つずつ作成できる
  • ページ毎の「GitHub Pages」は以下の通りになります*2 f:id:berukann:20180812174738p:plain
  • 例えば、ユーザ「berukann」でパブリックのGithubを利用した場合、GHEで独自ドメイン(ghe.beru.io)を利用した場合のURLは以下になります
Domain Type Page Type Repository Name URL
Normal User Page berukann/berukann.github.io https://berukann.github.io/
Normal Project Page berukann/gh-pages-001 https://berukann.github.io/gh-pages-001/
Custom User Page berukann/berukann.ghe.beru.io https://ghe.beru.io/pages/berukann/
Custom Project Page berukann/gh-pages-001 https://ghe.beru.io/pages/berukann/gh-pages-001/

GitHub Pages」で公開されるフォルダについて

  • GitHub Page」で公開されるフォルダは、以下から選択ができます
    • A. [gh-pages] ブランチのルートフォルダ
    • B. [master] ブランチのルートフォルダ
    • C. [master] ブランチのdocsフォルダ配下
  • 以前は [gh-pages] ブランチでしか公開されない仕様だったようですが、現状は「master」ブランチでも公開できます(ただ、現在でも [gh-pages] ブランチでも公開は可能)。詳細は 2016年新機能! GitHubのmasterブランチをWebページとして公開する手順@Qiita を参照にしてください))
  • 公式ページに記載の通り、「GitHub Pages」は、プライベートリポジトリ(GHE除く)であっても、インターネット上に公開されるため注意してください

GitHub Pages」を作成してみる

  • 試しに、以下の流れでテストプロジェクトを作成し、「GitHub Pages」を表示してみる ※ 公開するフォルダは上記の [B] パターン

  • (1)テストリポジトリ(gh-pages-001)を作成する

  • (2)「GitHub Pages」を有効にする
  • (3)テストページを「GitHub Pages」に表示させる

(1)テストリポジトリ(gh-pages-001)を作成する

  • GitHub にアクセスし、右上の「+」より、[New repository] を選択、テストリポジトリを作成する ※ ここでは「gh-pages-001」で作成 f:id:berukann:20180812151513p:plain
  • 今回は、[master] ブランチを公開するため、TerminalにてリポジトリをCloneし、 [master] ブランチを作成しておく
➜  ~ git clone git@github.com:berukann/gh-pages-001.git
Cloning into 'gh-pages-001'...
warning: You appear to have cloned an empty repository.
➜  ~ cd gh-pages-001/
➜  gh-pages-001 git:(master) echo "# gh-pages-001" >> README.md
➜  gh-pages-001 git:(master) git init
➜  gh-pages-001 git:(master) git add README.md
➜  gh-pages-001 git:(master) git commit -m "first commit"
➜  gh-pages-001 git:(master) git remote add origin git@github.com:berukann/gh-pages-001.git
➜  gh-pages-001 git:(master) git push -u origin master

(2)「GitHub Pages」を有効にする

  • 作成したリポジトリの [Settings] を選択し、「GitHub Pages」が「None」になっていることを確認 f:id:berukann:20180915115754p:plain
  • [Select source] にて [master branch] を選択し、[Save]を実施する。これで「GitHub Pages」が有効になる f:id:berukann:20180812152554p:plain
  • 再度、[Settings]->[GitHub Pages] を確認すると、URLが表示されてことを確認 f:id:berukann:20180812152735p:plain
  • ブラウザから上記URLにアクセスし、「404. There isn't a GitHub Pages site here.」が表示されることを確認 f:id:berukann:20180812153410p:plain
  • 補足:「GitHub Pages」を有効にしていない状態で上記URLにアクセスした場合、「404. File not found.」が表示されます f:id:berukann:20180812153545p:plain

(3)テストページを「Github Pages」に表示させる

  • Terminalにて、上記で作成したリポジトリをクローンし、テストページをプッシュする
➜  ~ cd gh-pages-001/
➜  gh-pages-001 git:(master) git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
➜  gh-pages-001 git:(master) vim index.html
➜  gh-pages-001 git:(master) cat index.html
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>GitHub Pages Test</title>
    </head>
    <body>
        <main>
            <h1>GitHub Pages Test</h1>
        </main>
    </body>
</html>
➜  gh-pages-001 git:(master) git add .
➜  gh-pages-001 git:(master) git commit -m "second commit."
➜  gh-pages-001 git:(master) git push origin master
  • GitHubのページにアクセスし、正常にテストページが表示されていることを確認 f:id:berukann:20180812154710p:plain

補足:[gh-pages] ブランチで作成した場合の挙動について

  • よくブログに書かれている [gh-pages] ブランチでプッシュした場合の挙動についても念の為、確認した
  • レポジトリ設定から「GitHub Pages」を有効にしないまま、「gh-pages」ブランチにプッシュしてみたが、「GitHub Pages」は正常に表示された
  • GitHub Pages」の [Settings] -> [GitHub Pages] を確認すると、[Select source] に [gh-pages branch] が追加されていた f:id:berukann:20180812155830p:plain
  • 公式ドキュメントで確認すると、「gh-pages」ブランチについて記載もあり、未対応になったわけではなさそうだが、わざわざ利用する必要もなさそう

まとめ

  • GitHub Pages」は、[master]、[gh-pages] ブランチ、もしくは、[master] ブランチの docs フォルダを公開フォルダとして指定できる
  • 次回は、静的ジェネレータである「Hugo」を利用した記事を [GitHub Pages] で公開する方法について整理する

*1:静的サイトとはHTMLベースのサイトであり、事前に生成したページを表示するだけなので、サーバー負荷が低く、高速に動作する

*2:GHEなどで、独自ドメインを設定している場合、URLが変わるため注意してください。詳細は 公式ページ を参照してください

「botpress」でSlackBotを作成してみる

はじめに

  • どうも。業務では Javascript を利用しないので、SlackBotを作るときはもっぱら、無理矢理にでも Python で書くのは私です
  • 今日、たまたま会社の先輩が「Botpress」に反応していて、調べてみるとダッシュボードがかっこよかったので、どんな感じのツールか試してみました
  • 基本的にはほぼほぼチュートリアルのままなので、気になる方はドキュメントを読んでいただけると幸いです

botpressとは

f:id:berukann:20180219232139p:plain

インストール

  • 実行環境は「macOS High Sierra」になり、インストールしたツールは以下になります
    • nodebrew (version: 0.9.8
    • node.js (version: 9.5.0
    • ngrock (version: 2.2.8
    • botpress (verssion: 1.1.13

インストール(nodebrew+node.js)

  • 「botpress」をインストールするために node.js が必要なのでインストールする
  • 今後のことも考えて、node.js は nodebrew でインストールする
  • node.js のバージョンは 4.6 以上であればいいらしく、最新版をインストールしておく
$ curl -L git.io/nodebrew | perl - setup
$ echo PATH=$HOME/.nodebrew/current/bin:$PATH >> .zshrc
[daicho]% nodebrew list
not installed
current: none
[daicho]% nodebrew install-binary latest
Fetching: https://nodejs.org/dist/v9.5.0/node-v9.5.0-darwin-x64.tar.gz
######################################################################## 100.0%
Installed successfully
[daicho]% nodebrew use latest
use v9.5.0
[daicho]% nodebrew list
v9.5.0
current: v9.5.0
[daicho]% node -v
v9.5.0

インストール(botpress)

[daicho]% npm install -g botpress
npm WARN deprecated nodemailer@2.7.2: All versions below 4.0.1 of Nodemailer are deprecated. See https://nodemailer.com/status/
npm WARN deprecated email-templates@2.7.1: 📫  Please upgrade to v3.1.5 (v3.0.x had a core bug with attachments and v3.1.5 now supports Node v6.4.0+). Also read the breaking changes for upgrading from v2 to v3 at https://github.com/niftylettuce/email-templates#v3-breaking-changes 📫
/Users/daicho/.nodebrew/node/v9.5.0/bin/bp -> /Users/daicho/.nodebrew/node/v9.5.0/lib/node_modules/botpress/bin/botpress
/Users/daicho/.nodebrew/node/v9.5.0/bin/botpress -> /Users/daicho/.nodebrew/node/v9.5.0/lib/node_modules/botpress/bin/botpress
> fsevents@1.1.3 install /Users/daicho/.nodebrew/node/v9.5.0/lib/node_modules/botpress/node_modules/fsevents
> node install
[fsevents] Success: "/Users/daicho/.nodebrew/node/v9.5.0/lib/node_modules/botpress/node_modules/fsevents/lib/binding/Release/node-v59-darwin-x64/fse.node" is installed via remote
> sqlite3@3.1.13 install /Users/daicho/.nodebrew/node/v9.5.0/lib/node_modules/botpress/node_modules/sqlite3
> node-pre-gyp install --fallback-to-build       
[sqlite3] Success: "/Users/daicho/.nodebrew/node/v9.5.0/lib/node_modules/botpress/node_modules/sqlite3/lib/binding/node-v59-darwin-x64/node_sqlite3.node" is installed via remote       
> nodemon@1.15.0 postinstall /Users/daicho/.nodebrew/node/v9.5.0/lib/node_modules/botpress/node_modules/nodemon
> node -e "console.log('\u001b[32mLove nodemon? You can now support the project via the open collective:\u001b[22m\u001b[39m\n > \u001b[96m\u001b[1mhttps://opencollective.com/nodemon/donate\u001b[0m\n')" || exit 0     
Love nodemon? You can now support the project via the open collective:
> https://opencollective.com/nodemon/donate      
npm WARN react-jsonschema-form@0.49.0 requires a peer of react@^15.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN react-codemirror@1.0.0 requires a peer of react@>=15.5 <16 but none is installed. You must install peer dependencies yourself.
npm WARN react-codemirror@1.0.0 requires a peer of react-dom@>=15.5 <16 but none is installed. You must install peer dependencies yourself.       
+ botpress@1.1.13
added 957 packages in 35.529s
[daicho]% botpress --version
1.1.13
[daicho]% botpress init test-bot
[botpress]
Hey there, thanks for using botpress!
We'll walk you through the creation of your new bot.
For more information or help, please visit http://github.com/botpress/botpress
---------------
name: (test-bot)
description: Say hello World
author: daicho
version: (0.0.1)
[botpress]       please wait, we are installing everything for you...
npm WARN deprecated email-templates@2.7.1: 📫  Please upgrade to v3.1.5 (v3.0.x had a core bug with attachments and v3.1.5 now supports Node v6.4.0+). Also read the breaking changes for upgrading from v2 to v3 at https://github.com/niftylettuce/email-templates#v3-breaking-changes 📫
npm WARN deprecated nodemailer@2.7.2: All versions below 4.0.1 of Nodemailer are deprecated. See https://nodemailer.com/status/

> fsevents@1.1.3 install /Users/daicho/test-bot/node_modules/fsevents
> node install

[fsevents] Success: "/Users/daicho/test-bot/node_modules/fsevents/lib/binding/Release/node-v59-darwin-x64/fse.node" is installed via remote

> sqlite3@3.1.13 install /Users/daicho/test-bot/node_modules/sqlite3
> node-pre-gyp install --fallback-to-build

[sqlite3] Success: "/Users/daicho/test-bot/node_modules/sqlite3/lib/binding/node-v59-darwin-x64/node_sqlite3.node" is installed via remote

> nodemon@1.15.0 postinstall /Users/daicho/test-bot/node_modules/nodemon
> node -e "console.log('\u001b[32mLove nodemon? You can now support the project via the open collective:\u001b[22m\u001b[39m\n > \u001b[96m\u001b[1mhttps://opencollective.com/nodemon/donate\u001b[0m\n')" || exit 0

Love nodemon? You can now support the project via the open collective:
 > https://opencollective.com/nodemon/donate

npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN react-codemirror@1.0.0 requires a peer of react@>=15.5 <16 but none is installed. You must install peer dependencies yourself.
npm WARN react-codemirror@1.0.0 requires a peer of react-dom@>=15.5 <16 but none is installed. You must install peer dependencies yourself.
npm WARN react-jsonschema-form@0.49.0 requires a peer of react@^15.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN test-bot@0.0.1 No repository field.
npm WARN test-bot@0.0.1 license should be a valid SPDX license expression

added 958 packages in 22.682s
[botpress]       OK installation has completed successfully
[botpress]       now run `bp start` in your terminal
[daicho]% cd test-bot
[daicho]% ls
LICENSE            content.yml        index.js           node_modules/      package.json
botfile.js         data/              modules_config/    package-lock.json
[daicho]% botpress start
20:34:32 - info: Starting botpress version 1.1.13
20:34:33 - verbose: [UMM] Enabled for slack
20:34:33 - info: Loaded botpress-slack, version 1.0.23
20:34:33 - verbose: [UMM] Enabled for web
20:34:33 - info: Loaded botpress-web, version 1.2.3
20:34:33 - info: Loaded 2 modules
20:34:33 - debug: Loading middleware: UMM.instrumentation
20:34:33 - debug: Loading middleware: hear
20:34:33 - debug: Loading middleware: conversations
20:34:33 - debug: Loading middleware: slack.sendMessages
20:34:33 - debug: Loading middleware: web.sendMessages
20:34:33 - debug: Loading middleware: fallback
20:34:33 - info: Bot launched. Visit: http://localhost:3000

「botpress」でSlackBotを作成する

  • botpressがインストールできたので、早速、SlackBotを作成してみる
  • 「botpress」でのSlackBotの作成方法は、「botpress」のSlackモジュールのドキュメントに記載の通りになります
  • 主に必要な作業は以下になりますが、今回はテストなので、ドキュメント通りにngrockを利用しています
    • (1)botpressにSlackモジュールをインストールする
    • (2)ngrockを利用して、ローカルホストを外部からアクセスできるようにする
    • (3)SlackBot用にSlack側でアプリを作成し、設定する
    • (4)作成した内容を元にbotpress側に登録する
    • (5)SlackBotの動作確認をする

(1)botpressにSlackモジュールをインストールする

  • ブラウザで「http://localhost:3000」にアクセスし、サイドバーの「Modules」を選択し、検索バーに「Slack」と入力して、Slackのコネクターをインストールする
  • CLIから実施したい場合は、以下のコマンドでも可能
botpress install slack

(2)ngrockを利用して、ローカルホストを外部からアクセスできるようにする

  • ngrock」は、ローカルで動作するアプリケーションをトンネリングして、外部からアクセスできるようにするサービス
  • 今回は、ローカルに立てたbotpress(http://localhost:3000)に外部からアクセスできるようにするために利用する
  • Basic認証が利用したかったので、アカウント登録を実施しました ※Basic認証とか利用しない場合はアカウント登録不要なので、そのままngrok http 3000を実行して下さい
  • ブラウザよりngrockにアクセスしアカウントを作成。ダッシュボードからAuthTokenを追加するコマンドを確認し、ターミナルにて実行する
[daicho]% brew cask install ngrok
==> Satisfying dependencies
==> Downloading https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-darwin-amd64.zip
######################################################################## 100.0%
==> No checksum defined for Cask ngrok, skipping verification
==> Installing Cask ngrok
==> Extracting nested container ngrok
==> Linking Binary 'ngrok' to '/usr/local/bin/ngrok'.
🍺  ngrok was successfully installed!
[daicho]% ngrok authtoken XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Authtoken saved to configuration file: /Users/daicho/.ngrok2/ngrok.yml
[daicho]% ngrok http --auth='admin:passw0rd' 3000 
  • 以下の画面が出力され、ForwardingされているURL(例: http://82aaf557.ngrok.io)にアクセスすると、http://localhost:3000と同様の画面が出力されることを確認する ※ Basic認証上記で入力したID/PASS f:id:berukann:20180220004553p:plain
  • 上記のコマンドは、実行毎に新しいURLになるため、一度、実行したらそのままにしておく

(3)SlackBot用にSlack側でアプリを作成し、設定する

  • Slackにログインした状態で「Create Slack App」にアクセスし、新規アプリを登録する
  • [App Name]にアプリ名、[Development Slack Workspace]にBotを作成したいSlackを選択する f:id:berukann:20180220005257p:plain
  • 左メニューより「Basic Information」を選択し、Client ID と Client Secret を確認する
  • 左メニューより「OAuth & Permissions」を選択し、Redirect URLsを追加する
  • 左メニューより「Bot Users」を選択し、Botユーザを作成する f:id:berukann:20180220010537p:plain
  • 左メニューより「Interactive Components」を選択し、Request URLを記載し、「Enable Interactive Components」を選択する

(4)作成した内容を元にbotpress側に登録する

  • ブラウザより「botpress」にアクセスし、(3)で確認した内容を元に記載し、「Authenticate & Connect」を選択する f:id:berukann:20180220012818p:plain
  • 正常に進むと、以下のような画面がでるので、Botがポストしたいチャンネルを選択し、「Authorize」を選択する ※今回はテスト用のチャンネル「testbot-room」を事前に作成 f:id:berukann:20180220013439p:plain
  • botpressの画面に戻されて、API token や Bot token が追加されていたら成功 f:id:berukann:20180220013829p:plain

(5)SlackBotの動作確認をする

  • (4)で認証したチャンネルを確認すると作成したintegrationが追加されている f:id:berukann:20180220014124p:plain
  • 対象のチャネルにボットユーザを招待して、hiというと返事してくれる f:id:berukann:20180220014414p:plain

SlackBotをカスタマイズする

  • はい。ここまでは、デフォルトのBotを起動しただけなので、カスタマイズしてみる
  • 「botpress」は、botpress init [bot-name] を実行するとファイルが自動されるが、中でも以下のファイルが重要
    • index.js
      • Botのロジックを記述するファイル
    • content.yaml
      • Botが話したい会話内容をすべて記載するファイル
      • UMM (Universal Message Markdown)と呼ばれ、Botpress特有のファイル
    • botfile.js
      • Botの設定ファイル。ファイルパスとか設定ファイル名とかを記載
  • 詳細は公式ドキュメントのfoundamentalsを確認して下さい

修造Botを作ってみる

  • 試しに hubot-syuzo みたいな修造Botを書いてみる
  •  一度、「botpress」をCtrl-C,Ctrl-Cで停止する ※ ngrockは停止しない
  • index.jsに以下のコードを記載する
/*
  CONGRATULATIONS on creating your first Botpress bot!
*/
module.exports = function(bp) {
  bp.hear({
        platform: 'slack',
        type: 'message',
        text: /(無理|むり|ムリ)|(でき|出来)(ない|ません|ん)/i } , (event, next) => {¬
        event.reply('#syuzo-img-link')
  })
}
  • content.ymlに以下のコードを記載後に、botpress startを再実行する
syuzo-img-link:
  - text:
    - "http://i.imgur.com/lCvSmkc.jpg"
    - "http://i.imgur.com/wRuO0T6.png"
    - "http://i.imgur.com/9pJcmPA.jpg"
    - "http://i.imgur.com/JoFiX17.jpg"
    - "http://i.imgur.com/0GJdUlW.jpg"
    - "http://i.imgur.com/cxLWi2Q.jpg"
    - "http://i.imgur.com/ht6Ng0J.jpg"
    - "http://i.imgur.com/p85gjPX.jpg"
    - "http://i.imgur.com/NDikSI4.jpg"
    - "http://i.imgur.com/UrFocgg.jpg"
    - "http://i.imgur.com/vLvuVqv.jpg"
    - "http://i.imgur.com/BCOFvKK.jpg"
    - "http://i.imgur.com/nNMuElm.png"
    - "http://i.imgur.com/pJP3lBn.jpg"
    - "http://i.imgur.com/5HhGuXB.jpg"
    - "http://i.imgur.com/RyLBvgs.jpg"
    - "http://i.imgur.com/MWEsCFG.jpg"
    - "http://i.imgur.com/3jEkEvI.jpg"
    - "http://i.imgur.com/ftZsjy3.jpg"
    - "http://i.imgur.com/QKQft3B.jpg"
    - "http://i.imgur.com/VNPx3B4.jpg"
    - "http://i.imgur.com/AD8tHQV.jpg"
    - "http://i.imgur.com/OMeB9Sf.png"
    - "http://i.imgur.com/3jcYzDR.jpg"
    - "http://i.imgur.com/E7BGbel.jpg"
    - "http://i.imgur.com/B7Op7MS.jpg"
    - "http://i.imgur.com/TbZkSrI.jpg"
    - "http://i.imgur.com/pDmMheZ.jpg"
    - "http://i.imgur.com/Mj81q08.jpg"
    - "http://i.imgur.com/xhOnNwd.jpg"
    - "http://i.imgur.com/HGpEk8E.jpg"
  • Slackで無理と発言すると反応する。Javascript力がなさすぎて、サンプルコードより劣化したコードになってしまった f:id:berukann:20180220104118p:plain

補足:他のモジュール「analytics」も試す

  • ChatbotのWordpressを目指しているだけあって、Connecter以外にもモジュールはありそう ※ npmのパッケージで検索すると全部で52個くらい?
  • 試しにUIから「analytics」をインストールしてみると、なんかかっこいいUIキタ━━━━(゚∀゚)━━━━!! f:id:berukann:20180220105236p:plain
  • ちなみに何か設定がいるのか、botpressでエラーを吐きまくってた
10:51:22 - info: slack connector is authenticated
10:51:22 - info: slack connector is connected
10:51:25 - error: Unhandled Rejection in Promise:  Promise {
  _bitField: 18087936,
  _fulfillmentHandler0: TypeError: Cannot read property 'startsWith' of undefined
    at Object.saveInteractionOut [as saveOutgoing] (/Users/daicho/test-bot/node_modules/botpress-analytics/bin/webpack:/src/db.js:68:15)
    at outgoingMiddleware (/Users/daicho/test-bot/node_modules/botpress-analytics/bin/webpack:/src/index.js:40:8)
    at exec (/Users/daicho/test-bot/node_modules/mware/index.js:50:23)
    at Function.run (/Users/daicho/test-bot/node_modules/mware/index.js:63:7)
    at Object.dispatch (webpack-internal:///54:74:10)
    at Object.eval [as sendOutgoing] (webpack-internal:///54:197:31)
    at eval (webpack-internal:///72:365:28)
    at tryCatcher (/Users/daicho/test-bot/node_modules/bluebird/js/release/util.js:16:23)
    at Object.gotValue (/Users/daicho/test-bot/node_modules/bluebird/js/release/reduce.js:155:18)
    at Object.gotAccum (/Users/daicho/test-bot/node_modules/bluebird/js/release/reduce.js:144:25)
    at Object.tryCatcher (/Users/daicho/test-bot/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/Users/daicho/test-bot/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (/Users/daicho/test-bot/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromiseCtx (/Users/daicho/test-bot/node_modules/bluebird/js/release/promise.js:606:10)
    at Async._drainQueue (/Users/daicho/test-bot/node_modules/bluebird/js/release/async.js:138:12)
    at Async._drainQueues (/Users/daicho/test-bot/node_modules/bluebird/js/release/async.js:143:10)
    at Immediate.Async.drainQueues [as _onImmediate] (/Users/daicho/test-bot/node_modules/bluebird/js/release/async.js:17:14)
    at runCallback (timers.js:756:18)
    at tryOnImmediate (timers.js:717:5)
    at processImmediate [as _immediateCallback] (timers.js:697:5),
  _rejectionHandler0: undefined,
  _promise0: undefined,
  _receiver0: undefined } Reason: TypeError: Cannot read property 'startsWith' of undefined
    at Object.saveInteractionOut [as saveOutgoing] (/Users/daicho/test-bot/node_modules/botpress-analytics/bin/webpack:/src/db.js:68:15)
    at outgoingMiddleware (/Users/daicho/test-bot/node_modules/botpress-analytics/bin/webpack:/src/index.js:40:8)
    at exec (/Users/daicho/test-bot/node_modules/mware/index.js:50:23)
    at Function.run (/Users/daicho/test-bot/node_modules/mware/index.js:63:7)
    at Object.dispatch (webpack-internal:///54:74:10)
    at Object.eval [as sendOutgoing] (webpack-internal:///54:197:31)
    at eval (webpack-internal:///72:365:28)
    at tryCatcher (/Users/daicho/test-bot/node_modules/bluebird/js/release/util.js:16:23)
    at Object.gotValue (/Users/daicho/test-bot/node_modules/bluebird/js/release/reduce.js:155:18)
    at Object.gotAccum (/Users/daicho/test-bot/node_modules/bluebird/js/release/reduce.js:144:25)
    at Object.tryCatcher (/Users/daicho/test-bot/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/Users/daicho/test-bot/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (/Users/daicho/test-bot/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromiseCtx (/Users/daicho/test-bot/node_modules/bluebird/js/release/promise.js:606:10)
    at Async._drainQueue (/Users/daicho/test-bot/node_modules/bluebird/js/release/async.js:138:12)
    at Async._drainQueues (/Users/daicho/test-bot/node_modules/bluebird/js/release/async.js:143:10)
    at Immediate.Async.drainQueues [as _onImmediate] (/Users/daicho/test-bot/node_modules/bluebird/js/release/async.js:17:14)
    at runCallback (timers.js:756:18)
    at tryOnImmediate (timers.js:717:5)
    at processImmediate [as _immediateCallback] (timers.js:697:5)
10:51:25 - error: TypeError: Cannot read property 'startsWith' of undefined
    at Object.saveInteractionOut [as saveOutgoing] (/Users/daicho/test-bot/node_modules/botpress-analytics/bin/webpack:/src/db.js:68:15)
    at outgoingMiddleware (/Users/daicho/test-bot/node_modules/botpress-analytics/bin/webpack:/src/index.js:40:8)
    at exec (/Users/daicho/test-bot/node_modules/mware/index.js:50:23)
    at Function.run (/Users/daicho/test-bot/node_modules/mware/index.js:63:7)
    at Object.dispatch (webpack-internal:///54:74:10)
    at Object.eval [as sendOutgoing] (webpack-internal:///54:197:31)
    at eval (webpack-internal:///72:365:28)
    at tryCatcher (/Users/daicho/test-bot/node_modules/bluebird/js/release/util.js:16:23)
    at Object.gotValue (/Users/daicho/test-bot/node_modules/bluebird/js/release/reduce.js:155:18)
    at Object.gotAccum (/Users/daicho/test-bot/node_modules/bluebird/js/release/reduce.js:144:25)
    at Object.tryCatcher (/Users/daicho/test-bot/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/Users/daicho/test-bot/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (/Users/daicho/test-bot/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromiseCtx (/Users/daicho/test-bot/node_modules/bluebird/js/release/promise.js:606:10)
    at Async._drainQueue (/Users/daicho/test-bot/node_modules/bluebird/js/release/async.js:138:12)
    at Async._drainQueues (/Users/daicho/test-bot/node_modules/bluebird/js/release/async.js:143:10)
    at Immediate.Async.drainQueues [as _onImmediate] (/Users/daicho/test-bot/node_modules/bluebird/js/release/async.js:17:14)
    at runCallback (timers.js:756:18)
    at tryOnImmediate (timers.js:717:5)
    at processImmediate [as _immediateCallback] (timers.js:697:5)
  • 気になってbotpress-analyticsのページにいったら、Slackは非対応でした・・・
Support connectors: ** botpress-messenger

まとめ

  • 会社で話題に出た「botpress」を試してみた
  • SaaSとかじゃなくて、オンプレ、ローカルで動かせるのがいい
  • Javascript好きな人にとったらとても良さそう ※それを言い出すと、そもそもhubotとかも・・・
  • まだまだモジュールは少ないけど、今後増えたらもっと便利になりそう
  • ただ、Botは増えていくので統合管理したかったんだけど、そういうツールではなさそう

参考記事:

Zabbix3.4でWindowsOSの自動起動のトリガーを一部のサービスのみ除外する方法

概要

  • Zabbix3.4でWindowsOSのテンプレートを適用した際に自動起動サービスの監視アラートがうざい
    • 例:Service "sppsvc" (Software Protection) is not running (startup type automatic delayed)
    • 例:Service "RemoteRegistry" (Remote Registry) is not running (startup type automatic)
  • ただ、トリガー自体は無効にしたくないため、不要と判断したサービスのみ除外する

環境

  • Zabbix 3.4
  • 監視対象:Windows 2012 R2

問題

  • Windows OS のテンプレートを Windows 2012 R2 に適用した際に自動起動のサービスが起動していない旨の警告がうざい f:id:berukann:20171224032023p:plain

解決策

  • 除外したいサービスのみのディスカバリから除外する。具体的な方法は以下になります
  • [Administration]->[General]を選択し、右のプルダウンから[Regular expressions]を選択する f:id:berukann:20171224032550p:plain
  • [Windows service names for discovery]を選択し、[Expression]に除外したいサービスを追記する
  • 修正前: ^(MMCSS|gupdate|SysmonLog|clr_optimization_v2.0.50727_32|clr_optimization_v4.0.30319_32)$
  • 修正後: ^(MMCSS|gupdate|wuauserv|TrustedInstaller|sppsvc|RemoteRegistry|SysmonLog|clr_optimization_v2.0.50727_32|clr_optimization_v4.0.30319_32)$
  • 監視対象をZabbixから一度消し、再登録すると、除外したサービスがディスカバリされなくなる

参考

「npm install」がエラー「pyenv: python2: command not found」で失敗する

概要

  • npm install 時に python2 周りのエラーが発生してインストールが失敗する
  • pyenv利用環境下で「python2」コマンドが利用できないのが原因

環境

  • macOS Sierra version 10.12.2
  • npm version 4.0.5
  • node version 7.4.0
  • pyenv version 1.0.6

問題

  • npm install 時に以下のエラーがでてインストールが失敗 -「pyenv: python2: command not found」からpython2コマンドがない
➜  dasher git:(master) npm install

> socketwatcher@0.3.0 install /Users/daicho/work/dasher/node_modules/socketwatcher
> node-gyp rebuild

gyp ERR! configure error 
gyp ERR! stack Error: Command failed: /Users/daicho/.pyenv/shims/python2 -c import platform; print(platform.python_version());
gyp ERR! stack pyenv: python2: command not found
gyp ERR! stack 
gyp ERR! stack The `python2' command exists in these Python versions:
gyp ERR! stack   2.7.13
gyp ERR! stack 
gyp ERR! stack 
gyp ERR! stack     at ChildProcess.exithandler (child_process.js:211:12)
gyp ERR! stack     at emitTwo (events.js:106:13)
gyp ERR! stack     at ChildProcess.emit (events.js:191:7)
gyp ERR! stack     at maybeClose (internal/child_process.js:885:16)
gyp ERR! stack     at Socket.<anonymous> (internal/child_process.js:334:11)
gyp ERR! stack     at emitOne (events.js:96:13)
gyp ERR! stack     at Socket.emit (events.js:188:7)
gyp ERR! stack     at Pipe._handle.close [as _onclose] (net.js:501:12)
gyp ERR! System Darwin 16.3.0
gyp ERR! command "/Users/daicho/.nodebrew/node/v7.4.0/bin/node" "/Users/daicho/.nodebrew/node/v7.4.0/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /Users/daicho/work/dasher/node_modules/socketwatcher
gyp ERR! node -v v7.4.0
gyp ERR! node-gyp -v v3.4.0
gyp ERR! not ok 
npm ERR! Darwin 16.3.0
npm ERR! argv "/Users/daicho/.nodebrew/node/v7.4.0/bin/node" "/Users/daicho/.nodebrew/current/bin/npm" "install"
npm ERR! node v7.4.0
npm ERR! npm  v4.0.5
npm ERR! code ELIFECYCLE

npm ERR! socketwatcher@0.3.0 install: `node-gyp rebuild`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the socketwatcher@0.3.0 install script 'node-gyp rebuild'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the socketwatcher package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     node-gyp rebuild
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs socketwatcher
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls socketwatcher
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /Users/daicho/work/dasher/npm-debug.log

原因

  •  pyenvでpython2コマンドを利用できるように設定できておらず、インストール時に利用するpython2コマンドが見つからなかったため
➜  ~ python2 -V
pyenv: python2: command not found

The `python2' command exists in these Python versions:
  2.7.13

解決策

  • python3しかglobalに設定していなかったため、python2もglobalに設定する
  • 以下の記事の通り、pyenvではpython2.x、3.xの両方を設定できる
  • 自分の環境で実施した結果は以下になる
➜  ~ python2 -V
pyenv: python2: command not found

The `python2' command exists in these Python versions:
  2.7.13
➜  ~ pyenv versions  
  system
  2.7.13
* 3.6.0 (set by /Users/daicho/.pyenv/version
➜  ~ pyenv global 3.6.0 2.7.13
➜  ~ pyenv rehash  
➜  ~ python -V
Python 3.6.0
➜  ~ python2 -V
Python 2.7.13
➜  ~ python3 -V
Python 3.6.0
➜  dasher git:(master) npm install

> socketwatcher@0.3.0 install /Users/daicho/work/dasher/node_modules/socketwatcher
> node-gyp rebuild

xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance

xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance

  CXX(target) Release/obj.target/socketwatcher/socket_watcher.o
../socket_watcher.cpp:104:37: warning: 'NewInstance' is deprecated [-Wdeprecated-declarations]
    info.GetReturnValue().Set(cons->NewInstance());
                                    ^
/Users/daicho/.node-gyp/7.4.0/include/node/v8.h:3292:52: note: 'NewInstance' has been explicitly marked deprecated here
  V8_DEPRECATED("Use maybe version", Local<Object> NewInstance() const);
                                                   ^
1 warning generated.
  SOLINK_MODULE(target) Release/socketwatcher.node

> pcap@2.0.0 install /Users/daicho/work/dasher/node_modules/pcap
> node-gyp rebuild

xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance

xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance

  CXX(target) Release/obj.target/pcap_binding/pcap_binding.o
  CXX(target) Release/obj.target/pcap_binding/pcap_session.o
../pcap_session.cc:46:37: warning: 'NewInstance' is deprecated [-Wdeprecated-declarations]
    info.GetReturnValue().Set(cons->NewInstance());
                                    ^
/Users/daicho/.node-gyp/7.4.0/include/node/v8.h:3292:52: note: 'NewInstance' has been explicitly marked deprecated here
  V8_DEPRECATED("Use maybe version", Local<Object> NewInstance() const);
                                                   ^
1 warning generated.
  SOLINK_MODULE(target) Release/pcap_binding.node
dasher@1.1.1 /Users/daicho/work/dasher
└─┬ node-dash-button@0.6.1 
  └─┬ pcap@2.0.0  (git+https://github.com/mranney/node_pcap.git#d920204745c8b00ef4b7a3fe27d902b263cdb70f)
    └── socketwatcher@0.3.0 

参考

shinespark.hatenablog.com

vagrant up時に「mount: unknown filesystem type 'vboxsf'」が発生する

概要

  • VagrantでUbuntu15.04のBoxを利用しようとした際に以下の Error が出た
mount: unknown filesystem type 'vboxsf'
  • boxに「VirtualBox Guest Additions」がインストールされていなかったのが原因だった

環境

問題

  • Ubuntu15.04のVagrantboxを取得し、起動しようとしたが、以下のエラーが発生
% mkdir TestDir; cd $_
% vagrant box add ubuntu15.04 https://github.com/kraksoft/vagrant-box-ubuntu/releases/download/15.04/ubuntu-15.04-amd64.box
% vagrant box list
ubuntu15.04 (virtualbox, 0)
% vagrant init ubuntu15.04
% vagrant up --provider=virtualbox
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'ubuntu15.04'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: TestDir_default_1453617483205_59253
==> default: Fixed port collision for 22 => 2222. Now on port 2200.
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 => 2200 (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2200
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Connection timeout. Retrying...
    default:
    default: Vagrant insecure key detected. Vagrant will automatically replace
    default: this with a newly generated keypair for better security.
    default:
    default: Inserting generated public key within guest...
    default: Removing insecure key from the guest if it's present...
    default: Key inserted! Disconnecting and reconnecting using new SSH key...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
    default: The guest additions on this VM do not match the installed version of
    default: VirtualBox! In most cases this is fine, but in rare cases it can
    default: prevent things such as shared folders from working properly. If you see
    default: shared folder errors, please make sure the guest additions within the
    default: virtual machine match the version of VirtualBox you have installed on
    default: your host and reload your VM.
    default:
    default: Guest Additions Version: 4.3.22_Ubuntu r98236
    default: VirtualBox Version: 5.0
==> default: Mounting shared folders...
    default: /vagrant => /Users/daicho/Work/DevEnv/ubuntu1504/TestDir
Failed to mount folders in Linux guest. This is usually because
the "vboxsf" file system is not available. Please verify that
the guest additions are properly installed in the guest and
can work properly. The command attempted was:
mount -t vboxsf -o uid=`id -u vagrant`,gid=`getent group vagrant | cut -d: -f3` vagrant /vagrant
mount -t vboxsf -o uid=`id -u vagrant`,gid=`id -g vagrant` vagrant /vagrant
The error output from the last command was:
stdin: is not a tty
mount: unknown filesystem type 'vboxsf'

原因

  • GuestOS内に「Virtualbox Guest Additions」がない、もしくはバージョンが違う
  • 実際にログインしてみてもコマンドがない
vagrant@vagrant-ubuntu-trusty:/usr/bin$ vboxsf
vboxsf: command not found

解決策

策1) GuestOS内に「Virtualbox Guest Additions」を手動インストールする

  • GuestOSにSSHログインする
% vboxmanage --version
5.0.10r104061
% vagrant ssh
Welcome to Ubuntu 15.04 (GNU/Linux 3.19.0-15-generic x86_64)
 * Documentation:  https://help.ubuntu.com/
New release '15.10' available.
Run 'do-release-upgrade' to upgrade to it.
Last login: Sun Jan 24 06:43:12 2016 from 10.0.2.2
vagrant@vagrant-ubuntu-trusty:~$
vagrant@vagrant-ubuntu-trusty:~$ wget http://download.virtualbox.org/virtualbox/5.0.14/VBoxGuestAdditions_5.0.14.iso
vagrant@vagrant-ubuntu-trusty:~$ sudo mkdir /media/VBoxGuestAdditions
vagrant@vagrant-ubuntu-trusty:~$ sudo mount -o loop,ro VBoxGuestAdditions_5.0.14.iso /media/VBoxGuestAdditions
vagrant@vagrant-ubuntu-trusty:~$ sudo sh /media/VBoxGuestAdditions/VBoxLinuxAdditions.run
vagrant@vagrant-ubuntu-trusty:~$ rm VBoxGuestAdditions_5.0.14.iso
vagrant@vagrant-ubuntu-trusty:~$ sudo umount /media/VBoxGuestAdditions
vagrant@vagrant-ubuntu-trusty:~$ sudo rmdir /media/VBoxGuestAdditions
vagrant@vagrant-ubuntu-trusty:~$ exit
% vagrant reload
/opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/pre-rubygems.rb:31: warning: Insecure world writable dir /usr in PATH, mode 040777
/opt/vagrant/embedded/gems/gems/bundler-1.10.5/lib/bundler/shared_helpers.rb:78: warning: Insecure world writable dir /usr in PATH, mode 040777
==> default: Attempting graceful shutdown of VM...
==> default: Clearing any previously set forwarded ports...
==> default: Fixed port collision for 22 => 2222. Now on port 2200.
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 => 2200 (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2200
    default: SSH auth method: private key
    default: Warning: Connection timeout. Retrying...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
==> default: Mounting shared folders...
    default: /vagrant => /Users/daicho/Work/DevEnv/ubuntu1504/TestDir
==> default: Machine already provisioned. Run `vagrant provision` or use the `--provision`
==> default: flag to force provisioning. Provisioners marked to run always will still run.

※当たり前ですが公式ページにもインストール手順書いてありました

策2) Pluginの「vagrant-vbguest」をインストールしておく

vagrant-vbguest」を入れてくと、起動時にホスト側の「GuestAdditions」をゲスト側にインストールしてくれる

  • vagrant-vbguest」をインストールする
% sudo vagrant plugin install vagrant-vbguest
% vagrant vbguest --status
GuestAdditions 5.0.10 running --- OK.
  • 通常通り「vagrant up」すると自動でインストールされる
% vagrant up --provider=virtualbox
/opt/vagrant/embedded/gems/gems/vagrant-1.7.4/lib/vagrant/pre-rubygems.rb:31: warning: Insecure world writable dir /usr in PATH, mode 040777
/opt/vagrant/embedded/gems/gems/bundler-1.10.5/lib/bundler/shared_helpers.rb:78: warning: Insecure world writable dir /usr in PATH, mode 040777
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'ubuntu15.04'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: TestDir_default_1453619815489_18864
==> default: Fixed port collision for 22 => 2222. Now on port 2200.
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 => 2200 (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2200
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Connection timeout. Retrying...
    default:
    default: Vagrant insecure key detected. Vagrant will automatically replace
    default: this with a newly generated keypair for better security.
    default:
    default: Inserting generated public key within guest...
    default: Removing insecure key from the guest if it's present...
    default: Key inserted! Disconnecting and reconnecting using new SSH key...
==> default: Machine booted and ready!
GuestAdditions versions on your host (5.0.10) and guest (4.3.22_Ubuntu r98236) do not match.
stdin: is not a tty
Reading package lists...
Building dependency tree...
Reading state information...
linux-headers-3.19.0-15-generic is already the newest version.
linux-headers-3.19.0-15-generic set to manually installed.
The following NEW packages will be installed:
  dkms
0 upgraded, 1 newly installed, 0 to remove and 41 not upgraded.
Need to get 65.5 kB of archives.
After this operation, 351 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu/ vivid/main dkms all 2.2.0.3-2ubuntu3 [65.5 kB]
dpkg-preconfigure: unable to re-open stdin: No such file or directory
Fetched 65.5 kB in 4s (14.9 kB/s)
Selecting previously unselected package dkms.
(Reading database ... 60906 files and directories currently installed.)
Preparing to unpack .../dkms_2.2.0.3-2ubuntu3_all.deb ...
Unpacking dkms (2.2.0.3-2ubuntu3) ...
Processing triggers for man-db (2.7.0.2-5) ...
Setting up dkms (2.2.0.3-2ubuntu3) ...
Copy iso file /Applications/VirtualBox.app/Contents/MacOS/VBoxGuestAdditions.iso into the box /tmp/VBoxGuestAdditions.iso
stdin: is not a tty
mount: /dev/loop0 is write-protected, mounting read-only
Installing Virtualbox Guest Additions 5.0.10 - guest version is 4.3.22_Ubuntu r98236
stdin: is not a tty
Verifying archive integrity... All good.
Uncompressing VirtualBox 5.0.10 Guest Additions for Linux............
VirtualBox Guest Additions installer
Copying additional installer modules ...
Installing additional modules ...
Removing existing VirtualBox DKMS kernel modules ...done.
Removing existing VirtualBox non-DKMS kernel modules ...done.
Building the VirtualBox Guest Additions kernel modules ...done.
Doing non-kernel setup of the Guest Additions ...done.
You should restart your guest to make sure the new modules are actually used
Installing the Window System drivers
Could not find the X.Org or XFree86 Window System, skipping.
An error occurred during installation of VirtualBox Guest Additions 5.0.10. Some functionality may not work as intended.
In most cases it is OK that the "Window System drivers" installation failed.
stdin: is not a tty
Restarting VM to apply changes...
==> default: Attempting graceful shutdown of VM...
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2200
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Connection timeout. Retrying...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
==> default: Mounting shared folders...
    default: /vagrant => /Users/daicho/Work/DevEnv/ubuntu1504/TestDir

まとめ

VirtualBoxのVagrantBoxを作成する際はしっかりとVirtualbox Guest Additionsをいれてあげるのは大事だが、 結局利用するホスト側のバージョンはいろいろなので、プラグイン入れておく。

参考

何となく利用しているComposerの利用方法を再入門する

概要

  • 最近のPHPのパッケージ依存管理で比較的デファクトスタンダードなComposer
  • なんとなく利用していたので利用目的、利用方法を整理する

環境

PHPのパッケージ依存管理ツール

  • Bundler,npmなど他の言語では当たり前のパッケージ依存管理ツールですがPHPには以下があります
  • 歴史的経緯なのかわからないが、PHPには意外にパッケージ管理ツールが少ない
  • Pearは昔から利用されているが、最近はComposerが主流
  • PearとComposerは大きくわけて以下の違いがある
    1. パッケージ管理される範囲 Pearではインストールしたパッケージをシステム全体に適用するのに対し、 Composerはプロジェクト単位に反映するため、root権限等も不要で、 プロジェクトごとにバージョンを変えたりもできる。
    2. クラスオートローディング機能を利用できる クラスオートローディング機能とはPHP5.3から本格的に利用され始めた機能で、 Pearではインストールしたパッケージをrequireやincludeなどで読み込む必要があったが、 Composerでは自動生成されるautoload.phpをrequireするだけで良い。

Composerの利用方法

インストール方法

PHP7をインストールする

vagrant@vagrant-ubuntu-trusty:~$ php --version
The program 'php' is currently not installed. You can install it by typing:
sudo apt-get install php5-cli
vagrant@vagrant-ubuntu-trusty:~$ sudo apt-get install -y software-properties-common
vagrant@vagrant-ubuntu-trusty:~$ sudo LC_ALL=en_US.UTF-8 add-apt-repository ppa:ondrej/php
vagrant@vagrant-ubuntu-trusty:~$ sudo apt-get update -y
vagrant@vagrant-ubuntu-trusty:~$ sudo apt-get install -y php7.0
vagrant@vagrant-ubuntu-trusty:~$ php -v
PHP 7.0.2-4+deb.sury.org~vivid+1 (cli) ( NTS )
Copyright (c) 1997-2015 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2015 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2015, by Zend Technologies

Composerをインストールする

vagrant@vagrant-ubuntu-trusty:~$ curl -sS https://getcomposer.org/installer | php
vagrant@vagrant-ubuntu-trusty:~$ sudo mv composer.phar /usr/local/bin/composer
vagrant@vagrant-ubuntu-trusty:~$ composer --version
Composer version 1.0-dev (837fa805ec9f8dcb1e05e0fca4099f0dab4f1e04) 2016-01-22 19:09:44

Composerの利用方法

基本的な利用の流れ

  • PackagistよりComposerに対応したライブラリを探す
  • パッケージ依存関係を記述したcomposer.jsonを手動で作成するか、以下のコマンドで作成する
composer require twig/twig:~1.8
  • composer.jsonを利用し以下のコマンドでパッケージをインストールする
composer install
<?php
require 'vendor/autoload.php';

例)ComposerでGoutteをインストールしてみる

スクレイピングに利用するGoutteをインストールする

ComposerでGoutteをインストールする
vagrant@vagrant-ubuntu-trusty:~$ mkdir SampleProject1
vagrant@vagrant-ubuntu-trusty:~$ cd SampleProject1/
vagrant@vagrant-ubuntu-trusty:~/SampleProject1$ composer require fabpot/goutte
Using version ^3.1 for fabpot/goutte
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing guzzlehttp/promises (1.0.3)
    Downloading: 100%

  - Installing psr/http-message (1.0)
    Downloading: 100%

  - Installing guzzlehttp/psr7 (1.2.2)
    Downloading: 100%

  - Installing guzzlehttp/guzzle (6.1.1)
    Downloading: 100%

  - Installing symfony/polyfill-mbstring (v1.0.1)
    Downloading: 100%

  - Installing symfony/dom-crawler (v3.0.1)
    Downloading: 100%

  - Installing symfony/css-selector (v3.0.1)
    Downloading: 100%

  - Installing symfony/browser-kit (v3.0.1)
    Downloading: 100%

  - Installing fabpot/goutte (v3.1.2)
    Downloading: 100%

symfony/browser-kit suggests installing symfony/process ()
Writing lock file
Generating autoload files
vagrant@vagrant-ubuntu-trusty:~/SampleProject1$ ls -g
total 28
-rw-rw-r-- 1 vagrant    59 Jan 24 05:38 composer.json
-rw-rw-r-- 1 vagrant 17169 Jan 24 05:38 composer.lock
drwxrwxr-x 7 vagrant  4096 Jan 24 05:38 vendor
vagrant@vagrant-ubuntu-trusty:~/SampleProject1$ composer install
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
Nothing to install or update
Generating autoload files
インストールしたパッケージを利用しスクレイピングしてみる
vagrant@vagrant-ubuntu-trusty:~/SampleProject1$ vim test.php
<?php
require 'vendor/autoload.php';

use Goutte\Client;

$client = new Client();
$crawler = $client->request('GET', 'http://spotlight.pics/ja/');
$crawler->filter('article img')->each(function ($node) {
    print $node->attr('src')."\n";
});
vagrant@vagrant-ubuntu-trusty:~/SampleProject1$ php test.php
http://i4.pixiv.net/c/720x1200/img-master/img/2015/09/18/19/20/42/52586771_p0_master1200.jpg
http://i4.pixiv.net/c/720x1200/img-master/img/2014/08/06/13/59/56/45157527_p0_master1200.jpg
http://i2.pixiv.net/c/720x1200/img-master/img/2014/10/14/21/29/40/46553081_p0_master1200.jpg
http://i1.pixiv.net/c/720x1200/img-master/img/2009/05/23/14/06/38/4391768_p0_master1200.jpg
http://i3.pixiv.net/c/720x1200/img-master/img/2014/06/13/17/47/32/44063774_p0_master1200.jpg
http://i2.pixiv.net/c/720x1200/img-master/img/2008/11/14/00/26/04/2124805_p0_master1200.jpg
http://i1.pixiv.net/c/720x1200/img-master/img/2015/12/22/18/31/08/54165128_p0_master1200.jpg
http://i3.pixiv.net/c/720x1200/img-master/img/2014/11/03/23/14/42/46903258_p0_master1200.jpg
http://i2.pixiv.net/c/720x1200/img-master/img/2013/12/27/09/58/56/40542565_p0_master1200.jpg
http://i4.pixiv.net/c/720x1200/img-master/img/2015/12/14/01/46/04/54032339_p0_master1200.jpg
http://i2.pixiv.net/c/720x1200/img-master/img/2013/07/12/16/11/23/37005801_p0_master1200.jpg
http://i2.pixiv.net/c/720x1200/img-master/img/2008/07/27/05/12/46/1248061_p0_master1200.jpg
http://i2.pixiv.net/c/720x1200/img-master/img/2008/04/26/17/57/13/718657_p0_master1200.jpg
http://i2.pixiv.net/c/720x1200/img-master/img/2010/10/03/01/53/38/13632409_p0_master1200.jpg
http://i1.pixiv.net/c/720x1200/img-master/img/2015/04/30/23/29/00/50115868_p0_master1200.jpg
http://i2.pixiv.net/c/720x1200/img-master/img/2011/01/31/23/45/29/16316625_p0_master1200.jpg
http://i3.pixiv.net/c/720x1200/img-master/img/2009/05/29/00/27/04/4476710_p0_master1200.jpg
http://i3.pixiv.net/c/720x1200/img-master/img/2009/10/30/22/38/52/6899990_p0_master1200.jpg
http://i1.pixiv.net/c/720x1200/img-master/img/2015/05/03/02/19/24/50162100_p0_master1200.jpg
http://i3.pixiv.net/c/720x1200/img-master/img/2014/08/09/00/16/26/45220066_p0_master1200.jpg

Composerのその他の利用方法

Composerでインストールしたパッケージリストを確認する

vagrant@vagrant-ubuntu-trusty:~/SampleProject1$ composer show -i
fabpot/goutte             v3.1.2 A simple PHP Web Scraper
guzzlehttp/guzzle         6.1.1  Guzzle is a PHP HTTP client library
guzzlehttp/promises       1.0.3  Guzzle promises library
guzzlehttp/psr7           1.2.2  PSR-7 message implementation
psr/http-message          1.0    Common interface for HTTP messages
symfony/browser-kit       v3.0.1 Symfony BrowserKit Component
symfony/css-selector      v3.0.1 Symfony CssSelector Component
symfony/dom-crawler       v3.0.1 Symfony DomCrawler Component
symfony/polyfill-mbstring v1.0.1 Symfony polyfill for the Mbstring extension

ローカルのパッケージリストを最新化する

vagrant@vagrant-ubuntu-trusty:~/SampleProject1$ composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
Nothing to install or update
Generating autoload files

パッケージリストからパッケージを探す

vagrant@vagrant-ubuntu-trusty:~/SampleProject1$ composer search phpunit
phpunit/phpunit The PHP Unit Testing framework.
phpunit/phpunit-mock-objects Mock Object library for PHPUnit
phpunit/phpunit-selenium Selenium Server integration for PHPUnit
phpunit/phpunit-story Story extension for PHPUnit to facilitate Behaviour-Driven Development.
phpunit/phpunit-skeleton-generator Tool that can generate skeleton test classes from production code classes and vice versa
phpunit/dbunit DbUnit port for PHP/PHPUnit to support database interaction testing.
phpunit/phpunit-dom-assertions DOM assertions for PHPUnit
phpunit/phpcov CLI frontend for PHP_CodeCoverage
phpunit/php-code-coverage Library that provides collection, processing, and rendering functionality for PHP code coverage information.
phpunit/php-token-stream Wrapper around PHP's tokenizer extension.
phpunit/php-timer Utility class for timing
phpunit/php-file-iterator FilterIterator implementation that filters files based on a list of suffixes.
phpunit/php-text-template Simple template engine.
jbzoo/phpunit PHPUnit toolbox with short assert aliases and useful functions
eher/phpunit Unofficial version of PHPUnit to be handled with Composer.

composer.jsonCLIで更新する

vagrant@vagrant-ubuntu-trusty:~/SampleProject1$ cat composer.json
{
    "require": {
        "fabpot/goutte": "^3.1"
    }
}
vagrant@vagrant-ubuntu-trusty:~/SampleProject1$ composer require phpunit/phpunit
Using version ^5.1 for phpunit/phpunit
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing myclabs/deep-copy (1.5.0)
    Downloading: 100%

  - Installing sebastian/version (1.0.6)
    Downloading: 100%

  - Installing sebastian/resource-operations (1.0.0)
    Downloading: 100%

  - Installing sebastian/global-state (1.1.1)
    Downloading: 100%

  - Installing sebastian/recursion-context (1.0.2)
    Downloading: 100%

  - Installing sebastian/exporter (1.2.1)
    Downloading: 100%

  - Installing sebastian/environment (1.3.3)
    Downloading: 100%

  - Installing sebastian/diff (1.4.1)
    Downloading: 100%

  - Installing sebastian/comparator (1.2.0)
    Downloading: 100%

  - Installing symfony/yaml (v3.0.1)
    Downloading: 100%

  - Installing doctrine/instantiator (1.0.5)
    Downloading: 100%

  - Installing phpdocumentor/reflection-docblock (2.0.4)
    Downloading: 100%

  - Installing phpspec/prophecy (v1.5.0)
    Downloading: 100%

  - Installing phpunit/php-text-template (1.2.1)
    Downloading: 100%

  - Installing phpunit/phpunit-mock-objects (3.0.6)
    Downloading: 100%

  - Installing phpunit/php-timer (1.0.7)
    Downloading: 100%

  - Installing phpunit/php-token-stream (1.4.8)
    Downloading: 100%

  - Installing phpunit/php-file-iterator (1.4.1)
    Downloading: 100%

  - Installing phpunit/php-code-coverage (3.1.0)
    Downloading: 100%

  - Installing phpunit/phpunit (5.1.4)
    Downloading: 100%

sebastian/global-state suggests installing ext-uopz (*)
phpdocumentor/reflection-docblock suggests installing dflydev/markdown (~1.0)
phpdocumentor/reflection-docblock suggests installing erusev/parsedown (~1.0)
phpunit/php-code-coverage suggests installing ext-xdebug (>=2.2.1)
phpunit/phpunit suggests installing phpunit/php-invoker (~1.1)
Writing lock file
Generating autoload files
vagrant@vagrant-ubuntu-trusty:~/SampleProject1$ cat composer.json
{
    "require": {
        "fabpot/goutte": "^3.1",
        "phpunit/phpunit": "^5.1"
    }
}

参考

EI Capitanでsudo付けているOperation not permittedが出た時の対処法

概要

Mac OS X 10.11 EI Capitanで/usr/libexec/配下にファイルを移動しようとした時、 sudo付けてんのに「Operation not permitted」がでて焦った話と対処方法。

原因

  • OS X 10.11 El Capitanから新しく追加されたセキュリティ機能(SIP:System Integrity Protection)「Rootless」のせい。
  • rootユーザーであってもカーネルレベルでアクセス制限がかけられるので、sudoをつけても「/usr」「/sbin」「/System」配下に書き込み操作できない。

対処法

以下の手順でSIP(Rootless)を無効にすることで解決できる。 ※ SIPを無効にするコマンドはリカバーモードでないと実行できないので注意

1: Macを再起動し、[Command+R]を押してリカバリーモードで起動 2: 上部のメニューから[ユーティリティ]->[ターミナル]を選択し、ターミナルを起動 3: 以下のコマンドで現在の「SIP」の状態を確認

% csrutil status
System Integrity Protection status: enabled.

4: 以下のコマンドで「SIP」を無効にし、再起動する

% csrutil disable
Successufully disabled System Integrity Protection. Please restart the machine for the changes to take effect.  
% reboot

5: 通常通りログインし、以下のコマンドで現在の「SIP」の状態を確認

% csrutil status
System Integrity Protection status: disabled.

参考記事

www.starlod.net