Index
Let me login to my pc AUTOMATICALLY
ちょっとスマートスピーカのネタから外れるのだが久々に更新。
先日、PASORIをラズパイにつないで、Felicaのカードを
置いたら、主人が帰ってきたことを認識するって仕組みを作った。
おかえりなさい
みたいなのをGoogle Home miniから喋らせて
それまで人感センサで電気をつけていたのを
ストップさせたりといった仕組み。
せっかくなので、家の私のPCのログイン画面の入力も
省略したいなと思い始めた。
なので、オートログインの仕組みをちょっと調べてみた。
Specs
その前に私のPCのスペックを。
| No | Name | Value |
|---|---|---|
| 0 | PC | Dellのなんか古いやつ |
| 1 | OS | Debian GNU/Linux 10.0 |
| 2 | X-Window System | xorg 7.7 |
| 3 | Display Manager | lightdm 1.10.3 |
別にハード的なことに制約はないので
OSとミドルだけ知ってほしかったのでこんなもんかな。
んでね。このlightdmってのが割と何も考えずに
普段のDesktop Managerとして選択しちゃって
もう2年ぐらい常用しているのだが
こやつの自動ログインの仕組みを調べたら
割と簡単な仕組みで実現できることがわかった。
How to auto-login
自動ログインの仕組みは、以下のディレクトリにファイルを作る。
私の環境はディレクトリがなかったので作った。
/etc/lightdm/lightdm.conf.d/10_autologin.conf1
$ sudo mkdir -p /etc/lightdm/lightdm.conf.d
$ sudo vi /etc/lightdm/lightdm.conf.d/10_autologin.conf
以下の内容を保存しておくと。
[SeatDefaults]
autologin-user={AUTOLOGIN_USERNAME}
autologin-user-timeout=0
{AUTOLOGIN_USERNAME}には自分が普段使っているユーザアカウント名に
置き換える。これで再起動すると、自動でログインできる仕組み。
If I put on my card, then let me login
例えばスマートカードでのログインだとPCにカードを挿したり置いたりしたら
ログインされるってのはあるけどそれをラズパイにつながっている
PASORIにカードを置いたことをトリガーにそれをできるようにするって話。
Is my master ON?
ラズパイではご主人が帰ってきたことを認識したらDBに保存している。
それをJudgeクラスから呼び出せば、ご主人様のいるかをtrue/falseで
わかるようにしているので、それを外部からもわかるようにする。
LAN内通信なので大したセキュリティは用意しない。ラズパイ側には
IPフィルタがあるのでPCからのアクセス許可をするぐらい。
んで、APIを用意する。
本気で作るならJSONでやりとりして
認証とかもtlsかなんかでやっちゃうんだろうけど
インターネットに晒すわけでもないのでここでは簡便にする。
以前から動かしているapi.jsに主人いますかAPIを用意する。
以下抜粋。
const jdg=require('Judge');
app.get('/loginauth/get/', (req, res) => {
let loginCheck=async ()=>{
let j=await new jdg();
let ret=await j.isMasterOn();
res.header('Content-Type', 'text/html; charset=utf-8');
res.status(200).send(ret);
}
loginCheck();
});
JudgeクラスのisMasterOnメゾッドを呼べばtrue/falseで
返ってくるので、それをそのままクライアントに返す。
URLは
http://raspberrypi:50880/loginauth/get/
みたいなのにしてみる。
PC側はこのAPIを定期的に叩いてtrueであれば
自動ログイン処理をスタートさせることに。
autologin.sh
今回cron+bash scriptで実現してみる。
仕組みは単純。
sequenceDiagram
participant sh as PC
participant api as raspberrypi
participant db as DB
alt flag file exists?
Note over sh : Quit
else
Note over sh : Run next step
end
sh->>+api : Get result
api->>+db : Get record set
db-->>-api : Send res
api-->>-sh : Send result
alt is master on
Note over sh : Call function
else
Note over sh : Quit
end
こんな感じ。
最終的に関数を呼んでいるのだが(Call functionのとこ)、
そこは以下のことをしている。
- 自動ログインのファイルを生成する
- lightdmを再起動する
- フラグファイルを作る
- 自動ログイン後は自動ログインのファイルを削除する
最後のフラグファイルはログイン後にも間違って動かないようにするためのやつ。
自動ログイン後は毎回自動ログインファイルを削除することで
次の再起動時にはログイン画面を表示させるため。
フラグファイルは再起動したら消えるように/tmpに生成する。
んで、このスクリプトを1分間隔で実行する。
はいできあがり。
ではスクリプトを作ってみる。
/srv/loginauth/checkmaster.sh
ここに作る。
#!/bin/bash
SYSNAME=autologin
AUTHURL=http://raspberrypi:50880/loginauth/get/
DMSERVICE=lightdm
SYSCTL=$(which systemctl)
CURL=$(which curl)
AUTHEVI=/tmp/loggedin.stat
AUTOLOGINFILE=/etc/lightdm/lightdm.conf.d/10_autologin.conf
USERNAME=friedbiscuit
if [ "x${SYSCTL}" == "x" -o "x${CURL}" == "x" ];
then
_e "some command[s] was/were not found"
exit 1
fi
if [ ! -d $(dirname $AUTOLOGINFILE) ];
then
mkdir -p $(dirname $AUTOLOGINFILE)
fi
if [ -f $AUTOLOGINFILE ];
then
rm -f $AUTOLOGINFILE
fi
function _e {
logger -t $SYSNAME "${1}"
}
function checking {
ret=$(${CURL} -s ${AUTHURL})
if [ "x$ret" == "xtrue" ];
then
_e "found master is on"
fi
echo $ret
}
function autologin {
ret=$($SYSCTL status $DMSERVICE |grep "running" >/dev/null && echo -n "OK")
if [ "x$ret" == "xOK" ];
then
_e "${DMSERVICE} is running now"
cat <<EOF >$AUTOLOGINFILE
[SeatDefaults]
autologin-user=${USERNAME}
autologin-user-timeout=0
EOF
$SYSCTL restart $DMSERVICE >/dev/null && _e "auto login start"
fi
}
function main {
if [ -f $AUTHEVI ];
then
exit
fi
ret=$(checking)
if [ "x$ret" == "xtrue" ];
then
autologin
sleep 5
_e "auto login evidence"
echo 1 > $AUTHEVI
rm -f $AUTOLOGINFILE
fi
}
main
あとはrootのcrontabに以下を追加
* * * * /srv/loginauth/checkmaster.sh >/dev/null
これで1分間隔でチェックさせる。
Did I have a good exprerience?
今のところ便利。以下の課題があるけど
特に解決しなくてもいいかな。
- 自分の部屋なので、マルチユーザには対応していない。
- 厳密にログインしたかを判断していない。
- 本当はデーモンとして動くクロスプラットフォーム化プログラムとしてちゃんと管理してみたい。