botが停止しているのをLINEへ通知するスクリプト

pc関連tips

自動取引botのサポート

仮想通貨自動取引botを使っている人向けの記事です。
勝手に取引してくれて、損したり得したりする自動取引bot。
 私もこちらの記事で作成しています。→bitmex用トレーディングbotを初心者が作ってみた
通常、元気に動き続けてくれるものですが、たまに予期せぬエラーで
停止してしまったりします。
停止するとやばいですよね。このまま放っておいていいポジションならいいですが、
ひょっとしたら既に決済した方がいいのかも…。
もちろんストップ入れているとか、対策済みの注文の場合はそこまで気にしなくていいかもしれませんが、
botが停止してしまったなら、早いところ検知した方がいいのが事実。
その検知のための方法を検討しました。
もっとうまい方法があるのかもしれませんが、一応検知できています。

環境

・aws(cloud9)
・python(bot)+bash(検知)

検知のスクリプト

私が現在使用しているものです。
今のところ問題なく停止検知をしてくれています。
ただ、bot本体をいじれる人向け。
botをいじらなくてよい簡易版(ps検知)も後半で記載しますが、そっちは検知が弱いです。
私のbotは「例外吐いて停止してるがプロセスは残る」状態で止まることが多いので、
プロセスがあるかないかによる検知ではイマイチでした。
そのため、本体がうまく動いていれば…という条件に変更しました。

bot本体に仕込みます

bot本体のloop部分に、定期的に外部ファイルへ書き込む処理を追加します。
#うちのbotは30秒に1回ループするので、頻度的に問題ないのですが、
もし1秒に1回ループなどの高頻度の場合、毎回書き込むのは多いかもしれません。
適宜調整してください。
#もしbotが元々外部ファイルを生成している場合は、それをチェックに使用することも可能かもです。


#import部分に記載
from datetime import datetime as dt

#↓定常ループの中に記載
#「botlog.txt」へ日付を書き込んでいるだけのものです
nowtime = dt.now().strftime('%Y-%m-%d %H:%M:%S')
f = open("botlog.txt", "a")
f.write(str(nowtime))
f.write("
")
f.close()

これがループの中で稼働すると、このように時刻がテキストに記載されていきます。
2018-07-14 14:42:37
2018-07-14 14:43:09
2018-07-14 14:43:43
2018-07-14 14:44:16
2018-07-14 14:44:49
2018-07-14 14:45:22
2018-07-14 14:45:55
2018-07-14 14:46:27
(時刻が必ずしも30秒後ではないのは、httpの戻りとか注文のためsleepが入ったとか
そういった理由によるものです)
そして、結果として、「botlog.txt」ファイルの中身と、タイムスタンプが更新されてゆきます。これが検知の準備です。

チェックスクリプトを作成する

次はチェック側のスクリプトを仕込みます。

コードです。「check.sh」として保存します。

cd /home/ec2-user/environment
if [ -f checklockfile ]; then
 exit;
fi

hantei=`find . -maxdepth 1 -mmin -2 -name "botlog.txt" |wc -l`
if [ $hantei != 0 ]; then
  echo "ikiteru"
else
  echo "sinda"
  curl -X POST -H 'Authorization: Bearer ☆あなたのlineのアクセストークン☆' -F 'message=otita' https://notify-api.line.me/api/notify
  touch checklockfile
fi

これは何をしているかというと、findコマンドで2分以内に更新があった「botlog.txt」というファイルがあるかどうかを判定しています。
あれば何もしません。
無ければ、botがループできていないと判定し、LINEへ通知を行います。
#「2分以内(コードの-mmin -2の指定の部分)」というのは私のbotの更新頻度になんとなく合わせた数値ですので、適宜調整してください。
また、通知を行った際に「checklockfile」というファイルを生成します。
これは何度も通知を行うことを防ぐものです。このファイルがあるうちは再度通知を行いません。

LINEのアクセストークンを取得する

LINEへ通知を行うためには、貴方のラインへのアクセストークンを取得する必要があります。上記コードの、☆あなたのlineのアクセストークン☆としたところに書き込めばOKです。
アクセストークンの取得の仕方です。

1.以下URLにPCからログイン。

https://notify-bot.line.me/ja/

2.マイページを開きます

マイページを開きます。

3.トークンを発行するをクリック

トークンを発行するをクリック

4.名前と宛先を選択して発行する

名前と宛先を選択して発行します。
宛先は、グループも選べるようですが、自身の場合は1:1のところでよいと思います。
#ちなみに、この名前ですが、LINEからの通知に必ず表示されるので、長くするとイラッとすると思います。短めで行きましょう。

5.発行された

発行されました!発行されたトークンをメモしてください。
再度表示することはできないみたいです!

6.トークンをbashに記載

このメモしたトークンをコードに入れてください。
シングルクオートで囲ったりとかは不要です。そのままぺたりと。

curl -X POST -H 'Authorization: Bearer ☆あなたのlineのアクセストークン☆' -F 'message=otita' https://notify-api.line.me/api/notify

検知のジョブを登録する

スクリプトができたら、それをジョブに登録します。
Linux環境では「Cron」と呼ばれるものです。
crontab -e
として、vi環境に入り、以下のように記載します。

*/5 * * * * /home/ec2-user/environment/check.sh > /dev/null 2>&1

5分毎にチェックスクリプトを実行する、という記載になります。
1分毎に検知したければ、一番左の「*/5」を「*」と書き換えます。
「/home/ec2-user/environment/check.sh」はご自身のチェックスクリプトまでの環境と読み替えてください。
かいたら、:wqとして保存します。
crontab -l とすると、Cronへ登録されているリストが確認できます。

botに追記②

チェックスクリプトが作成するロックファイルをbot起動時に削除するよう仕込みます。
これでiphoneからでも気軽に再起動が可能になります。
#AWSはiphoneからログインできるし、botの停止起動程度なら可能です。はやくはないしプログラムなおすのはちょっと無理ゲーっぽいけど…


#import部分に記載してください。
import os

#これは起動時のみ通るところに記載してください。loop内には入れちゃダメ(入れても死なないけど無駄なので…)
#checklockfileがあれば、削除する。無ければ何もしない。
#※パスは環境に合わせて適宜変更してください
try:
    os.remove("/home/ec2-user/environment/checklockfile")
except:
    pass

まとめ

これで一旦完了です。
今のところうまく動いてくれているので、いいかな~という感じ。
もっといろいろな仕組みがあるかもしれません。
良いものが見つかれば改良していきたいと思います!
まあ、botが死なないのが一番なんですけど…!!
次は、落ちたら検知して通知して勝手に起動させるようにしようかなー。
でもそれちょっと怖いかなー。大丈夫だとは思うけど…

検知のスクリプト【簡易版】

簡易版です。これは停止検知が上で紹介したものより弱いのですが、簡単に導入できます。
※私はAWSで運用しています。

cd /home/ec2-user/environment(※cd先はご自身の環境を指定してください)
if [ -f checklockfile ]; then
 exit;
fi

ps -ef |grep [m]ybot.py(※貴方のbot名を使用します、頭文字は[]に入れましょう)
if [ $? = 0 ]; then
  echo "ikiteru"
else
  echo "sinda"
  curl -X POST -H 'Authorization: Bearer ★★★(あなたのlineのアクセストークン)' -F 'message=otita' https://notify-api.line.me/api/notify
  touch checklockfile
fi

解説しますと、
Linux環境ですので、「ps」というコマンドでプロセスを表示することができます。
それをgrepにてあなたのbot名を抜くようにします。
結果、mybot.pyがあれば、戻り値は0となりますので、"ikiteru"分岐に入ります。
無ければ、戻り値は0以外となり、"sinda"分岐に入ります。

"sinda"分岐に入った場合、LINEへの通知を行います。
これを使用します。↓
「curl -X POST -H 'Authorization: Bearer ★★★(あなたのlineのアクセストークン)' -F 'message=otita' https://notify-api.line.me/api/notify」

で、最後にロックファイルをtouchします。
これは、落ち続けている場合通知が届き続けるのを防ぐためです。
落ちた通知を出し続けたい場合はtouchしなくてもよいかと。

LINEのアクセストークンの取得方法

ページ上部に記載しています。

検知のジョブを登録する

スクリプトができたら、それをジョブに登録します。
Linux環境では「Cron」と呼ばれるものです。
crontab -e
として、vi環境に入り、以下のように記載します。

*/5 * * * * /home/ec2-user/environment/check.sh > /dev/null 2>&1

5分毎にチェックスクリプトを実行する、という記載になります。
1分毎に検知したければ、一番左の「*/5」を「*」と書き換えます。
「/home/ec2-user/environment/check.sh」はご自身のチェックスクリプトまでの環境と読み替えてください。
かいたら、:wqとして保存します。
crontab -l とすると、Cronへ登録されているリストが確認できます。

もし通知が来たら

検知自体は、Cronに登録したとおり5分に一度の頻度で行います。
実際に通知が来て、botを立ち上げなおしたら、
必ずtouchした「checklockfile」を削除しておいてください。
このファイルがあると、一度検知済みの状態となっており、次の通知が来ません。


cd /home/ec2-user/environment
rm checklockfile

懸念点

検知できない状況について。
この検知は、「ps 結果のgrep」に検知を頼っています。
つまり、「プロセスは[ある]が[うまく動いていない]場合」は、動いていると判断し、通知は来ません。
また、「別のプロセスがたまたま同じ名前で、検知に引っかかっていた」ケースでも動いていると判断し、通知は来ません。

で、私のbotについては、たいてい「プロセスは残るが動作はしていない」という状況で死んでいたので…、あまり使えませんでした。
使える人もいるかもしれませんので、メモとして残しておきます。
繰り返しますが、こちらの検知力は低いです。

コメント

  1. […] →botが停止しているのをLINEへ通知するスクリプトを作りました。こちらもどうぞ […]

  2. […] これは私のbotのエラー処理も悪かったのですが… テストネットではほぼほぼ発生しなかったのですが、本番環境ですと、以下の処理が503等の エラーで蹴られることが発生しました。 「ローソク足のデータをhttpsで取得」 「注文処理を実行」 で、例外を吐いて死んでいる…ということがありました… 原因: 価格が大きく動いた際など、大量の人が群がると、サーバ側が重くなってしまい発生するようです。 ユーザには防ぐ術はありません。 8月にも、ガーンと下がった時に発生していましたね… この時たまたまWebオンしていたのですが、Webページの方にも入れなくなってました。 ロスカ食らった人も多いんじゃないかなー。 困ったらtwitterなどで「mex 入れない」とかで検索すると周りの状況がわかるかもです。 対策: これは「try: except」等のエラー処理をきちんと行いましょう。 503エラーを吐いても処理が続行できるように書けば大丈夫です。 ただ、それでも拾いきれない例外があったりしたので、私はbotを監視して停止したらLINEに通知する処理を仕込みました。  →botが停止しているのをLINEへ通知するスクリプト […]

タイトルとURLをコピーしました