ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 특정 디렉터리에서 변경된 파일을 나스(NAS)에 FTP 프로토콜을 통해 복사(업로드)하는 프로그램
    PYTHON(파이썬)/파이썬 활용 2024. 11. 15. 07:21
    728x90
    반응형
    ###################################################
    # 파일을 나스에 복사 - FTP
    #   Date : 2023-08-10  By : EPLUS
    #    1. 폴드에서 변경된 일자 기준으로
    #    2. NAS에 접속 후 Upload (FTP)
    ###################################################
    import ftplib
    import os, sys, time, shutil
    from datetime import datetime, timedelta
    #######################################################
    def upload_file(path, filename):
        os.chdir(path)
        myfile = open(filename,'rb')
        ftp.storbinary('STOR '+ filename, myfile)
        myfile.close()
        #
        print("upload_file: ", path, filename)
        #
    #    
    def CopyFile(directory, fromFile, toFile):
        try:
            if not os.path.exists(directory):
                os.makedirs(directory)
            shutil.copyfile(fromFile, toFile)
        except OSError:
            print("Error: Failed to create the directory.")
    #######################################################    
    sfrom = "c:/epython"  # c:/ or e:/  폴드가 있으면 e:/ework
    sto = "./g/cbackup"  # FTP 폴드 대/소문자 구분함

    if len(sys.argv) == 3:
        sfrom = sys.argv[1]
        sto = sys.argv[2]
    #
    ftp = ftplib.FTP()
    ftp.set_debuglevel(0)
    ftp.encoding = 'cp949'  # 한글 폴드 또는 파일 처리 시 utf-8 대신 사용
    ftp.connect("t.e.co.kr", 231)
    ftp.login("ftpA","A123~")
    #
    now = datetime.now()
    snow = now.strftime('%Y-%m-%d %H:%M:%S')
    print("Backup Start : ", snow, sfrom, sto)
    #
    now = datetime.now()
    snow = now.strftime('%Y-%m-%d')
    now = now - timedelta(days=1)
    snow0 = now.strftime('%Y-%m-%d')
    #
    iFcnt = 0
    #######################################################
    # pC에서 일단위로 ftp에 저장 - 대상 파일 및 폴드 지정
    #######################################################
    if sfrom != '':
        smypath = sfrom
    if sto != '':
        smyftp = sto
    #######################################################
    sdir = smyftp + "/" + snow
    ftp.cwd(smyftp)
    #
    try:
        if snow not in ftp.nlst():
            ftp.mkd(snow)
    except:
        print("### 폴드생성 오류 1 ###_DIR: ", snow)

    ftp.cwd(snow)
    #
    print("1:_" + smyftp, snow)    
    #######################################################
    for (path, dir, files) in os.walk(smypath):
        for filename in files:
            sdate = datetime.fromtimestamp(os.path.getmtime(path + str("/")+ filename)).strftime('%Y-%m-%d')
            stime = datetime.fromtimestamp(os.path.getmtime(path + str("/")+ filename)).strftime('%H:%M:%S')
            #
            if sdate == snow or sdate == snow0:  # 당일 또는 전일에 수정 또는 생성된 파일
                iFcnt = iFcnt + 1
                #print(path + str("/")+ filename, stime)
                #
                sdir2 = path
                sdir2 = sdir2.replace(chr(92), '/')
                sdir2 = sdir2.replace('/', '_')
                sfdir = sdir+"/"+sdir2
                #--------------------------------------------------
                #try:
                #    if sdir2 not in ftp.nlst():
                #        print("3.1:_" + sfdir)
                ##        ftp.mkd(sdir2)
                #except Exception as err:
                #    print("### 폴드생성 오류 2###_DIR: " , err)
                #-------------------------------------------------
                if len(sdir2) > 100:
                    sdir2 = sdir2[:90] + 'XXXX'
                try:
                    ftp.cwd(sdir2)
                except:
                    if ftp.pwd() != sdir2:
                        ftp.mkd(sdir2)                
                        ftp.cwd(sdir2)
                #
                print("4:_" + sdir2 + ' : ' + str(iFcnt))
                #
                try:
                    upload_file(path, filename)
                except Exception as err:
                    print("### Upload 오류 ###_FiLE: ", filename, err)
                    # 오류발생시 파일 복사
                    spath = "e:/back_file/" + snow
                    fromFile = path + '/' + filename
                    toFile = spath + '/' + filename
                    CopyFile(spath, fromFile, toFile)                
                    #
                    time.sleep(1)
                #                
                try:
                    ftp.cwd("..")                
                except:
                    print("### 폴드이동 오류 ###_path: ", path)
                    time.sleep(1)
                    ftp.cwd("..")
                time.sleep(0.1)
    ########################################################
    ftp.close
    ########################################################
    now = datetime.now()
    snow = now.strftime('%Y-%m-%d %H:%M:%S')
    print("Backup 완료 : ", snow, smypath, smyftp)
    #######################################################

    NAS FTP 접속 정보는 임의로 변경했음...개발자의 NAS 접속 정보에 맞게 수정 가능후 사용가능....

    이 코드는 특정 디렉터리에서 변경된 파일을 나스(NAS)에 FTP 프로토콜을 통해 복사(업로드)하는 프로그램입니다. 주석과 코드를 통해 기능을 단계적으로 설명하겠습니다.

    ### 주요 목적 및 흐름
    1. **지정된 폴더의 변경된 파일을 찾는다.**
    2. **FTP 서버에 접속하여 NAS에 업로드한다.**
    3. **업로드에 실패한 파일은 로컬 백업 디렉터리에 복사한다.**

    ### 주요 구성 요소
    1. **라이브러리 임포트**
       ```python
       import ftplib
       import os, sys, time, shutil
       from datetime import datetime, timedelta
       ```
       - `ftplib`: FTP 기능을 사용하기 위해 필요합니다.
       - `os`, `sys`, `time`, `shutil`: 파일 및 폴더를 다루고, 시간을 조정하며 시스템 작업을 처리하는 라이브러리입니다.
       - `datetime`, `timedelta`: 날짜와 시간을 다루는 데 사용됩니다.

    2. **FTP 파일 업로드 함수**
       ```python
       def upload_file(path, filename):
           os.chdir(path)
           myfile = open(filename, 'rb')
           ftp.storbinary('STOR ' + filename, myfile)
           myfile.close()
           print("upload_file: ", path, filename)
       ```
       - FTP를 통해 파일을 업로드하는 함수입니다.
       - 파일을 바이너리 모드로 읽고, FTP 서버에 업로드합니다.

    3. **로컬 파일 복사 함수**
       ```python
       def CopyFile(directory, fromFile, toFile):
           try:
               if not os.path.exists(directory):
                   os.makedirs(directory)
               shutil.copyfile(fromFile, toFile)
           except OSError:
               print("Error: Failed to create the directory.")
       ```
       - 파일 복사 중 에러가 발생할 경우 디렉토리를 생성하고 복사합니다.

    4. **FTP 접속 설정 및 기본 경로 설정**
       ```python
       ftp = ftplib.FTP()
       ftp.set_debuglevel(0)
       ftp.encoding = 'cp949'  # 한글 폴드 또는 파일 처리 시 utf-8 대신 사용
       ftp.connect("t.e.co.kr", 231)
       ftp.login("ftpA", "A123~")
       ```
       - `cp949` 인코딩은 한글 파일명 처리를 위해 사용됩니다.
       - FTP 서버에 접속 후 로그인을 시도합니다.

    5. **백업 시작 시점과 전날 날짜 설정**
       ```python
       now = datetime.now()
       snow = now.strftime('%Y-%m-%d')
       now = now - timedelta(days=1)
       snow0 = now.strftime('%Y-%m-%d')
       ```
       - 백업 작업의 현재 시간 및 전날 날짜를 설정합니다.
       - 당일과 전일 파일을 구분하여 업로드합니다.

    6. **FTP 폴더 생성 및 파일 업로드**
       ```python
       sdir = smyftp + "/" + snow
       ftp.cwd(smyftp)
       try:
           if snow not in ftp.nlst():
               ftp.mkd(snow)
       except:
           print("### 폴드생성 오류 1 ###_DIR: ", snow)
       ```
       - 지정된 NAS의 폴더로 이동한 후, 당일 날짜 폴더가 없으면 생성합니다.
       - FTP 서버에서 현재 폴더 목록을 확인하고, 날짜 폴더가 없으면 새로 생성하는 방식입니다.

    7. **디렉터리 순회 및 파일 조건에 따른 업로드**
       ```python
       for (path, dir, files) in os.walk(smypath):
           for filename in files:
               sdate = datetime.fromtimestamp(os.path.getmtime(path + str("/") + filename)).strftime('%Y-%m-%d')
               ...
               if sdate == snow or sdate == snow0:
                   ...
                   try:
                       upload_file(path, filename)
                   except Exception as err:
                       ...
                       CopyFile(spath, fromFile, toFile)
       ```
       - 지정된 폴더(`smyftp`)를 순회하면서 파일의 최종 수정 날짜를 확인합니다.
       - 당일(`snow`) 또는 전일(`snow0`)에 수정된 파일만 업로드 대상으로 간주합니다.
       - 업로드 실패 시 `CopyFile` 함수를 호출해 로컬 백업 디렉터리에 복사합니다.

    8. **마무리 및 종료 로그**
       ```python
       ftp.close()
       now = datetime.now()
       snow = now.strftime('%Y-%m-%d %H:%M:%S')
       print("Backup 완료 : ", snow, smypath, smyftp)
       ```
       - 모든 작업이 완료되면 FTP 연결을 종료하고 작업 완료 시간을 출력합니다.

    ### 주요 기능 요약
    1. **파일 탐색 및 수정 시간 확인**: `os.walk()`와 `os.path.getmtime()`을 사용해 지정된 폴더 내 모든 파일을 탐색하며, 특정 시간 기준으로 필터링합니다.
    2. **FTP 서버 접속 및 폴더 생성**: NAS에 해당하는 FTP 서버에 접속하고, 필요하면 날짜별 폴더를 생성합니다.
    3. **파일 업로드**: 수정된 파일을 FTP 서버에 업로드합니다.
    4. **에러 처리**: 업로드 실패 시 파일을 로컬 백업 디렉터리에 복사합니다.

    이 프로그램은 일정 폴더의 파일을 기준으로 NAS에 백업하는 목적으로 설계되었으며, 사용자는 경로를 변경하거나 FTP 설정을 조정하여 다양한 백업 상황에 대응할 수 있습니다.

    728x90
Designed by Tistory.