S3 삭제된 파일 파이썬으로 복구하기(feat. python)
Paul Granduer Lee /클라우드 서비스

S3 삭제된 파일 파이썬으로 복구하기(feat. python)

S3 기능중 버저닝 기능이 활성화되어 있다면, 파일이 삭제되도 복구할 수 있다.
단, 버저닝된 파일조차 영구삭제가 가능하기 때문에 영구삭제하면 복구 불가

 

버저닝 기능이 활성화되어 있는 상태에서 파일 또는 폴더가 삭제된다면 삭제마커가 생성된 채로 

버저닝된다.

아래 그림은 버저닝 리스트 보기를 활성화한 상태로 같이 Type 부분에 Delete marker라고 찍히고 삭제되어 있는 모습을 볼수있다.

버저닝 리스트가 비활성화 된 모습

 

파일이 한두개면, 그냥 버저닝 리스트 활성상태에서 체크박스 체크해서 Delete를 해버리면 

 

리스트로 다시 돌아오는것을 알수 있다.

 

단, 파일이 복수개이고, 폴더가 복수개인 경우는 수동으로 하기가 힘들기 때문에 SDK를 통해서 수행하는것이 편하다.

 

참고. CLI로 찾아 삭제하는법(단건삭제)

#aws s3api delete-object --bucket 버킷명 --key 파일또는폴더 --version-id 버전ID

#최상위 path에 있는 파일 삭제
aws s3api delete-object --bucket midasit-kr-dv-valut-test --key valut1 --version-id IF6CbyuridA7g3vbzCFajGnKdBINtiYI

#특정 path에 있는 파일 삭제
aws s3api delete-object --bucket midasit-kr-dv-valut-test --key valut1/setup.log --version-id ThQCqZkRAhFH3KYkAp51YncsLhh7c9ov

 

Python으로 다건 삭제
(실행전에 accesskey가 OS에 적용되어 있어야 하며, 그렇지 않다면 코딩상 accesskey를 추가해줘도 동작한다.)

import boto3
import botocore

BUCKET_NAME = '버킷명'
PrefixList= [
        #'복구대상',
        'test/',
        'valut/',
        'valut1/'
]
s3 = boto3.resource('s3')
#s3 = boto3.resource('s3', aws_access_key_id="accesskey 입력", aws_secret_access_key="시크릿키 입력", region_name='ap-northeast-2')


def main():
    bucket = s3.Bucket(BUCKET_NAME)
    for prefixList in PrefixList:
        prefix=prefixList
        versions = bucket.object_versions.filter(Prefix=prefix)
        
        for version in versions.all():
            if is_delete_marker(version):
                 version.delete()
                 
        print(BUCKET_NAME+'/',prefix,'restore done')
        
            


def is_delete_marker(version):
    try:
        # note head() is faster than get()
        version.head()
        return False
    except botocore.exceptions.ClientError as e:
        if 'x-amz-delete-marker' in e.response['ResponseMetadata']['HTTPHeaders']:
            return True
        # an older version of the key but not a DeleteMarker
        elif '404' == e.response['Error']['Code']:
            return False


if __name__ == '__main__':
    main()     

 

코드는 더 이쁘고 알차게 수정할수 있지만 귀찮아서 여기까지