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)
두 개의 AMD 프로세서 시스템은 제대로 작동하지만 두 개의 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
is 0
, 즉 localtime
return 입니다 0
. glibc localtime
매뉴얼 페이지를 읽으면 이것이 오류 조건에서만 발생한다는 것을 알고 있습니다. 불행히도 정확히 무엇이 잘못되었는지에 대한 징후는 없습니다. 그러나 time_t
실제로 a를 사용하여 를 로컬 타임스탬프로 변환하는 데에는 아무런 문제가 없습니다 localtime
. 지정된 유일한 오류 유형은 전달된 값이 사람에게 너무 클 때 오버플로입니다. 여기서 일어나는 일은 다음과 같습니다.
이 오류 조건이 발생하면 호출은 timetostr
단지 호출됩니다 anytostr
(gnulib, 특히 gnulib/lib/anytostr.c입니다. grep 없이 또는 몇 년 동안 gnulib 코드를 쳐다보지 않고도 이를 알아낼 수 있는 방법을 묻지 마십시오. 이 코드는 유지됩니다. 그러나 솔직히 그것은 역사적 이유로 끔찍하고 거시적으로 오염되었습니다. c). anytostr(inttype i, char *buf)
솔직히 이것은 중복된 재구현일 뿐이 므로 utmp 레코드를 십진수로 해석하여 인쇄하는 sprintf(buf, "%jd")
것뿐입니다 !time_t
놀랍게도 십진수 7205944946380205577을 읽으면 나노초 단위로 측정되지만 그것은 수세기에서 수천년의 미래입니다.
따라서 utmp 기록이 손상되어 localtime
합리적인 로컬 타임스탬프로 변환할 수 없으므로 원래 번호만 인쇄하게 됩니다.
지금,왜파일에서 읽은 utmp 레코드가 손상되었습니다. 모르겠습니다.
이는 실행 중인 두 시스템 모두에서 심각한 버그인 것 같습니다. 어쩌면 utmp 레코드가 이를 읽는 libc에서 사용되는 것과 다른 구조 정의로 작성되었을 수도 있습니까 who
? 어쩌면 파일이 x86 PC에서 ARM 시스템으로 복사되었을 수도 있습니다(가능성은 낮음).
이것이 내가 주석에서 "깨진 libc 업데이트"에 대해 추측한 이유입니다. 한 가지 설명은 utmp 파일을 읽을 때 올바른 것으로 utmp.h
가정되는 것과 who
파일을 작성할 때 여전히 올바른 것으로 가정하는 것이 다르다는 것입니다. 하지만 파일을 삭제했다고 하셨는데, 그 후에 로그인하신 것으로 가정하여 이를 배제할 수 있습니다.
이 시점에서는 데비안 수준의 디버깅이 필요합니다. 나는 who
데비안 관리자(아마도 패키지 관리자)에게 버그를 제출할 것을 권장합니다 coreutils
. coreutils의 gnulib이 최신 상태인지, 특히 구성 스크립트가 utmp.h
또는 의 존재를 올바르게 감지하는지 확인하도록 요청하세요 utmpx.h
. (저는 이것이 gnulib이 소스 코드에 복사하는 소스 코드 묶음일 뿐이고 이미 이것을 물린 사용자를 포함하여 다른 시스템과 동기화를 유지하기 어려운 많은 경우 중 하나라고 생각합니다.