Slack から Hubot 経由で会社にあるパソコンの電源をオンにする

会社の自分用サーバーで Hubot を動かして Slack からの命令でデスクトップパソコンにマジックパケットを飛ばします。

起動せたいパソコンは既に Wake on LAN の設定は終わっていて、スマホWoL クライアントからはマジックパケットを送って起動できるようになっています。
しかしこの方法ではパソコンとスマホが同じネットワーク上にないといけないので、出社してからモバイルルータのスイッチを切り、会社の Wi-Fi に接続されたのを確認してからアプリを起動してマジックパケットを送るというあんまりスマートではない運用でした。
Slack から起動命令を送ることができれば、会社に着く直前でモバイルルータに接続された状態であっても起動命令を送ることができるようになります。
もっとも、パソコンの電源スイッチを押すのは「始業時間くらいになってからでいいんじゃね」という本質的な問題を孕んでいます。

とりあえずその辺はおいといて、今回やった方法については下記の感じで。
環境としては debianKVM 上にセットした FreeBSD 10.3-RELEASE に設定します。

Slack や Hubot の設定に関するほとんどの部分はこちらのブログを参考にしています。

まずは Slack で Hubot Integration の設定をして起動コマンドを発行したいチャンネルに bot アカウントを /invite しておきます。
Hubot Integration の設定で表示される API Token を使うので適当にコピーしておく必要があります。

続いて FreeBSD 側の設定、まずは Node.js のインストール。

$ cd /usr/ports/www/node
$ sudo make config-recursive
$ sudo make install clean-denepds
$ node -v
v6.2.0

さらに npm をインストール。

$ cd /usr/ports/www/npm
$ sudo make config-recursive
$ sudo make install clean-depends
$ npm -v
3.9.2

Hubot のディレクトリを作って Hubot 関連をインストール。

$ cd ~
$ mkdir -p hubot/magic
$ cd ~/hubot/magic

$ sudo npm install -g coffee-script hubot
$ sudo npm install -g yo generator-hubot

Hubot を設定します。 Bot adapterslack にしておけばなんとかなるっぽいです。

$ yo hubot
Owner : Zoar
Bot name : magic
Description : A simple helpful robot for your Company
Bot adapter : slack

Slack と Hubot の疎通ができるか確認するスクリプトを書いて bot を起動します。

$ vi scripts/hello.coffee
module.exports = (robot) ->
   robot.hear /hello/, (msg) ->
      msg.send msg.random [
         'hello',
         'what?'
      ]
$ HUBOT_SLACK_TOKEN=%API TOKEN% ./bin/hubot --adapter slack

%API TOKEN% は Hubot Integration で表示された API Token を使います。
設定したチャンネルで hello を打って bot から反応があれば OK.

続いて Hubot からシェルスクリプトを動かせるかどうか確認します。

$ mkdir scripts/shell
$ vi scripts/shell/test.sh
#!/bin/sh
pwd
whoami
$chmod +x scripts/shell/test.sh
$ vi scripts/slack.coffee
module.exports = (robot) ->
  robot.respond /test_shell/, (msg) ->
    @exec = require('child_process').exec
    command = "sh /home/zoar/hubot/magic/scripts/shell/test.sh"
    msg.send "Command: #{command}"
    @exec command, (error, stdout, stderr) ->
      msg.send error if error?
      msg.send stdout if stdout?
      msg.send stderr if stderr?
$ chmod + x scripts/shell/test.sh

Hubot を再起動して Slack 側で bot に対して test_shell という@コメントを飛ばして bot から実行したコマンドと、Hubot のディレクトリ、 Hubot を実行しているユーザ名が返ってくれば OK.

今度は FreeBSD からマジックパケットを送信する net/wol をインストールします。

$ cd /usr/ports/net/wol/
$ sudo make config-recursive
$ sudo make install clean-depends
$ wol --version 
wol 0.7.1
<snip>

試しにマジックパケットを飛ばして起動させてみます。

$ wol -i 192.168.135.255 00:aa:11:bb:22:cc
Waking up 00:aa:11:bb:22:cc...

これで起動してくれれば Hubot から実行するスクリプトを書きます。

$ vi scripts/shell/wol.sh
#!/bin/sh
echo "Send magic packet to ProDESK600"
wol -i 192.168.135.255 00:aa:11:bb:22:cc
$ chmod +x scripts/shell/wol.sh

次は Slack のレスポンスを担当する Coffee スクリプト

$ vi scripts/slack.coffee
module.exports = (robot) ->
  robot.respond /wol_pc/, (msg) ->
    @exec = require('child_process').exec
    command = "sh /home/zoar/hubot/magic/scripts/shell/wol.sh"
    msg.send "Command: #{command}"
    @exec command, (error, stdout, stderr) ->
      msg.send error if error?
      msg.send stdout if stdout?
      msg.send stderr if stderr?

Hubot を再起動した後 botwol_pc というリプライを飛ばしてパソコンが起動すればOK.

会社最寄りの交差点で信号待ちしてる間に Slack からコメント送れば席に着くまでに起動しててくれると思います。
できればもうちょっと簡単にしたいところですが…。

FreeBSD にしたのは、たまたま動かしてるマシンの中で一番付加の小さいマシンだったからで特に宗教的な意味とかはないです。