그 자리에 타르 아카이브를 추출


14

여기에 약간의 딜레마가 있습니다 ...

내 서버 중 하나에서 다른 서버로 약 70GB 상당의 파일을 이동해야했기 때문에 파일을 압축 해제하고 아카이브를 보내는 것이 가장 빠른 방법이라고 결정했습니다.

그러나 수신 서버는 tar 아카이브를 수신 한 후 5GB의 공간 만 남습니다.

'in-place'타르를 추출 할 수있는 방법이 있습니까? 압축 파일을 추출한 후에 보관할 필요가 없으므로이 작업을 수행 할 수 있는지 궁금합니다.

편집 : 보관 파일이 이미 전송되었으며 다른 방법으로 다시 전송하지 않도록하고 싶습니다.

답변:


11
% tar czf - stuff_to_backup | ssh backupmachine tar xvzf -

이것은 다음과 같이 번역됩니다.

  • tar 및 'stuff_to_backup'을 stdout으로 압축
  • ssh를 통해 'backupmachine'에 로그인
  • 'backupmachine'에서 'tar'를 실행하고 stdin에서 들어오는 내용을 untar하십시오.

연결이 끊어지면 물건을 계속 전송할 수 있기 때문에 개인적으로 'ssh를 통한 rsync'를 사용하여 물건을 전송합니다.

% rsync -ar --progress -e 'ssh' 'stuff_to_backup' user@backupmachine:/backup/

'stuff_to_backup'에서 'backupmachine'의 'backup'폴더로 모든 내용을 전송합니다. 연결이 끊어지면 명령을 반복하십시오. 'stuff_to_backup'의 일부 파일이 변경되면 해당 내용을 반복하면 차이 만 전송됩니다.


내 편집 된 질문보기
익명 겁쟁이

@Charlie Somerville : 그렇습니다. 중요한 부분을 먼저 빼 냈습니다. :)
akira

6

다른 컴퓨터에 ssh가 있으면 tar 파일을 사용하지 않는 다른 대안으로 rsync를 사용하는 것이 좋습니다.

rsync -avPz /some/dir/ user@machine:/some/other/dir/

그리고 선두에 조심 /

업데이트 수정

글쎄, 당신이 그것을 삭제하고 rsync로 다시 시작할 수 없다면 이것이 어떻게 훌륭한 피클인지 알 것입니다. 아마도 선택적 추출을 시도하고 tar에서 삭제합니다.

선택적 추출물 :

$ tar xvf googlecl-0.9.7.tar googlecl-0.9.7/README.txt
googlecl-0.9.7/README.txt

선택적 삭제 :

$ tar --delete --file=googlecl-0.9.7.tar googlecl-0.9.7/README.txt

그러나이 스크립트를 코딩하는 데 많은 시간을 할애하는 것 같습니다 ...


내 편집 된 질문보기
익명 겁쟁이

내 편집 된 답변보기 ... 행운을 빌어 요 :-/
YuppieNetworking

편집 해 주셔서 감사합니다. 파일은 실제로 숫자로 이름이 지정되므로 bash의 빠른 for 루프가 트릭을 수행 할 수 있습니다.
익명 겁쟁이

1
@Charlie Somerville : tar의 끝에 저장된 파일로 시작해야 할 수도 있고, 그렇지 않으면 tar로 새 아카이브를 생성 할 수도 있습니다. 따라서 tar의 끝에서 먼저 파일을 삭제하십시오.
akira

5

기본적으로 필요한 것은 파일을 tar로 파이프하고 앞으로 갈 때 앞면을 "돌릴"가능성입니다.

StackOverflow에서 누군가가 front 에서 파일자르는 방법을 요청 했지만 불가능한 것 같습니다. 특별한 방법으로 파일의 시작 부분을 0으로 채울 수 있으므로 파일이 스파 스 파일 이되지만 어떻게 해야할지 모르겠습니다. 그러나 파일의 끝을자를 수 있습니다. 그러나 tar는 아카이브를 뒤로 읽지 말고 앞으로 읽어야합니다.

해결책 1

간접적 인 수준은 모든 문제를 해결합니다. 먼저 파일을 원래 위치로 되 돌린 다음 뒤로 읽고 (원래 파일을 앞으로 읽게 함) 되 돌린 파일의 끝을 자릅니다.

파일의 시작과 끝을 청크 단위로 교환하고 파일을 한 번에 청크를 자르면서이 청크를 tar로 파이프하는 프로그램 (c, python 등)을 작성해야합니다. 이것이 구현하기가 더 쉬운 솔루션 2의 기초입니다.

해결책 2

또 다른 방법은 파일을 작은 청크로 인플레 이스분할 한 다음 추출한 청크를 삭제하는 것입니다. 아래 코드는 1MB의 청크 크기를 가지며 필요에 따라 조정하십시오. 분리 할 때와 추출하는 동안 더 빠를수록 더 많은 중간 공간이 필요합니다.

archive.tar 파일을 분할하십시오.

archive="archive.tar"
chunkprefix="chunk_"
# 1-Mb chunks :
chunksize=1048576

totalsize=$(wc -c "$archive" | cut -d ' ' -f 1)
currentchunk=$(((totalsize-1)/chunksize))
while [ $currentchunk -ge 0 ]; do
    # Print current chunk number, so we know it is still running.
    echo -n "$currentchunk "
    offset=$((currentchunk*chunksize))
    # Copy end of $archive to new file
    tail -c +$((offset+1)) "$archive" > "$chunkprefix$currentchunk"
    # Chop end of $archive
    truncate -s $offset "$archive"
    currentchunk=$((currentchunk-1))
done

해당 파일을 tar로 파이프하십시오 (두 번째 터미널에는 chunkprefix 변수가 필요합니다).

mkfifo fifo
# In one terminal :
(while true; do cat fifo; done) | tar -xf -
# In another terminal :
chunkprefix="chunk_"
currentchunk=0
while [ -e "$chunkprefix$currentchunk" ]; do
    cat "$chunkprefix$currentchunk" && rm -f "$chunkprefix$currentchunk"
    currentchunk=$((currentchunk+1))
done > fifo
# When second terminal has finished :
# flush caches to disk :
sync
# wait 5 minutes so we're sure tar has consumed everything from the fifo.
sleep 300
rm fifo
# And kill (ctrl-C) the tar command in the other terminal.

명명 된 파이프 ( mkfifo fifo)를 사용하므로 모든 청크를 한 번에 파이프 할 필요는 없습니다. 공간이 부족한 경우 유용 할 수 있습니다. 다음 단계를 수행 할 수 있습니다.

  • 마지막 10Gb 청크를 다른 디스크로 이동하십시오.
  • 아직도 가지고있는 청크로 추출을 시작하십시오.
  • while [ -e … ]; do cat "$chunk…; done루프가 완료 되면 (두 번째 터미널) :
  • tar명령을 중지하지 말고 fifo (첫 번째 터미널)를 제거하지 마십시오sync . 단, 다음과 같은 경우에 실행할 수 있습니다 .
  • 압축이 풀린 일부 추출 된 파일 (데이터가 이러한 파일 추출을 완료하기를 기다리는 동안 tar가 정지되지 않음)을 다른 디스크로 이동하십시오.
  • 남은 덩어리를 뒤로 옮기고
  • while [ -e … ]; do cat "$chunk…; done라인을 다시 실행하여 추출을 재개 하십시오.

물론 이것은 모두 오 볼트입니다 . 당신이 실수를 저지르면 작별 데이터 이기 때문에 먼저 더미 아카이브의 모든 것이 정상인지 확인하고 싶을 것입니다 .

첫 번째 터미널 ( tar)이 실제로 fifo의 내용 처리를 완료했는지 알 수 없으므로 원하는 경우 대신 실행할 수 있지만 다른 디스크와 청크를 원활하게 교환 할 수는 없습니다.

chunkprefix="chunk_"
currentchunk=0
while [ -e "$chunkprefix$currentchunk" ]; do
    cat "$chunkprefix$currentchunk" && rm -f "$chunkprefix$currentchunk"
    currentchunk=$((currentchunk+1))
done | tar -xf -

기권

이 모든 것이 작동하려면 셸, 꼬리 및 자르기가 64 비트 정수를 올바르게 처리해야합니다 (64 비트 컴퓨터 또는 운영 체제가 필요하지 않음). 광산은하지만 이러한 요구 사항이없는 시스템에서 위의 스크립트를 실행하면 archive.tar의 모든 데이터가 손실 됩니다.

어쨌든 잘못 된 것이 있으면 archive.tar의 모든 데이터가 손실되므로 데이터 백업이 있는지 확인하십시오.


0

이동할 오브젝트 파일이있는 경우 제거하십시오. 이렇게하면 상당한 공간이 절약됩니다.

$ strip `find . -name "*.bin"`
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.