MOYOMOYO
이명진 · PERSONAL BLOG

MOYO

생각과 경험을 기록하는 공간입니다.

← 글 목록

[리눅스]특정 경로에 파일이 존재하는 경우 특정 디렉토리에 이동시키기

이명진조회 2댓글 0

스크립트 설계

  1. 로그 함수 정의:
    • log 함수는 현재 시간과 함께 로그 메시지를 지정된 로그 파일에 기록합니다.
  2. PID 파일 체크:
    • 스크립트가 이미 실행 중인지 확인하고, 실행 중인 경우 스크립트를 종료합니다.
  3. PID 파일 생성 및 종료 시 삭제:
    • 현재 스크립트의 PID를 PID 파일에 저장하고, 스크립트 종료 시 PID 파일을 삭제하도록 설정합니다.
  4. 무한 루프:
    • WATCH_DIR 디렉토리가 존재하는지 확인합니다.
    • find 명령어를 사용하여 WATCH_DIR와 하위 디렉토리의 모든 파일을 찾습니다.
    • 각 파일의 크기와 수정 시간을 측정하여 일정 시간 동안 변경되지 않았으면 파일을 복사합니다.
    • cp 명령어를 사용하여 파일을 DEST_DIR로 복사한 후, 복사된 파일의 크기가 원본과 동일한 경우에만 원본 파일을 삭제합니다.
    • rm 명령어를 사용하여 원본 파일을 삭제합니다. 삭제가 실패할 경우 로그에 기록합니다.
  5. 하위 디렉토리 포함:
    • find "$WATCH_DIR" -type f 명령어를 사용하여 하위 디렉토리의 파일도 포함하여 검색합니다.

이 스크립트는 파일 복사가 완료된 후 원본 파일을 삭제하므로 데이터 손실의 위험을 줄일 수 있습니다. 로그 파일을 주기적으로 확인하여 스크립트의 동작 상태를 모니터링하는 것이 좋습니다.

#!/bin/bash

WATCH_DIR="/downloads/completed"
DEST_DIR="/home/completed"
LOG_FILE="/home/file_watch.log"
PIDFILE="/var/run/file_watch.pid"

# 로그 함수 정의
log() {
    local message="$1"
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $message" >> "$LOG_FILE"
}

# PIDFILE 체크
if [ -f "$PIDFILE" ]; then
    echo "Script is already running with PID $(cat $PIDFILE). Exiting."
    exit 1
fi

# PIDFILE 생성
echo $$ > "$PIDFILE"

# 종료 시 PIDFILE 삭제
trap 'rm -f "$PIDFILE"; exit' INT TERM EXIT

# 무한 루프 시작
while true; do
    # WATCH_DIR이 존재하는지 확인
    if [ ! -d "$WATCH_DIR" ]; then
        log "Watch directory $WATCH_DIR does not exist."
        rm -f "$PIDFILE"
        exit 1
    fi
    
    # 현재 디렉토리에서 하위 디렉토리를 포함한 파일 목록을 가져옴
    find "$WATCH_DIR" -type f | while IFS= read -r file; do
        # 파일이 존재하는지 확인
        if [ ! -e "$file" ]; then
            log "File $file does not exist."
            continue
        fi
        
        # 파일 크기 측정
        initial_size=$(stat -c%s "$file")
        initial_mtime=$(stat -c%Y "$file")
        # 파일을 잠시 기다린 후 다시 크기와 수정 시간을 측정
        sleep 300
        new_size=$(stat -c%s "$file")
        new_mtime=$(stat -c%Y "$file")
        
        # 파일 크기와 수정 시간이 변하지 않으면 복사 후 원본 삭제
        if [ "$initial_size" -eq "$new_size" ] && [ "$initial_mtime" -eq "$new_mtime" ]; then
            # 목적지 파일 경로
            dest_file="$DEST_DIR/$(basename "$file")"
            # 파일 복사
            cp "$file" "$dest_file" 2>> "$LOG_FILE"
            if [ $? -eq 0 ]; then
                # 복사 성공 후 원본 파일 삭제
                if [ "$initial_size" -eq "$(stat -c%s "$dest_file")" ]; then
                    rm "$file" 2>> "$LOG_FILE"
                    if [ $? -eq 0 ]; then
                        log "Moved $(basename "$file") to $DEST_DIR"
                    else
                        log "Failed to delete the original file $(basename "$file") after copy."
                    fi
                else
                    log "Size mismatch after copying $(basename "$file") to $DEST_DIR."
                fi
            else
                log "Failed to copy $(basename "$file") to $DEST_DIR. Check log for details."
            fi
        else
            log "File $file is still being modified or its size changed."
        fi
    done

    sleep 10
done

위의 스크립트가 file_watch.sh 라고 할 때, 백그라운드로 실행시키고 싶다면,

sudo nohup ./file_watch.sh &

백그라운드로 실행되 있는 스크립트를 확인하고자 한다면,

sudo ps aux | grep file_watch.sh

백그라운드로 실행하고 있는 스크립트를 종료시키고자 한다면,

sudo pkill -f file_watch.sh

그런데, 백그라운드 실행 방식은 세션이 종료되면 함께 종료될 수 있다.

따라서, 서비스로 등록시켜서 재부팅이 된 후에도 실행이 되도록 하자.

sudo nano /etc/systemd/system/file_watch.service

아래와 같이 입력하고 저장한다.

[Unit]
Description=File Watch Script

[Service]
ExecStart=/path/to/your/file_watch.sh
Restart=always
User=root

[Install]
WantedBy=multi-user.target

아래 명령어를 차례대로 수행하여 활성화 시켜주자.

sudo systemctl daemon-reload
sudo systemctl enable file_watch.service
sudo systemctl start file_watch.service

file_watch 서비스의 실행 여부는 아래 명령으로 확인한다.

sudo service file_watch status

#파일감시 #파일이동 #리눅스 #쉘스크립트

댓글 0

등록된 댓글이 없습니다.