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