The Rank of F

六本木で働く無能のブログ

家が燃えても気づける! @zeriyoshi_svr の裏側

みんなあるよね自宅サーバ

この界隈の人達にとって,自宅にサーバーがあるのは珍しいことではないかと思います。

特にファイルサーバーなんかは既製品を買ってくるよりも自作したほうが遥かに安く強力な物を作れるので便利です。

実際私も家にサーバーがあるのですが,WD Red 8TBx2をRAID1で構成し,ファイルサーバー兼Webサーバーとして稼働してもらっています。

この自宅サーバーなのですが,15分毎に室温+各種ハードウェアの温度をTwitterに投稿しています。

twitter.com

Twitterのフォロワーさんにこれを真似してくれている人が居たので,個人的なメモ代わりにもこのbotがどのようにして動いているかを書いておきたいと思います。

サーバー構成

  • CPU : Intel(R) Core(TM) i5-4570 CPU @ 3.20GHz (4th Gen, Haswell)
  • RAM : 20GB (8GBx2, 2GBx2)
  • OS : Arch Linux (x86_64)

ハードウェアはそれなりにパワーがあるのですが,自宅の回線が細い(100Mbps VDSL)なのであまり有効に活用できない...

最近はもっぱらファイルサーバーとして活躍しています。

死活監視が出来ない

自宅の回線は特にISPの固定IPオプションなどを契約していない為,グローバルIPv4アドレスが定期的に変わる環境にあります。

その為にドメインレジストラのDynamic DNS機能を用いて逐次現在のIPアドレスを登録しているのですが,何かしらの問題が発生して登録が正常に行われない可能性があります。

こうなるとサーバーに物理的にアクセスできない限り現状の把握が出来ません。もしかしたら停電が起こっていたり,最悪サーバーが燃えている可能性も考えられます。

ならば"サーバー側から"現在の状況を報告もらえばいいのです。手持ちのUSB温度計があったので同時に室温も報告してもらうことにしました。

例えば室温が80℃とかになっていればそれはもう確実に家が燃えているので,安心してかなしい気持ちになることができます。(そう,燃えていることに気づけるだけです。)

なぜTwitterなのか

自分が一番良く見ているのがTwitterだから

(関係ないですが,私に連絡する時はメールとかLINEよりもTwitterでreplyかDMした方が反応がたぶん早いです...)

@zeriyoshi_svrを作ろう

では実際に作っていきたいと思います。

Twitter側作業

アカウントの作成

15分毎に自分のメインアカウントでつぶやかれるとフォロワーさんに迷惑です。ちゃんとbot用アカウントを作りましょう。メインアカウントで垂れ流そうものなら速攻でミュートに突っ込みます。

アプリケーション登録

Twitterにつぶやく為にはアプリケーションの登録が必要です。

先程作成したアカウントでログインした状態でTwitter Applicaton Managementにアクセスし,Create New Appボタンを押して登録を進めます。

Callback URLは空欄のままで大丈夫です。

アプリケーション権限変更

アプリケーションの登録は完了しましたが,初期状態ではTwitterに書き込む権限を有していません。

Twitter Applicaton Managementから先程作成したアプリケーションを開き,Keys and Access Tokensタブからmodify app permissionsを開いてRead and Writeに変更してください。

自身のアクセストークンを取得

権限の変更が完了したら,Keys and Access Tokensタブの下にあるYour Access TokenToken ActionからCreate my access tokenボタンをクリックして自身のアカウント用のアクセストークンを生成します。

Access Tokenが生成されたら,しっかりとAccess LevelRead and Writeになっていることを確認しましょう。

最後にアカウントのスクリーンネームと以下の4つのToken, Secretをメモしておきましょう。

サーバー側作業

ShellからTweet出来る環境構築

情報取得の前にまずShellからTweet出来る環境を整える必要があります。

ShellからTwitterにつぶやく為の方法はいくつかありますが,今回は非常にポータブルで使いやすい火を吹くTwitter怪人“小鳥男”を使っていきます。

使い方...は記事の方で詳細に説明されているので省略します。

で,問題はスクリプトをどこに置くかなのですが,当時の自分は何も考えずsudo su -した後/etc/zeriyoshiなるディレクトリを作ってそこに全てを突っ込むという凶悪な行為を行っていました。

本来であれば適切なパーミッションを設定した上で/optディレクトリ以下に置いたほうが良いでしょう。

温度情報の取得とTweetを行うスクリプトの作成

まずlm_sensorshddtempコマンドを用いるのでこれらをインストールします。

Linux ディストロによっては最初から入ってたりパッケージ名が違ったりするかもなので適宜確認してください。

$ sudo pacman -S lm_sensors hddtemp

で,ざっと次のようなスクリプトを書きます。

tweet_temp.sh

#!/bin/bash

cpu_temp=`sensors | grep Package | cut -c 17-24`
hdd_temps=""

for device in /dev/sd[abcd];do
    hdd_temps="${hdd_temps}${device}:`hddtemp -n $device` °C
";
done

echo -e "CPU:${cpu_temp}\nHDDs:\n${hdd_temps}\n`date +\"%Y/%m/%d %H:%M:%S\"`" | /etc/zeriyoshi/kotoriotoko/BIN/tweet.sh

はい。本当に適当です。各種実行ファイルのパスやデバイスノード名は環境に合わせて書き換えてください。

systemd-timerに登録しスクリプトを定期実行する

ちょっと前まではcronを使って定期実行を行うのが通例でしたが,最近のLinuxディストロは殆どがsystemdinitデーモンとして用いており,systemd自体にcron代替機能が備わっているのでそれを利用します。

まずはサービスを作成します。

$ sudo vim /etc/systemd/system/tweet_temp.service

[Unit]
Description=Tweet CPU and HDDs temperature.

[Service]
Type=oneshot
ExecStart=/etc/zeriyoshi/tweet_temp.sh

次にタイマーを作成します。

$ sudo vim /etc/systemd/system/tweet_temp.timer

[Unit]
Description=Tweet CPU and HDDs temperature.

[Timer]
OnCalendar=*:0/15

[Install]
WantedBy=timers.target

終わったらsystemdのデーモンを再読込し,タイマーを有効化して開始します。

$ sudo systemctl enable tweet_temp.timer
$ sudo systemctl start tweet_temp.timer

タイマーが正常に動作しているか確認します。

$ sudo systemctl | grep tweet_temp
  tweet_temp.timer                                                                                      loaded active waiting   Tweet CPU and HDDs temperature.                                   

これで一通り完了です。

おまけ : 室温をつぶやこう

@zeriyoshi_svrでは自宅の室温もつぶやいています。ではこれはどうやっているのかというと

f:id:zeriyoshi:20180108000443j:plain

こうしています。

こういうのと

www.itmedia.co.jp

これを組み合わせて

github.com

室内温度を測定しています。このUSB温度計は販売終了品となってしまっていますが,中国のR Ding社のOEM品なので今でも普通に入手することができます。

コンパイルにはlibusbが必要になるのでインストール後にmakeしてください。

GitHubの説明通り適切に設定を行えば管理者ユーザーでなくとも実行できるようになりますが,systemd-timerで実行している為特に設定はしていません。

デフォルトでは現在時刻が出力されてしまう&センサーの個体差で取得できる温度にブレがあるので通常の室温計を元にキャリブレーションを行い再度コンパイルしました。

一応ソースも貼っておきます。

pcsensor.cの修正patch(不要な変数宣言を消しているだけです)
--- pcsensor.c   2018-01-08 00:36:23.685319615 +0900
+++ pcsensor.fix.c    2018-01-08 00:34:36.358652434 +0900
@@ -47,7 +47,6 @@ const static char uCmd3[] = { 0x52,    0
 const static char uCmd4[] = { 0x54,    0,    0,    0,    0,    0,    0,    0 };
 
 const static int reqIntLen=8;
-const static int reqBulkLen=8;
 const static int timeout=5000; /* timeout in ms */
  
 static int debug=0;
temper.cを温度の出力のみ変更したpatch
--- temper.c 2018-01-08 00:40:19.838654085 +0900
+++ temper.zeri.c 2018-01-08 00:33:46.555318858 +0900
@@ -9,8 +9,8 @@
 
 /* Calibration adjustments */
 /* See http://www.pitt-pladdy.com/blog/_20110824-191017_0100_TEMPer_under_Linux_perl_with_Cacti/ */
-static float scale = 1.0287;
-static float offset = -0.85;
+static float scale = 1.00000;
+static float offset = -2.00;
 
 int main(){
    int passes = 0;
@@ -38,15 +38,7 @@ int main(){
        /* Apply calibrations */
        tempc = (tempc * scale) + offset;
 
-      struct tm *utc;
-      time_t t;
-      t = time(NULL);
-      utc = gmtime(&t);
-      
-      char dt[80];
-      strftime(dt, 80, "%d-%b-%Y %H:%M", utc);
-
-      printf("%s,%f\n", dt, tempc);
+       printf("%.3f °C\n", tempc);
        fflush(stdout);
 
        return 0;

あとは先程のtweet_temp.shを以下のようにするだけです。

#!/bin/bash

cpu_temp=`sensors | grep Package | cut -c 17-24`
hdd_temps=""

for device in /dev/sd[abcd];do
    hdd_temps="${hdd_temps}${device}:`hddtemp -n $device` °C
";
done

echo -e "Room:`/etc/zeriyoshi/temper`\nCPU:${cpu_temp}\nHDDs:\n${hdd_temps}\n`date +\"%Y/%m/%d %H:%M:%S\"`" | /etc/zeriyoshi/kotoriotoko/BIN/tweet.sh