PythonスクリプトとD-Busでユーザーのログイン・ログアウトを検知する

★★★ イベント情報 ★★★
◇【参加登録受付中】Kong Summit, Japan 2022◇
今年は12月15日に開催決定!最新情報とデモとともにKongと事例/ユースケースのご紹介などAPIエコノミーやマイクロサービスに関心のある開発者の方にとっては必見です。ぜひお申し込みください!イベントの詳細・お申込はこちら

★★★ Live配信告知 ★★★
◇11月29日開催 19:00~ 世界一わかりみの深いクラウドネイティブon Azure◇
テーマは「Web App for ContainersとKeycloakで最速OpenID Connect」です!

◇11月30日開催 17:00〜 知ってると ちょっと便利なコマンド集◇
知っていると少し効率の上がるようなコマンドをいくつかご紹介します!

こんにちは、サイオステクノロジーの藤野です。

Linux 上で Python スクリプトから D-Bus 経由でユーザーのログインセッションを監視する方法を紹介します。

動作イメージ

作業端末で仮想コンソールを2つ用意し、ホストにsshでログインしてPythonスクリプトを起動します。(画面上部)

この状態でもう片方の仮想コンソール(画面下部)からsshでホストにログインすると、スクリプトがログインセッションの開始を検知しユーザー情報を表示します。ログアウトでも同様にログインセッションの終了を検知し、ユーザー情報を表示します。

それでは実装の紹介です。今回は以下の構成で進めていきます。

作業端末

  • OS X

ホスト

  • CentOS 7.4
  • Python 2.7.5

まずはホストで必要なパッケージを導入します。

$ sudo yum install epel-release
$ sudo yum install python-gobject-base
$ sudo yum install python-pip
$ sudo pip install pydbus

test-dbus.py にコードを書きます。

from pydbus import SystemBus
from gi.repository import GLib
from functools import partial
import datetime

users = {}

def onSessionNew(sid, path, bus):
  session = bus.get('org.freedesktop.login1', path)
  (uid, path) = session.User
  user = bus.get('org.freedesktop.login1', path)
  user = { 'name': user.Name, 'uid': user.UID, 'gid': user.GID }
  users[sid] = user
  print('sid={} uid={} user={} event={}'.format(sid, user['uid'], user['name'], 'login'))

def onSessionRemoved(sid, path):
  user = users.get(sid)
  if users:
    del users[sid]
    print('sid={} uid={} user={} event={}'.format(sid, user['uid'], user['name'], 'logout'))

def main():
  bus = SystemBus()
  manager = bus.get('org.freedesktop.login1', '/org/freedesktop/login1')
  manager.SessionNew.connect(partial(onSessionNew, bus=bus))
  manager.SessionRemoved.connect(onSessionRemoved)
  print('wait for session event..')
  loop = GLib.MainLoop()
  try:
    loop.run()
  except KeyboardInterrupt:
    loop.quit()
  except:
    sys.exit(1)

main()

実装の解説

main()

D-BusのシステムワイドなイベントバスであるSystemBusを取得します。
イベントバスから logind の Manager オブジェクトを取得します。
Manager オブジェクトの SessionNew と SessionRemoved シグナルにそれぞれのコールバック関数を接続します。
https://www.freedesktop.org/wiki/Software/systemd/logind/#themanagerobject
なお、onSessionNew() ハンドラに bus を渡したかったので functools.partial を使ってハンドラ側の bus 引数に変数 bus を束縛してあります。
GLibのイベントループを開始します。ユーザーが Ctrl+C を入力することでイベントループが終了するように KeyboardInterrupt 例外を捕捉しておきましょう。

onSessionNew()

ユーザーのログインセッション作成後にこの関数をコールバックします。Session ID と Session オブジェクトのパスが引数で渡されます。

Session オブジェクトのパスを使って Session オブジェクトを取得します。
https://www.freedesktop.org/wiki/Software/systemd/logind/#sessionobjects
Session オブジェクトには User というプロパティがあり、Python のタプルで UID と User オブジェクトのパスが取得できます。

User オブジェクトのパスを使って User オブジェクトを取得します。
https://www.freedesktop.org/wiki/Software/systemd/logind/#userobjects

User オブジェクトから UID, GID, ユーザー名 をそれぞれ取得し、表示しています。
ログアウト時にもユーザー情報を出力したいので、Session ID をキーにして保持しておきます。

onSessionRemoved()

ユーザーのログインセッションの削除後にこの関数をコールバックします。Session ID と Session オブジェクトのパスが引数で渡されます。
シグナルの名前通り、この関数が呼ばれた時点で既に Session 存在していません。
そのため、ログアウトしたユーザーの情報はログイン時に保存しておいた情報を参照しています。

駆け足での紹介でしたが、D-Bus インターフェースを実装プログラムから利用する事でシステム内のイベントを購読し、情報を取り出せることができました。





ご覧いただきありがとうございます。
ブログの最新情報はSNSでも発信しております。
ぜひTwitterのフォロー&Facebookページにいいねをお願い致します!



>> 雑誌等の執筆依頼を受付しております。
   ご希望の方はお気軽にお問い合わせください!


ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。

Be the first to comment

Leave a Reply

Your email address will not be published.


*


質問はこちら 閉じる