예측할 수 없는 상황으로 인해 현재 애플리케이션(종료하고 싶지 않은)이 천천히 전체 디스크 공간을 차지하는 상황에 대한 해결책을 찾아야 합니다. 더 많은 배경 정보 제공
multiprocessing.Pool을 사용하여 5개의 스레드를 시작하는 Python 애플리케이션이 있습니다. 각 스레드는 자체 파일에 일부 데이터를 씁니다.
이 프로그램은 Linux에서 실행되며 컴퓨터에 대한 루트 액세스 권한이 없습니다.
이 프로그램은 CPU를 많이 사용하며 몇 달 동안 실행되었습니다. 아직 모든 데이터를 작성하려면 며칠이 남았습니다.
파일 내 데이터 중 40%는 중복되므로 빠른 테스트 후 삭제할 수 있습니다.
프로그램을 실행하는 시스템에는 남은 디스크 공간이 30GB에 불과하며 현재 작업 속도로 볼 때 프로그램이 완료되기 전에 확실히 채워질 것입니다.
위의 사항을 고려하여 각각의 문제에 대한 다음과 같은 해결책을 봅니다.
i가 file_i에 쓰고 있는 프로세스 번호를 고려하면 file_i를 외부 위치로 이동해도 안전합니까? 운영 체제는 단순히 새로운 file_i 인스턴스를 생성하고 여기에 기록합니까? 파일을 이동하면 해당 파일이 삭제되고 프로세스가 "죽은" 파일을 작성하게 될 것이라고 생각했습니다.
생성된 작업자 5개 중 4개를 중지하고 그 중 하나가 완료될 때까지 기다린 후 작업을 재개하는 "명령줄" 방법이 있습니까? (작업자 스레드가 디스크를 차지하지 않을 것이라고 확신합니다)
Ctrl+Z를 사용하여 기본 프로세스를 정지한다고 가정해 보겠습니다. 이렇게 하면 multiprocessing.Pool에 의해 생성된 다른 모든 프로세스가 중지됩니까? 그렇다면 파일을 안전하게 편집하여 추가 줄을 제거할 수 있습니까?
내가 본 세 가지 옵션이 주어지면 이 상황에서 어떤 옵션이 작동할까요? 그렇지 않다면 이 문제를 처리하는 더 좋은 방법이 있습니까? 프로그램이 완료되기 며칠 전에 충돌이 발생하는 상황은 정말 피하고 싶습니다.
답변1
파일을 다른 파일 시스템으로 이동하면 뒤에서 일어나는 일은 파일의 현재 내용이 복사되고 원본 파일이 삭제되는 것입니다. 프로그램이 여전히 파일에 쓰는 중이면 현재 삭제된 파일에도 계속해서 씁니다. 삭제되었지만 열려 있는 파일은 실제로 삭제되지 않고 분리만 됩니다(더 이상 이름이 없음). 프로그램이 닫힐 때 파일이 실제로 삭제됩니다. 따라서 두 가지 장점을 모두 얻을 수 있습니다. 파일은 여전히 가능한 한 많은 디스크 공간을 사용하지만 나머지 출력은 손실됩니다.
Ctrl+를 눌러 Z포그라운드 프로세스를 일시 중지한 다음 명령을 사용하거나 bg
다시 시작할 수 있습니다 fg
. 프로그램에서 다른 동작이 발생하지 않는 한 모든 스레드는 일시 중단됩니다. (네트워크를 통해 하위 프로세스를 생성하도록 설계된 프로그램은 다른 동작을 나타낼 수 있습니다. 단일 프로세스, 다중 스레드 프로그램은 정상적으로 동작할 가능성이 높습니다.) 프로그램이 다른 프로세스로 구성된 경우 명령을 사용하여 ps
모든 프로세스를 찾고 다음과 kill -STOP 1234 1238 1239
같은 명령을 사용합니다. 모두 걸어 두십시오( kill -CONT …
나중에 복원하기 위해).
프로그램이 파일에 쓰거나 앞뒤로 읽는 경우에는 코 밑에 있는 데이터를 삭제할 수 없습니다. 이 단계에서 데이터 이동은 가능할 수 있지만 어려울 수 있으며 프로그램 작동 방식에 따라 다릅니다. 그러나 귀하의 설명에 따르면 프로그램은 각 파일에 계속 추가할 수 있으며, 이 경우 일부 데이터가 처음에 삭제될 수 있습니다.
파일을 편집하지 마십시오. 원하는 효과를 얻을 가능성이 낮습니다. 대부분의 편집자가 작업하는 방식은 새 파일을 저장하고 이전 파일의 위치로 이동하는 것입니다(저장 시 충돌이 발생하는 경우 더 안정적입니다). 파일의 시작 부분을 잘라서 디스크 공간을 절약할 수 있습니다. 먼저 파일을 복사하여 다른 곳에 데이터를 저장하세요. 그런 다음 파일은 길이 0으로 잘립니다. 프로그램은 이전 위치에 계속 추가합니다. 해당 위치가 12345인 경우 프로그램이 다른 바이트를 추가하면 파일은 12345 널 바이트로 시작됩니다. 대부분의 널 바이트는 디스크 공간을 차지하지 않습니다.스파스 파일.
# Suspend the program first, otherwise you'll lose output produced between cp and truncation!
for x in *.out; do
cp "$x" /elsewhere/
: >|"$x" # truncate $x to size 0
done
프로그램이 완료되면 나머지 데이터를 다른 곳에 저장된 파일에 추가할 수 있습니다. 이것tail
유틸리티는 첫 번째 파일을 생략하고 파일을 복사할 수 있습니다.질소bytes; 이 매개변수는 생략할 바이트 수에 1을 더한 것입니다.
for x in *.out; do
existing_size=$(stat -c %s "/elsewhere/$x")
tail -c +$((existing_size+1)) "$x" >>"/elsewhere/$x"
done
rsync 3.0.0 이상이면 사용할 수 있습니다
rsync --append *.out /elsewhere/
이전 버전의 rsync는 파일의 기존 부분을 소스의 새로운 null 바이트로 덮어쓴다는 점에 유의하세요! 이 작업을 수행하기 전에 rsync 버전을 확인하세요.
답변2
루트 액세스가 없으면 옵션이 매우 제한됩니다. 최선의 선택이자 현실적으로 성공할 수 있는 유일한 기회인 IMHO는 이미 작성하고 닫은 파일을 압축하여 프로그램을 완료할 수 있는 충분한 공간을 확보하는 것입니다. SO 사용자에게는 다른 옵션이 있을 수 있습니다. 거기에 물어보셨나요?
답변3
i가 file_i에 쓰고 있는 프로세스 번호를 고려하면 file_i를 외부 위치로 이동해도 안전합니까? 운영 체제는 단순히 새로운 file_i 인스턴스를 생성하고 여기에 기록합니까? 파일을 이동하면 해당 파일이 삭제되고 프로세스가 "죽은" 파일을 작성하게 될 것이라고 생각했습니다.
프로그램이 계속해서 파일을 열고, 데이터를 쓰고, 다시 닫는다면 파일을 이동하면 새 파일이 생성됩니다. 그것은 대부분의 프로그램이 작동하는 방식이 아닙니다. 운영 체제에서는 파일이 이동되었다고 표시할 수 있지만 실제로는 프로그램이 파일 핸들을 닫을 때까지 디스크 공간을 차지합니다.
생성된 작업자 5개 중 4개를 중지하고 그 중 하나가 완료될 때까지 기다린 후 작업을 재개하는 "명령줄" 방법이 있습니까? (작업자 스레드가 디스크를 차지하지 않을 것이라고 확신합니다)
이는 프로그램이 사용하는 작업자 스레드의 유형에 따라 달라지며 거의 확실하게 루트 액세스가 필요합니다(디버깅 도구를 사용해야 할 수도 있으며 정확한 순서는 프로그램 작동 방식에 따라 크게 달라집니다). 이는 프로그램의 내부 작동에 대한 루트 액세스 및 깊은 지식 없이는 실현 가능하지 않을 수 있습니다.
Ctrl+Z를 사용하여 기본 프로세스를 정지한다고 가정해 보겠습니다. 이렇게 하면 multiprocessing.Pool에 의해 생성된 다른 모든 프로세스가 중지됩니까? 그렇다면 파일을 안전하게 편집하여 추가 줄을 제거할 수 있습니까?
다시 말하지만 프로그램 실행 방법에 따라 다릅니다. 프로세스를 일시 중지하면 작업자도 일시 중지될 가능성이 높지만 이것이 보장되지는 않습니다. 그러나 파일 핸들의 파일 포인터가 여전히 파일을 편집하기 전과 동일한 오프셋을 가리키기 때문에 이것이 문제를 바꾸지는 않는다고 생각합니다.
시스템 밖으로 다른 파일을 이동할 수 있나요? 아니면 가상 디스크를 확장할 수 있는 가상 머신인가요?