在 inotifywait 中是否考虑删除事件 close_write?

Are delete events considered close_write in inotifywait?

我有一个简单的 inotifywait 脚本,它监视 FTP 文件上传 关闭 ,然后将它们移动到 aws s3。它似乎在工作,除了在 inotify 日志中,它指示未找到该文件(尽管该文件确实已上传到 s3 )。 s3 move 命令将文件移动到云端并在本地删除它。这可能是因为 inotifywait 将删除文件检测为 close_write 事件吗? 为什么 inotify 似乎执行了两次命令?

TARGET=/home/*/ftp/files

inotifywait -m -r -e close_write $TARGET |
    while read directory action file
    do
        if [[ "$file" =~ .*mp4$ ]]
        then
            echo COPY PATH IS "$directory$file"
            aws s3 mv "$directory$file" s3://bucket
        fi
    done

示例日志:

Setting up watches.  Beware: since -r was given, this may take a while!
Watches established.
COPY PATH IS /home/user/ftp/files/2022/05/16/user-cam-1_00_20220516114055.mp4
COPY PATH IS /home/user/ftp/files/2022/05/16/user-cam-1_00_20220516114055.mp4
COPY PATH IS /home/user/ftp/files/2022/05/16/user-cam-1_00_20220516114055.mp4
move: ../user/ftp/files/2022/05/16/user-cam-1_00_20220516114055.mp4 to s3://bucket/user-cam-1_00_20220516114055.mp4
upload: ../user/ftp/files/2022/05/16/user-cam-1_00_20220516114055.mp4 to s3://bucket/user-cam-1_00_20220516114055.mp4
move failed: ../user/ftp/files/2022/05/16/user-cam-1_00_20220516114055.mp4 to s3://bucket/user-cam-1_00_20220516114055.mp4 [Errno 2] No such file or directory: '/home/user/ftp/files/2022/05/16/user-cam-1_00_20220516114055.mp4'
rm: cannot remove '/home/user/ftp/files/2022/05/16/user-cam-1_00_20220516114055.mp4': No such file or directory
                                                                                                                  

Cleaned-up 您的脚本并添加了引号和检查已处理文件的安全性,以防文件系统触发同一文件的重复事件。

#!/usr/bin/env bash

# Prevents expanding pattern without matches
shopt -s nullglob

# Expands pattern into an array
target=(/home/*/ftp/files/)

# Creates temporary directory and cleanup trap
declare -- tmpdir=
if tmpdir=$(mktemp -d); then
  trap 'rm -fr -- "$tmpdir"' EXIT INT
else
  # or exit error if it fails
  exit 1
fi

# In case no target matches, exit error
[ "${#target[@]}" -gt 0 ] || exit 1

s3move() {
  local -- p=
  local -- tmp="$tmpdir/$p"
  printf 'Copy path is: %s\n' "$p"
  # Moves the file to temporary dir
  # so it is away from inotify watch dir ASAP
  mv -- "$p" "$tmp"

  # Then perform the slow remote copy to s3 bucket
  # Remove the echo onces it is ok
  echo aws s3 mv "$p" s3://bucket
  
  # File has been copied to s3, tmp file no longer needed
  rm -f -- "$tmp"
}

while read -r -d '' p; do
  # Skip if file does not exist, as it has already been moved away
  # case of a duplicate event for already processed file
  [ -e "$p" ] || continue
  s3move "$p"
done < <(
  # Good practice to spell long option names in a script
  # --format will print null-delimited full file path
  inotifywait \
    --monitor \
    --recursive \
    --event close_write \
    --includei '.*\.mp4$' \
    --format '%w%f%0' \
    "${target[@]}" 2>/dev/null
)