RPI-4でDebian Bookwormを使用すると、このwho
コマンドはログイン日時の代わりに大きな数字を表示します。一部の検索では、/run/utmp
所有権と権限を削除、再作成、確認することを提案しています。
私はうまく動作する他のシステムにあるものと一致するように root:root
それらを変更しました。これらのどれも役に立ちません。rw-r--r--
root:utmp
rw-rw-r--
以下はコマンドの出力ですwho
。
root pts/0 7205944946380205577 (192.168.0.100)
次のようにする必要があります。
root pts/0 2024-03-17 15:49 (192.168.0.100)
2 つの AMD プロセッサシステムは正常に動作しますが、2 つの RPI-4 はそうではありません。
私が調査した内容は次のとおりwho
です。
type who
who is hashed (/usr/bin/who)
who --version
who (GNU coreutils) 9.1
私のオペレーティングシステムはDebian Bookworm 12.1 Kernel 6.1.21-v8+ aarch64です。
答え1
まあ、私たちはますます近づいています。
あなたの意見で述べたように、デバッグにgdbを使用していただきありがとうございます。
$> gdb /usr/bin/who
…
(gdb) break strftime
…
(gdb) run
Starting program: /usr/bin/who [Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".
root pts/0 7205944946380205577 (192.168.0.100)
[Inferior 1 (process 6631) exited normally]
(gdb)
strftime
実際には呼び出されないと言えます。しなければならないwho
v9.1に関する限りsrc/who.c
、(330行目から始まります):
/* Send properly parsed USER_PROCESS info to print_line. The most
recent boot time is BOOTTIME. */
static void
print_user (const STRUCT_UTMP *utmp_ent, time_t boottime)
{
// …
/* skipping to line 434 */
print_line (sizeof UT_USER (utmp_ent), UT_USER (utmp_ent), mesg,
sizeof utmp_ent->ut_line, utmp_ent->ut_line,
time_string (utmp_ent), idlestr, pidstr,
hoststr ? hoststr : "", "");
}
ここで興味深い部分は、ここ(216ff行)と呼ばれる関数ですstatic char const *time_string(const STRUCT_UTMP *)
。この関数の仕事は、utmpエントリから時間情報を取得し、人間に優しい方法で印刷することです。
/* Return a time string. */
static char const *
time_string (const STRUCT_UTMP *utmp_ent)
{
static char buf[INT_STRLEN_BOUND (intmax_t) + sizeof "-%m-%d %H:%M"];
/* Don't take the address of UT_TIME_MEMBER directly.
Ulrich Drepper wrote:
"... GNU libc (and perhaps other libcs as well) have extended
utmp file formats which do not use a simple time_t ut_time field.
In glibc, ut_time is a macro which selects for backward compatibility
the tv_sec member of a struct timeval value." */
time_t t = UT_TIME_MEMBER (utmp_ent);
struct tm *tmp = localtime (&t);
if (tmp)
{
strftime (buf, sizeof buf, time_format, tmp);
return buf;
}
else
return timetostr (t, buf);
}
今、デバッガではstrftime
呼び出されないと言います!
唯一の可能な方法はif tmp
、0
つまりlocaltime
returnです0
。 glibclocaltime
のマニュアルページを読むと、これはエラー条件でのみ発生することがわかります。残念ながら、正確に何が間違っているかという兆候はありません。しかし、time_t
実際にaを使ってローカルタイムスタンプに変換することには問題はありませんlocaltime
。指定された唯一のエラータイプは、渡された値が人に大きすぎる場合のオーバーフローです。ここで何が起こるかは次のとおりです。
このエラー状態が発生した場合、呼び出しは単に呼び出されますtimetostr
(anytostr
gnulib、特にgnulib / lib / anytostr.cです)。しかし、正直なところ、それは歴史的な理由でひどくて巨視的に汚染されています。anytostr(inttype i, char *buf)
正直なところ、これは重複した再実装であるだけなので、utmpレコードを10進数として解釈して印刷するsprintf(buf, "%jd")
だけです!time_t
驚くべきことに、10進数7205944946380205577を読むとナノ秒単位で測定されますが、それは何世紀から数千年の未来です。
そのため、utmpの記録が破損し、localtime
合理的なローカルタイムスタンプに変換できないため、元の番号だけが印刷されます。
今、なぜファイルから読み取られたutmpレコードが破損しています。わかりません。
これは、実行中の両方のシステムで深刻なバグのようです。おそらく、utmpレコードがそれを読み取るlibcで使用されているものとは異なる構造定義で書かれていますかwho
?おそらく、ファイルがx86 PCからARMシステムにコピーされている可能性は低いです。
これが私がコメントから「壊れたlibcアップデート」について推測した理由です。 1つの説明は、utmpファイルを読み取るときに正しいと仮定し、utmp.h
ファイルwho
を作成するときにまだ正しいと仮定することが異なることです。しかし、ファイルを削除したとし、その後ログインしたと仮定してそれを除外できます。
この時点では Debian レベルのデバッグが必要です。who
Debian Manager(おそらくパッケージマネージャ)にバグを送信することをお勧めしますcoreutils
。 coreutilsのgnulibが最新であること、特に設定スクリプトが存在するかどうかをutmp.h
正しく検出していることを確認してくださいutmpx.h
。 (私はこれがgnulibがソースコードにコピーするソースコードの束であり、すでにこれを噛んでいるユーザーを含む他のシステムと同期を維持するのが難しい多くのケースの1つだと思います)。