다중 스레드 프로그램에서 지속적인 I/O 읽기 및 쓰기가 발생하는 바쁜 파일 시스템을 마운트 해제하려고 하므로 umount 명령이 실패합니다.
root@ubuntu:~ # umount /mount/v1
umount: /mount/v1: target is busy.
(In some cases useful info about processes that use
the device is found by lsof(8) or fuser(1))
이제 다음 명령을 사용하여 모든 프로세스를 종료하려고 합니다.
/sbin/fuser -m /mount/v1 -k
그러나 따르면수정 명령
fusionr -k 또는 -K는 프로그램 실행이 시작된 직후 생성된 새 프로세스를 감지하고 종료하지 못할 수 있습니다.
일부 스레드가 동시에 IO 요청을 발행할 수 있기 때문에 이것이 제 경우입니다. 파일 시스템을 다시 마운트 해제하면 다시 사용 중이라는 메시지가 표시되고 루프가 됩니다.
제 질문은 새로운 프로세스가 파일 시스템에서 읽기/쓰기 작업을 수행할 수 없도록 어떻게 보장합니까?
/sbin/fuser -m /mount/v1 -k
파일 시스템이 정상적으로 마운트 해제될 수 있도록 명령을 실행하십시오.
답변1
여기에는 두 가지 방법이 있습니다. 애플리케이션을 신뢰하지 않는 경우 두 번째 방법으로 직접 이동할 수 있습니다.
1.umount --lazy
방해하는 프로세스가 마운트 지점에 들어가지 않고 chdir()
(예: 절대 경로 사용) 결국 포기할 것이라는 것을 알고 있다면 Linux에서는 다음을 사용할 수 있습니다 umount --lazy
. 커널은 디렉토리 트리에서 파일 시스템의 매핑을 해제하여 다른 사용자가 액세스할 수 없도록 만듭니다. 새로운 액세스 권한을 부여하고 마지막 참조가 사라지면 자동으로 언로드합니다. 참조는 열린 fd, cwd, 내부 마운트 지점일 수 있습니다(마지막 지점은 아마도 좋지 않을 것입니다)...
그러나 이는 참조를 "내부적으로" 유지하는 프로세스/스레드에 영향을 미치지 않습니다. 예를 들어 파일 설명자가 여전히 열려 있거나서부 독일안에. 그러면 이제 파일 시스템에 더 이상 액세스할 수 없고 문제가 되는 프로세스/스레드를 추적하는 것이 더 어려워지기 때문에 이것이 더 어려워질 것입니다(예: fuser -m
더 이상 찾을 수 없음). 따라서 이 방법을 올바르게 수행하려면 프로세스가 필요합니다.
2.냉동 장치
작동해야 하는 대체 솔루션나쁜 행동프로세스: 이러한 모든 프로세스(및 스레드)를 동일한 Freezer cgroup으로 그룹화합니다. 모두 동결하여 마운트 지점에 리소스 사용량을 추가하는 것을 방지합니다(새 fd를 분기/복제/열기). 첫 번째 루프에서 일부를 놓치더라도 결국 후속 반복에서 새로운 모든 것을 발견하게 될 것입니다. 이제 동결되었으므로 새로운 활동이 발생하지 않습니다. 이제 모두 죽일 수 있습니다. cgroups v1의 경우 운영 체제에 의해 초기화되었습니다(예: 다음을 통해).체계또는CG매니저그렇지 않으면 어떻게 해야 하는지 알아내야 합니다.고정 cgroup 하위 시스템 설치), 이와 같은 것이 작동해야 합니다. 분명히 쓰기에는 cgroup.procs
존재해야 하는 모든 스레드가 포함되어야 tasks
하지만 신뢰할 수 없는 동작에 대한 보고가 있으므로, 필요하지 않더라도 스레드에 대해 반복하는 경우도 있습니다(예: tasks
스레드가 이미 있을 수 있음 ). 올바르게 채워졌으므로 루프가 for t
추가됩니다).
mkdir -p /sys/fs/cgroup/freezer/prepareumount
echo FROZEN > /sys/fs/cgroup/freezer/prepareumount/freezer.state
for i in $(seq 1 10); do
for p in $(fuser -m /mount/v1 2>/dev/null); do
echo $p > /sys/fs/cgroup/freezer/prepareumount/cgroup.procs
for t in $(ps -L -o tid= -p $p); do
echo $t > /sys/fs/cgroup/freezer/prepareumount/tasks
done
done
done
#give time to an overloaded kernel to freeze everything (FREEZING->FROZEN)
while ! cat /sys/fs/cgroup/freezer/prepareumount/freezer.state | grep -q FROZEN; do
sleep 0.1
done
# kills, delayed
for i in $(cat /sys/fs/cgroup/freezer/prepareumount/cgroup.procs); do
kill -KILL $i
done
# actual kills happen now, at once
echo THAWED > /sys/fs/cgroup/freezer/prepareumount/freezer.state
sleep 1
umount /mount/v1
cgroups v2를 사용하는 경우 이를 조정해야 합니다.