背景
サーバー側で起動したスクリプトの結果を何らかの方法で通知したくなることがよくあります。企業として利用する場合には古式ゆかしいメールや、最近ではSlackに通知することもあるかと思います。しかし個人用途で外部メール配信を設定したり、独自にSlackのチームを作ったりするのもなかなか面倒なものです。そこで今回はPushbulletというサービスを使った通知の仕組みを構築してみます。
Pushbulletとは
Pushbulletはどういうサービスなのか?どのようにアカウントを取得するのか?などは他の記事で詳しく紹介されています。
- PCと携帯端末でデータ同期できるアプリ『Pushbullet』の活用法 | ライフハッカー[日本版]
- 「Pushbullet」最高。 パソコン、スマホ間のデータ送信が信じられないほどラクに! : ギズモード・ジャパン
- 第377回 Pushbulletで通知をお手軽にしてみよう:Ubuntu Weekly Recipe|gihyo.jp … 技術評論社
これらを要約するとだいたい下記のとおりです。
- スマートフォンとPCとで下記のデータのやりとりができる。
- テキストメッセージ
- ファイル
- リンク
- SMSをWeb上で管理することができる。
すべての機能がWeb APIで提供されているため、他のサービスと連携させるなどプログラマブルに利用することができます。テキストメッセージ機能を使えば様々な通知を集約することができそうです。
準備
Pushbulletアカウントの取得
PushbulletのWebサイトでアカウントを取得します。GoogleとFacebookの認証を利用することができます。特に難しいことはなかったので、ここでは割愛します。
Pushbullet APIのアクセストークンの取得
Pushbullet APIを介して通知を送るので、APIのアクセストークンを取得しておく必要があります。ログイン後のメニューから「Setting」→「Accout」を選択します。

メインカラムの中で「Access Tokens」という項目を見つけられると思います。

この「Create Access Token」をクリックするとアクセストークンが生成され、その文字列が表示されます。この文字列は2度と表示することはできないのでメモっておきましょう。
通知スクリプト
通知スクリプトを作成します。今回の目的はサーバー側で何らかの処理が実行されたことおよびその処理の実行結果の通知なので、標準出力をパイプで受け取って通知することにしましょう。
通知を作成するのはAPIドキュメントの中のcreate-pushの項目で説明されています。このページでは curl
を用いた通知の例が示されていますが、BashではJSONの扱いなどが死ぬほど面倒なので、Perlで書き直すことにします。今さらPerlかよ、とは言わないように。
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
use HTTP::Tiny;
use Encode;
use Encode::Guess qw/shift-jis euc-jp 7bit-jis/;
use JSON::PP qw/encode_json decode_json/;
my $config = load_config( "$ENV{HOME}/.pushbullet.json" );
my $access_token = $ENV{PUSHBULLET_ACCESS_TOKEN} // $config->{pushbullet_access_token} // "";
my $endpoint = "https://api.pushbullet.com/v2/pushes";
my $title = $ARGV[0];
my $body = "";
while ( <STDIN> ) {
chomp $_;
$body .= "$_\n";
}
my $decoder = Encode::Guess->guess( $body );
if ( ref $decoder ) {
$body = $decoder->decode( $body );
}
my $json_data = {
title => $title,
body => $body,
type => "note",
};
my $headers = {
'Access-Token' => $access_token,
'Content-Type' => 'application/json',
};
my $ua = HTTP::Tiny->new;
my $response = $ua->post( $endpoint, {
'headers' => \%$headers,
'content' => encode_json( $json_data ),
} );
unless ( $response->{success} ) {
print STDERR Dumper $response;
exit 1;
}
exit 0;
sub load_config {
my $file = shift;
return {} unless -f $file;
open my $fh, '<', $file or die $!;
$config = decode_json( join '', <$fh> );
close $fh;
return $config;
}
環境変数からアクセストークンを取得し、第1引数から通知タイトルを取得、標準入力から通知ボディを取得しています。環境変数を設定するのが面倒な場合は、設定ファイル(~/.pushbullet.json
)に記載しておくこともできる親切設計です。
簡単に実装するならこんな感じかと思いますが、エラー処理などをきちんと実装したい人はぜひご自分で。
必須ライブラリ
できるだけ標準ライブラリで構成しましたが、HTTPSの通信のために IO::Socket::SSL
だけはインストールする必要があります。RedHat系なら下記の通りにパッケージをインストールしておけば問題無いでしょう。
$ sudo yum install perl-IO-Socket-SSL
cpanm
でインストールするなら下記の通りです。
$ cpanm IO::Socket::SSL
使用例
長い時間のかかる処理の終了を知らせる
数10分〜数時間かかるようなスクリプトを実行すると、終了時間を知りたかったり、その出力を知りたかったりすることがあります。しかし終了時刻に端末の前にいる可能性は低いので、どこでも通知を得られるPushbulletはうってつけの通知先です。
$ some-command | PUSHBULLET_ACCESS_TOKEN="YOUR_ACCESS_TOKEN" /path/to/pushbullet-pushes.pl "Notification title"
定期実行するスクリプトの実行結果を知らせる
下記のようなファイルを所定のPATHに配置すれば、2ヶ月に1度、早朝4時に cron
で実行してくれます。これくらい処理の間隔が空いていると、ちゃんと実行されているのか不安になります。そんな場合にも実行結果をPushbulletに飛ばすことで安心感を得られるようになります。Pushbulletに通知するロジックを実行スクリプトの中に仕込むこともできますが、標準出力を受け取る仕組みにしたことで、スクリプト内に本質的な処理とは無関係な処理を書かずにすみます。
PUSHBULLET_ACCESS_TOKEN="YOUR_ACCESS_TOKEN"
0 4 1 */2 * root /path/to/something-update.sh | /path/to/pushbullet-pushes.pl "Updated something"
補足
大方の通知システムの根本的な問題として、通知システム自体にトラブルがあった際には通知が届きません。万全を期する場合には外部へのメール配信を設定しておくなどが必要となりますが、今回の目的でそこまでする必要もないでしょう。