서버와 노트북에서 루틴을 수행 apt upgrade
하고 모든 것을 다시 시작한 후 다음을 발견했습니다.
$ mount nfs-server:/mnt /mountpoint
그것은 영원히 중단됩니다. 논리적인 설명은 없는 것 같습니다.
나는 먼저 통찰력을 얻기 위해 Wireshark를 찾았습니다.
140 60.439219227 192.168.0.2 192.168.0.3 NFS 170 V4 Reply (Call In 138) EXCHANGE_ID
141 60.439302740 192.168.0.3 192.168.0.2 NFS 258 V4 Call (Reply In 142) CREATE_SESSION
142 60.439984105 192.168.0.2 192.168.0.3 NFS 194 V4 Reply (Call In 141) CREATE_SESSION
143 60.440070415 192.168.0.3 192.168.0.2 NFS 198 V4 Call (Reply In 147) PUTROOTFH | GETATTR
147 65.511499058 192.168.0.2 192.168.0.3 NFS 158 V4 Reply (Call In 143) PUTROOTFH Status: NFS4ERR_DELAY
헤헤. 그래서 그것은 효과가 있지만 완전히 즐겁지 않은 것들이 있습니다. 장애물은 무엇입니까?
다음으로 방향을 바꾸자 dmesg
즉시 "원을 그리며 불확실하게 단서를 찾고 있는" 단계를 순식간에 지나갔습니다.
[ 283.998430] rpc.mountd[2238]: segfault at 0 ip 00007f816550f3d6 sp 00007ffd60245820 error 4 in libc-2.28.so[7f81654b7000+148000]
[ 283.998523] Code: 1f 44 00 00 85 f6 0f 8e 88 00 00 00 83 fe 01 0f 84 8f 00 00 00 41 54 83 ee 01 49 89 fc 41 b8 01 00 00 00 55 b9 0a 00 00 00 53 <8b> 02 48 89 d3 89 c5 83 e0 df 89 02 48 63 d6 48 89 fe 48 89 df 83
이는 시작하자마자 거의 즉시 발생합니다. 여기서 무슨 일이 일어나고 있는지 궁금합니다 ...
직접 시작하려면 어떻게 해야 하나요? 유닛 파일의 일부 내용을 살펴보면 매개 변수가 필요하다는 것을 알 수 있었고 --manage-gids
눈을 가늘게 뜨고 전경에서 실행한다고 --help
언급했습니다 . -F
좋아요
# rpc.mountd --manage-gids -F
rpc.mountd: Version 1.3.3 starting
Segmentation fault
글쎄, 다시 만드는 데 시간이 오래 걸리지 않습니다! 그렇다면 이런 일을 해야 하는 이유는 무엇일까?
stat("/", {st_mode=S_IFDIR|0755, st_size=37, ...}) = 0
openat(AT_FDCWD, "/etc/mtab", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
futex(0x7faf15dd5168, FUTEX_WAKE_PRIVATE, 2147483647) = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=NULL} ---
+++ killed by SIGSEGV +++
Segmentation fault
...아뇨, 내 시스템이 아직 자체적으로 플러시되지 않았습니다. 그렇죠? :에스
# ls -l /etc/mtab
lrwxrwxrwx 1 root root 19 Jul 12 15:17 /etc/mtab -> ../proc/self/mounts
...알았어, 와.
잘. 나는 그 악당이 openat()
실제로 도서관에서 전화를 걸었다고 확신한다 . ltrace
다른 흥미로운 배경이 추가되었는지 궁금합니다 .
__xstat(1, "/", 0x7ffe45d9f620) = 0
free(0) = <void>
strdup("/") = 0x559b3adaf640
strlen("/") = 1
setmntent("/etc/mtab", "r") = 0
getmntent(0 <no return ...>
--- SIGSEGV (Segmentation fault) ---
+++ killed by SIGSEGV +++
어-허, 그게 뭐--
DESCRIPTION
These routines are used to access the filesystem description file
/etc/fstab and the mounted filesystem description file /etc/mtab.
The setmntent() function opens the filesystem description file filename
and returns a file pointer which can be used by getmntent(). The argu-
ment type is the type of access required and can take the same values
as the mode argument of fopen(3).
The getmntent() function reads the next line of the filesystem descrip-
tion file from stream and returns a pointer to a structure containing
the broken out fields from a line in the file. The pointer points to a
static area of memory which is overwritten by subsequent calls to getm-
ntent().
...
RETURN VALUE
The getmntent() and getmntent_r() functions return a pointer to the mn-
tent structure or NULL on failure.
잠시만 기다리세요. setmntent()
NULL 포인터라고도 불리는 0을 반환합니다. 그런 다음 NULL 포인터가 사용됩니다 getmntent()
. 깨진 것 같습니다...?
나는 여기서 무슨 일이 일어나고 있는지 알고 싶습니다. rpc.mountd
포함된 패키지에 디버깅 기호가 있으면 좋지 않을까요? 아 멋지 군요 nfs-kernel-server-dbgsym
. 시원한.
프로그램이 SIGSEGV 신호, 분할 오류를 수신했습니다. __GI___fgets_unlocked의 0x00007ffff7db73d6(buf=buf@entry=0x5555555a8060 "", n=n@entry=4096,fp=fp@항목=0x0) iofgets_u.c:50 50 iofgets_u.c: 해당 파일이나 디렉터리가 없습니다. (gdb)BT #0 0x00007ffff7db73d6 in __GI___fgets_unlocked(buf=buf@entry=0x5555555a8060 "", n=n@entry=4096, fp=fp@entry=0x0) in iofgets_u.c:50 __GI___getmntent_r의 #1 0x00007ffff7e2ef16(스트림=스트림@항목=0x0, mp=mp@entry=0x7ffff7efb140 , buffer=0x5555555a8060 "", bufsiz=bufsiz@entry=4096) mntent_r.c:130 getmntent의 #2 0x00007ffff7e2ed03(스트림=스트림@항목=0x0) mntent.c:52 #3 캐시의 next_mnt(v=0x555555571ac8, p=0x5555555a4ff8 "/")의 0x000055555555cfa8.c:383 #4 nfsd_fh(f=6)(cache.c:736) #5 0x000055555555d2cd in 캐시_process_req(readfds=readfds@entry=0x7fffffffe960) in 캐시.c:1424 #6 0x000055555555d718 at my_svc_run() svc_run.c:117 #7 0x0000555555558ee3 in main(argc=, argv=) at mountd.c:894
잘.
367화 [368 장] 369화 [370 장] 371 { 372화 373화 374화 375 if (*v == NULL) { 376화 377화 378화 379화 380화 381화 [382 장] 383화 384화 385 끝(f); 386화 387화 388화 [389 장] 390화
어 허.
그래서... setmntent()
NULL을 반환하고 에 할당된 f
다음 getmntent(f)
...segfaults...?
한 번 보자.
$ cat setmntent.c
#include <stdio.h>
#include <mntent.h>
int main() {
FILE *ret = setmntent("/etc/mtab", "r");
printf("%p\n", (void *)ret);
return 0;
}
$ gcc -o setmntent setmntent.c
$ ./setmntent
(nil)
응. 그래서 내 시스템에서는 /etc/mtab
심볼릭 링크이기 때문에 setmntent()
폭발합니다. 엄청난.
어디 보자...
$ cat getmntent.c
#include <mntent.h>
int main() {
getmntent(NULL);
}
$ gcc -o getmntent getmntent.c
$ ./getmntent
Segmentation fault
글쎄, 이것은 완전히 논리적입니다. *주요 역*
NFS가 작동하기를 원합니다. 무엇을 합니까?
답변1
끔찍한 해결책:
rm /etc/mtab; cat /proc/mounts > /etc/mtab
주의사항:
이는 /etc/mtab
결코 사라지지 않을 것으로 예상되는 것들을 나노초라도 무작위로 파괴할 수 있습니다.
사용 가능한 백업 테이프가 충분하지 않은 경우(시간, 리소스) 프로덕션 복구에 사용되지 않을 수 있습니다.
나는 이것이 해킹이라고 생각하기 때문에 이(자체 답변)를 허용된 것으로 표시하지 않을 것입니다. 대신에 논의할 다른 의견/답변을 찾습니다.
이 NFS 문제는 100% 재현 가능한 것으로 보이며 이론적으로(?) 모든 곳에서 발생할 수 있으므로 내 시스템이
/etc/mtab
가리키는 이유는 무엇입니까?/proc/self/mounts
왜 이런 일이 발생합니까?
나는 무엇을 해야 합니까?규범적으로이 상황을 해결하세요(특히
/etc/mtab
적절한 구성을 사용하여).
그러한 정보를 주시면 매우 감사하겠습니다!