공간을 절약하기 위해 여러 단계로 분할 tar 아카이브를 만드는 방법은 무엇입니까?

공간을 절약하기 위해 여러 단계로 분할 tar 아카이브를 만드는 방법은 무엇입니까?

tar 아카이브를 만들려고 하는 매우 큰 폴더가 있습니다. 문제는 전체 아카이브를 저장할 추가 여유 공간이 부족해서 한 번에 100~200GB의 아카이브 청크를 생성하여 개별적으로 클라우드 스토리지로 전송하고 싶다는 것입니다. HDD가 가득 차지 않도록 새 청크가 생성되는 시기를 제어할 수 있어야 하지만 분할 타르볼을 생성하는 모든 명령은 항상 동일한 디렉토리에 한 번에 모든 청크를 생성한다는 것을 발견했습니다.

내가 찾은 가장 가까운 해결책은 다음에서 나왔습니다.이 문제그러나 모든 응답은 크기보다는 파일 수를 기준으로 보관됩니다. 이는 파일 크기가 균등하게 분산되지 않기 때문에 사용 사례에 중요합니다.

답변1

tar다음 옵션과 함께 을 사용할 수 있습니다 .

--새 볼륨 스크립트=주문하다
--테이프 길이=질소

각 볼륨이 끝나면 방금 처리된 볼륨을 알 수 있는 일부 환경 변수가 있는 스크립트를 호출합니다. 확인하다매뉴얼 페이지TAR_VOLUME전체 목록을 보려면 출력 파일의 이름을 바꾸거나 현재 볼륨을 추적해야 하는 경우 최소한 이 변수가 유용합니다.

TAR_VOLUME

    처리 중인 볼륨의 일련 번호 tar(다중 볼륨 아카이브를 읽는 경우 설정)

스크립트가 0을 반환하면 tar계속되고, 그렇지 않으면 중지됩니다.

예를 들어, 최대 크기가 20M인 각 볼륨을 생성하고 제한에 도달할 때마다 스크립트를 호출합니다.

tar cvf /tmp/volume.tar /path/to/files/ --new-volume-script=/path/to/myscript.sh --tape-length=20M

스크립트는 간단할 수도 있고 스크립트에서 전송할 수도 있습니다( 종료되면 덮어쓰게 되므로 echo "Next volume";read볼륨 이름을 바꿉니다 )./tmp/volume.tar

반면에 flag 를 사용해야 합니다 --multi-volume. 이렇게 하지 않으면 tar가 오류와 함께 중지됩니다(누군가 오류를 검색할 경우를 대비하여 이 내용을 남깁니다).

tar: Unexpected EOF in archive
tar: Error is not recoverable: exiting now
tar xvf /path/to/transferred.volume --multi-volume
Prepare volume #2 for /path/to/transferred.volume and hit return: 

tar새 볼륨을 입력하라는 메시지가 표시됩니다. Enter을 누르면 /path/to/transferred.volume다시 켜집니다.

답변2

후속 조치에두아르도 트라파니훌륭한 답변입니다. 아래는 다음에서 발견된 스크립트의 약간 수정된 버전입니다.GNU 페이지각 볼륨에 대한 사용자 입력을 기다렸다가 볼륨을 찾을 수 없으면 다시 시도하십시오.

완전성을 위해 아카이브를 생성하는 데 사용되는 명령은 다음과 같습니다.

tar cvf /tmp/volume.tar /path/to/files/ --new-volume-script=./myscript.sh --tape-length=1000M

이것은 분할 아카이브를 추출하는 데 사용하는 명령입니다.

tar xvf /tmp/volume.tar --multi-volume --new-volume-script=./myscript.sh

myscript.sh:

#!/bin/bash
# For this script it's advisable to use a shell, such as Bash,
# that supports a TAR_FD value greater than 9.

echo "Press enter to continue to next volume"

read

echo Preparing volume $TAR_VOLUME of $TAR_ARCHIVE.

name=`expr $TAR_ARCHIVE : '\(.*\)-.*'`
case $TAR_SUBCOMMAND in
-c)       ;;
-d|-x|-t) test -r ${name:-$TAR_ARCHIVE}-$TAR_VOLUME || echo "Failed to find volume"
          ;;
*)        exit 1
esac

echo ${name:-$TAR_ARCHIVE}-$TAR_VOLUME >&$TAR_FD

편집: 이는 다음을 통해 macOS(Homebrew 포함)에 설치할 수 있는 GNU Tar에서만 작동합니다.

brew install gnu-tar

이를 기본 tar로 사용하려면 다음과 같이 경로에 추가해야 합니다.

export PATH="$(brew --prefix)/opt/python/libexec/bin:$PATH"

답변3

나는 사용하려고조쉬 해리슨의 답변이것은 나에게 효과가 없습니다.
관리되는 호스트이기 때문에 서버에 대한 실제 SSH 액세스 권한이 없습니다. 나는 그것을 사용하고 있다https://github.com/flozz/p0wny-shell조개껍데기 같은 것을 가지고 있습니다.

문제는 p0wny-shell이 ​​표준 입력 스트림을 제공하지 않기 때문에 read명령이 스크립트를 중지하지 않고 부분이 일시 중지되지 않고 계속해서 하나씩 생성된다는 것입니다.

부품을 자동으로 새 서버로 하나씩 이동하도록 수정했습니다.

  1. 부품 생성
  2. 섹션 업로드 및 삭제
  3. 모든 부품이 생성될 때까지 반복합니다.
  4. 마지막 부분을 수동으로 업로드
  5. 원본 myscript.sh를 사용하여 원격 서버에서 압축을 푼다( read부분 사이에 멈추지 않고).
#!/bin/bash
# For this script it's advisable to use a shell, such as Bash,
# that supports a TAR_FD value greater than 9.

if [[ $TAR_SUBCOMMAND != '-c' ]]; then
  echo 'This script can only be used to compress with -c option'
  exit 1;
fi

# $TAR_ARCHIVE per run:
# 1. archive.tar
# 2. archive.tar-2
# 3. archive.tar-3
# ...

# $TAR_ARCHIVE_NAME per run
# 1. <empty>
# 2. archive.tar
# 3. archive.tar
# ...
TAR_ARCHIVE_NAME=`expr $TAR_ARCHIVE : '\(.*\)-.*'`

# $TAR_ARCHIVE_BASE_NAME per run
# 1. archive.tar
# 2. archive.tar
# 3. archive.tar
# ...
TAR_ARCHIVE_BASE_NAME=${TAR_ARCHIVE_NAME:-$TAR_ARCHIVE}

if (( $TAR_VOLUME == 2 )); then
  # On the first run $TAR_VOLUME will be '2', we want to use the base name
  TAR_ARCHIVE_PREV_PART=$TAR_ARCHIVE_BASE_NAME
elif (( $TAR_VOLUME >= 3 )); then
  # On the next runs $TAR_VOLUME we want to build the name with the previous $TAR_VOLUME
  TAR_PREV_VOLUME=$(($TAR_VOLUME-1))
  TAR_ARCHIVE_PREV_PART=$TAR_ARCHIVE_BASE_NAME-$TAR_PREV_VOLUME
fi


echo "Copying $TAR_ARCHIVE_PREV_PART..."
# SSH key was previously created with `ssh-keygen -f ./id_rsa_user` and public key was added to remote
scp \
  -o StrictHostKeyChecking=no \
  -i '/usr/www/users/user/.ssh/id_rsa_user' \
  $TAR_ARCHIVE_PREV_PART \
  [email protected]:/home/user/path/to/target/


echo "Removing $TAR_ARCHIVE_PREV_PART..."
rm $TAR_ARCHIVE_PREV_PART


echo Preparing volume $TAR_VOLUME of $TAR_ARCHIVE_BASE_NAME.
echo $TAR_ARCHIVE_BASE_NAME-$TAR_VOLUME >&$TAR_FD

관련 정보