RPI-4의 Debian Bookworm "who" 명령은 로그인 날짜/시간 대신 큰 숫자를 표시합니다.

RPI-4의 Debian Bookworm "who" 명령은 로그인 날짜/시간 대신 큰 숫자를 표시합니다.

RPI-4에서 Debian Bookworm을 사용하면 이 who명령은 로그인 날짜/시간 대신 큰 숫자를 표시합니다. 일부 검색에서는 /run/utmp소유권과 권한을 삭제하고 다시 만들고 확인하도록 제안했습니다.

나는 잘 작동하는 다른 시스템에 있는 것과 일치 root:root하도록 그것들을 변경했습니다 . 이 중 어느 것도 도움이 되지 않습니다.rw-r--r--root:utmprw-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실제로 호출되지는 않는다고 말할 수 있습니다 .~해야 한다whov9.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, 즉 localtimereturn 입니다 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이 소스 코드에 복사하는 소스 코드 묶음일 뿐이고 이미 이것을 물린 사용자를 포함하여 다른 시스템과 동기화를 유지하기 어려운 많은 경우 중 하나라고 생각합니다.

관련 정보