Who コマンドを掘り下げよう
Who コマンドとは
基who コマンドでは、現在システムにログオンしているユーザーを一覧表示することができます。
$ who user1 tty2 2020-08-30 15:06 (tty2) user1 pts/1 2020-08-30 15:06 (tmux(1555).%0) user1 pts/2 2020-08-30 16:41 (tmux(1555).%6) user1 pts/4 2020-08-30 15:57 (tmux(1555).%3)
物理的な端末 tty2 と 3 つの疑似端末でログインしていることを教えてくれている。この例だと現在のGnome Shellのセッションはtty2で実行されており、3つのtmuxウィンドウが開いている。
しかし、これらの情報はどこから取得しているのか?Linuxではすべてファイルとして扱われることを思い出すと、この情報はおそらくファイルからだと推測できるが、どのファイルにどのようにデータが保存されているのか確認してみたい。
ちょっとしたリバースエンジニアリング
whoコマンドが何をしているのかを見るために、ソースコードを見つけてそれを掘り下げてみることができる。また、代わりにstraceを使ってプロセスが何をしているかをチェックするのが面白い。
$ strace who 2>&1 | grep open openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/var/run/utmp", O_RDONLY|O_CLOEXEC) = 3 openat(AT_FDCWD, "/etc/localtime", O_RDONLY|O_CLOEXEC) = 3
最初のファイル /etc/ld.so.cache, /usr/lib/libc.so.6 はプロセスが読み込んだ共有ライブラリである。
次に、/usr/lib/locale/local-archive, /var/run/utmp, /etc/localtime が開かれる。これらのファイルが何を保存しているのか見てみよう。
manで確認してみると、マニュアルの第5章は「ファイル形式と規約(“file formats and conventions” )」にページが割かれていることがわかる。ここをしらべよう。
locale-archive
$ man -wK 5 '/usr/lib/locale/locale-archive' Sends us to locale(5) where we can read:
ロケール定義ファイルには、localedef(1) コマンドがそれをバイナリロケールのデータベースに変換するために必要なすべての情報が含まれている。 このページでは、これらの情報についてのより詳しい説明のために locale(7) にもかかれている。
ロケールとは、言語と文化のルールの集合です。ロケールとは、言語や文化のルールの集合です。 メッセージの言語、文字セット、語彙・図形の規則などが含まれます。プログラムは、異文化に移植できるようにロケールを決定し、それに応じて行動できるようにしなければなりません。 そこで、who コマンドはこのファイルを読み込んで、おそらく setlocale(3) 関数を使って、情報の書式や表示方法を調べていることがわかるだろう。
これは以下のように実際に確認することができる。
$ LC_ALL='fr_FR.utf8' who gauthier tty2 Sep 2 11:38 (:1) gauthier pts/1 Sep 2 12:11 (tmux(2445).%0) gauthier pts/2 Sep 2 12:37 (tmux(2445).%1) gauthier pts/3 Sep 2 13:04 (tmux(2445).%2)
確かに、日付は同じようにフォーマットされていません!
localtime $ man -wK 5 '/etc/localtime'
localtime(5) は
・etc/localtime ファイルは、アプリケーションがユーザに表示するために使用するローカルシステムのシステム全体のタイムゾーンを設定。
となる。
おそらくwhoがこのファイルを使っているか(あるいはこのファイルを使っている関数を使っているか)は、ユーザによって設定された正しいタイムゾーンを使ってタイムスタンプ(誰の出力の4列目と5列目)をprintしてうr