これもたまに話題になる「CLI/cronとかからSlackとかへの通知」のためのスクリプトです。
スクリプトそのものよりは、curlでのAPIを叩く動作や、そのためのjqの利用Tipsが有用じゃないかな、というところです。
経緯
まだ(いまも)シェルスクリプトとかに不慣れな頃、「作業完了とかでの通知があるといいな」と思い、調べてみたが、それぞれの手法について、自分の環境に上手くフィットさせれなく、使えていなかった。
それから幾星霜(1年くらい?)、自分の環境に向いたツールやスクリプトなど状況を用意できたので、公開する。
なんらかのシェルスクリプトの動作完了通知を好きなメッセージングサービス経由で通知してもらえるのと、それを簡単に切り替え可能なのが良いところ
大枠の特徴
- XMPP/SlackやTwitter...etcへ通知を行うためのスクリプト
- 自分の秘密情報は分離している
- が、個人の秘密情報に依存するので、システムワイドな通知には使いにくい(ex.cronでのジョブ完了など)
- 日本語も通る(常にiconvでUTF-8にしている、ので多分環境は選ばないとは思う)
- 使うツールは、curl,iconv,jq,sed,gpgなのでPerl/Python/Rubyなどがなくても?どうにかなる(jqを便利ツールとして使っているけど)
詳細
XMPP
2017/12/06 追記
閉鎖されたそうです。(im.kayac.com was closed at Oct 31, 2017.)
以降は知見のために残します。
カヤックが提供している(放置されてるかも?、2017時点で動かないっぽいorz)のXMPPブリッジサービスim.kayac.comに通知を投げてXMPPへ流すスクリプト。
日本語を通すためにUTF-8をurlencodeするのだが、curlではうまくいかないのでjqの@uri
を利用する。
あとjqの値抽出はダブルクォーテーションでくくられるので、それは除去する。rawアウトプットだとクォートされないが、その代り変換もないのでうれしくなかったりする。
変換済みだし、data-urlencode/data-binaryじゃなくて、どっちもdata-asciiでもいいかもしれないけど...まあいいか。
#!/bin/bash
URL="http://im.kayac.com/api/post/<username>"
# import im.kayac.com API Token
api_key=$(cat 秘密鍵)
# notify message for XMPP
arg="$*"
if [ -z "${arg}" ];then
message="notice from ${HOSTNAME:none}"
else
message="${arg:none}"
fi
message=$(echo "{\"value\":\"${message}\"}" | iconv -t UTF-8 | jq -a -M '.value | @uri' | sed -e 's/"\([^"]*\)"/\1/i' )
# jq' output are quoted "..."
# remove using sed regex
# debug
# --verbose
# --trace-ascii /dev/stdout
# if need insecure SSL/TLS
# --insecure
curl \
--request POST \
--silent \
--data-urlencode "password=${api_key}" \
--data-binary "message=${message}" \
$URL > /dev/null
# if output is not use, pipe to null
# > /dev/null
# if output is used, echo "" for treat console
# echo ""
例によってバッチのラッパー
@echo off
bash %~dp0notify-xmpp.sh %*
引数は%0
はバッチファイル自身なので、入れない。
Slack/Twitter...
IFTTTが提供しているMakerチャンネルを利用して、通知を行う。
ここの例はSlack宛てにしているが、IFTTTで連携できれば、なんでもできる。
(Twitterとかのパブリックへ出す時はホスト名とかは入れないほうがいいか)
中を流用したのでXMPPと同じくjqを経由している。こちらではUTF-8を\uxxx
でエスケープする必要があるため@text
を使う。
なおPOSTデータはjsonなのだが、これ自体をどうにかjqで作れたらよかったのだが、うまくいかなかった。
altとなっているのは、XMPPと同じ流れで一度文字列のダブルクォートを除去するパターン。どの道ダブルクォートでくくるので、コメントのみ残してある。
GyazoでキャプったIFTTTのレシピ画像、サンプルとして
2017/12/06 追記
GnuPGのstableが2.2系になり、gpg-agent
常用になったりなど変化があり、パスフレーズをコンソールから確認する(agentでキャッシュはされる)という風に調整しています。
サイレント動作については当然ですがそのまま動きます
#!/bin/bash
# Event check
event="$1"
if [ -z "${event}" ];then
# fail
exit 1
fi
# Key
# import IFTTT Maker : key
# plain
# key="$(cat ~/.password-store/Message/ifttt-maker-key)"
# password-store style encrypt
key="$(gpg --pinentry-mode loopback --no-verbose --quiet --decrypt --output - ~/.password-store/Message/ifttt-maker-key.gpg)"
# URL
baseurl="https://maker.ifttt.com/trigger"
keyurl="with/key"
URL="${baseurl}/${event}/${keyurl}/${key}"
# notify message
arg="$2"
if [ -z "${arg}" ];then
message="notice from ${HOSTNAME:none}"
else
message="${arg:none}"
fi
json=$(echo "{\"value\":\"${message}\"}" | iconv -t UTF-8 | jq -a -M '{value1:(.value|@text),value2:"",value3: ""}')
# debug
# --verbose
# --trace-ascii /dev/stdout
# if need insecure SSL/TLS
# --insecure
curl \
--request POST \
--header "Content-Type: application/json; charset=UTF-8" \
--silent \
--data-binary "${json}" \
$URL
# if output is not use, pipe to null
# > /dev/null
# if output is used, echo "" for treat console
echo ""
例えばslack
というイベント名を定義しているなら、以下のようにできる。
#!/bin/bash
source notify-maker.sh slack "$*"
IFTTT上でslackへの通知をするようにイベントを紐付け。これを切り替えることで、違うサービスに出すのを同じもので実現可能(自分はTwitter/Mail/Pushbulletを定義している)
例によってバッチのラッパー
@echo off
bash %~dp0notify-slack.sh %*
同じ