Github Actions 워크플로 실행 중에 발생한 'rsync: [generator] delete_file' 에러 Troubleshooting

김동욱·2024년 4월 11일
0

Troubleshooting

목록 보기
7/14
post-thumbnail

제목과 동일하게 Github Actions 워크플로 실행 중에 'rsync: [generator] delete_file' 에러가 발생했다. 정확한 에러를 살펴보면 다음과 같다.

rsync: [generator] delete_file: unlink(backend/logs/backend_2024-04-08.log) failed: Permission denied (13)
rsync: [generator] delete_file: unlink(nginx/logs/error.log) failed: Permission denied (13)
rsync: [generator] delete_file: unlink(nginx/logs/access.log) failed: Permission denied (13)
cannot delete non-empty directory: backend/logs
cannot delete non-empty directory: nginx/logs

에러가 발생한 step을 살펴보면 다음과 같다.

    - name: copy source via ssh key
      uses: burnett01/rsync-deployments@4.1
      with:
        switches: -avzr --delete
        remote_path: /home/ubuntu/srv/
        remote_host: ${{ secrets.SSH_HOST }}
        remote_user: ${{ secrets.SSH_USERNAME }}
        remote_key: ${{ secrets.SSH_KEY }}

서버에 원격 접속하여 소스코드를 복사하는 과정이다. 여기서 Github Actions의 동작을 간략하게 살펴보자.

내가 작성한 워크플로의 첫 번째 step이다.

    - name: checkout
      uses: actions/checkout@master

레포지토리에서 최신 코드를 가져오는 과정이다. 이 step에서는 actions/checkout을 사용하여 GitHub 저장소의 코드를 Runner(실행 환경)에 복제한다. 이후의 step에서 rsync를 사용하여 GitHub Runner에 복제해둔 코드를 서버로 코드를 동기화한다.

rsync는 'Remote Sync'의 줄임말로 파일과 디렉토리를 동기화하기 위한 프로토콜이자 리눅스의 유틸리티 명령어다. rsync 명령어 를 이용해 로컬에 있는 파일이나 디렉토리를 원격 호스트로 보내거나 원격에 있는 파일, 디렉토리를 로컬로 복사해 올 수 있다.

rsync를 사용하여 코드를 복제하는 과정에서 rsync의 옵션을 -avzr --delete 처럼 지정했다. --delete 옵션은 소스 디렉토리에 없는 파일이 대상 디렉토리에 존재할 경우 이를 삭제한다. 그리고 삭제하는 과정에서 권한 관련 에러가 발생한 것이다.

여기서 해결책은 두 가지가 있었다. Dockerfile을 수정하여 디렉토리 권한을 변경하거나 디렉토리 권한을 변경하는 step을 추가하는 방법은 해당 디렉토리를 확실히 지울 수 있는 방법이다. 하지만 현재 지우려고 하는 디렉토리는 로그가 저장돼 있는 디렉토리로, Docker volume의 위치이기도 하다. 따라서 디렉토리를 지우는 것이 아닌 rsync의 옵션을 추가하는 방식을 선택했다.

문제가 있는 step을 다음과 같이 수정했다.

- name: Copy source via ssh key excluding logs
      uses: burnett01/rsync-deployments@4.1
      with:
        switches: -avzr --delete --exclude='backend/logs/*' --exclude='nginx/logs/*'
        remote_path: /home/ubuntu/srv/
        remote_host: ${{ secrets.SSH_HOST }}
        remote_user: ${{ secrets.SSH_USERNAME }}
        remote_key: ${{ secrets.SSH_KEY }}

주목할 부분은 -avzr --delete --exclude='backend/logs/*' --exclude='nginx/logs/*'이다. --exclude 옵션을 추가하여 기존에 존재하는 디렉토리를 삭제할 때 로그 디렉토리를 제외시켰다. 이렇게 수정하면 정상 동작한다.

profile
안녕하세요! 질문과 피드백은 언제든지 환영입니다:)

0개의 댓글