ぶていのログでぶログ

思い出したが吉日

NetworkManagerのDispatcherで出勤記録を自動化する

仕事を開始するときに出勤記録をつける必要がある。 便利なことにCLIがあるので*1これを叩けば出勤記録をつけることができる。

$ syukkin

しかしながら、これを忘れることがあるので自動化したい!というのが目的。

NetworkManager Dispatcher

結論からいうとNetworkManagerのDispatcherを使うことにした。

developer.gnome.org

これを使うとネットワークに関連するイベントが発生したときに任意のスクリプトを実行することができる。 実行したいスクリプトは実行権限をつけて /etc/NetworkManager/dispatcher.d 配下に配置すると実行される。 ちゃんと確認していないけど、ファイル名順に実行されるっぽい。 今回は 99-dakoku というファイル名にした。

➜ ls -lah /etc/NetworkManager/dispatcher.d/99-dakoku
.rwxr-xr-x root root 378 B Wed Jul 31 20:20:08 2019 99-dakoku

スクリプトには各種環境変数が渡されるので、これを見て動作を変える。 様々な環境変数があるが、今回利用したのは以下の2つである。

  • $NM_DISPATCHER_ACTION : どういうアクションによってスクリプトが実行されたかが格納される
  • $CONNECTION_UUID : コネクションプロファイルのUUID(後述)

$NM_DISPATCHER_ACTION はわかりやすく、 up とか down とかが入る。 $CONNECTION_UUID はNetworkManagerで管理されているプロファイルのUUIDになる。 これは、 nmcli connection で確認できる。

➜ nmcli connection
NAME                   UUID                                  TYPE       DEVICE
****                   5f5bba80-6de6-476d-8cce-424bfe256558  vpn        wlp2s0
****                   29b52b22-1937-4bb7-b05b-f6eb2af0bbbb  wifi       wlp2s0
****                   c1d3d458-8029-495b-9350-39424ab2eb06  tun        tun0

$NM_DISPATCHER_ACTION だけではどのネットワークに接続されたのかがわからないため、$CONNECTION_UUIDも確認することで特定することができる。 今回は、オフィスのWiFiに接続した時に実行したいのでオフィスWiFiのUUIDを指定した。

完成したスクリプト

雑に多重実行の防止をいれて*2完成

#!/bin/bash

PROFILE_UUID="***"
STATE="/var/lib/NetworkManager/dakoku"

if [ "$NM_DISPATCHER_ACTION" != "up" -o "$CONNECTION_UUID" != "$PROFILE_UUID" ]; then
    exit 0;
fi

PREV="`cat $STATE 2> /dev/null || echo 0`"
NOW="`date +%Y%m%d`"

if [ $PREV -ge $NOW ]; then
    exit 0
fi

/usr/local/bin/syukkin
result="$?"

echo $NOW > $STATE

exit 0

デバッグする場合は /var/log/syslognm-dispatcher でgrepすると何かがわかるはず。

おわりに

NetworkManagerのDispatcherを使って、オフィスでPCを起動すると自動で出勤記録をつけられるようになった! これが実際便利で、オフィスに来てから何も考えずにPCを起動して仕事を開始することができるようになった。 また、このスクリプトには含まれていないけど出勤記録をつける時に会社Slackに出勤したことを通知することで、リモートワークしている人にも出勤したことが伝わってとても便利。

ちなみに、退勤記録は自動化していない。 というのも同じような仕組みで実装しようとすると、WiFiが切断されたときに実行されることになるのでスタンドアローン状態になり記録することができない。。 まぁ、私は区切りをつける意味で退勤するときはtaikinコマンドを実行することにしているので困ってはいない。

おまけ: /etc/network/{if-down.d,if-post-down.d,if-pre-up.d,if-up.d} との使い分け

Ubuntuには /etc/network 配下に if-up.dなどのディレクトリがあり、この配下にスクリプトを置くと今回やったことと同じことができる。 ではどちらを使えばいいのだろうか? 🤔 実は、 /etc/network 配下のスクリプトは NetworkManager Dispatcher を使って実装されている。 /etc/NetworkManager/dispatcher.d/01-ifupdown というスクリプトがあり、このスクリプトから /etc/network 配下のスクリプト群を呼び出す仕組みになっているようだ。

*1:非公式

*2:/var/lib/NetworkManager/timestamps にプロファイルごとのタイムスタンプがあるのだが、このファイルが更新されてからスクリプトが呼び出されるために参照できないのであった…。