Bash 脚本(cron 作业?)来处理上传到目录的文件?

问题描述 投票:0回答:1

假设我有一个名为 jpeg2txt 的工具。我需要编写一个 bash 脚本:

  1. 不断检查
    source
    目录下是否有新文件(JPEG)
  2. 在它们上启动 jpeg2txt,并将结果写入
    target
    目录
  3. 随后删除源 JPEG

现在,我是一名开发人员,但我对 bash 脚本的了解相当有限。 你能指出我应该从哪里开始吗?

我想该脚本可能需要安排为 cron 作业,每分钟启动一次......?

但是我可以看到两个问题:

  • 假设第 2 步(JPEG 处理)可能需要很长时间 - 例如15分钟。 cron 是否会继续每分钟产生新的脚本实例,最终导致约 15 个并行作业在同一组文件上运行?也许不使用 cron,最好让一个脚本在循环中运行(在后台,就像守护进程),如果没有什么可处理的,就休眠 1 分钟?
  • 假设文件通过 (S)FTP 上传到
    source
    目录。如果一个文件仅上传了 50%,我们就开始处理怎么办?换句话说,如何确保步骤 2.) 仅在完整上传时启动,而不是部分上传?我们可以以某种方式跳过处理打开的文件吗?

谢谢!

bash shell cron scripting
1个回答
0
投票

对于您的情况,您可以创建一个 .lock 文件,该文件将确保该文件正在被处理并且不应再次处理,如下所示,

#!/bin/bash

source_dir="source"
target_dir="target"

while true; do
    # Check for new JPEGs in the source directory
    new_files=$(find "$source_dir" -maxdepth 1 -type f -iname "*.jpg" -newer "$source_dir" -print -quit)

    if [ -n "$new_files" ]; then
        # Process new files
        for file in $new_files; do
            # Check if the file is complete (see the next section)
            if is_file_complete "$file"; then
                # Process the file
                jpeg2txt "$file" > "$target_dir/$(basename "$file" .jpg).txt"

                # Remove the source file
                rm "$file"
            fi
        done
    fi

    # Sleep for a minute before checking again
    sleep 60
done

确保完整的文件上传:

为了确保您只处理完整的文件,您可以使用多种技术的组合:

a.文件锁定:在处理文件之前,在同一目录中创建一个锁定文件(例如 file.jpg.lock)。如果锁定文件已经存在,则表示该文件正在上传或处理中,应跳过。处理完成后,删除锁定文件。

b.检查打开的文件句柄:您可以使用 lsof 命令检查文件当前是否打开(即正在写入)。如果是,则跳过处理。

c.检查更改:在处理文件之前,记录其大小和时间戳。短暂延迟(例如 5 秒)后,检查文件大小或时间戳是否已更改。如果没有,则假设它已完成并进行处理。

这是结合了这些技术的 is_file_complete 函数的示例:

is_file_complete() {
    local file="$1"
    local lock_file="$file.lock"

    # Check if the lock file exists
    if [ -f "$lock_file" ]; then
        return 1
    fi

    # Create the lock file
    touch "$lock_file"

    # Check if the file is open
    if lsof "$file" > /dev/null; then
        rm "$lock_file"
        return 1
    fi

    # Record the file size and timestamp
    size1=$(stat -c%s "$file")
    time1=$(stat -c%Y "$file")

    # Wait for 5 seconds
    sleep 5

    # Check if the file size or timestamp has changed
    size2=$(stat -c%s "$file")
    time2=$(stat -c%Y "$file")

    if [ "$size1" == "$size2" ] && [ "$time1" == "$time2" ]; then
        # File is complete
        rm "$lock_file"
        return 0
    else
        # File is still being written
        rm "$lock_file"
        return 1
    fi
}

此函数检查锁定文件是否存在,如果不存在则创建一个新文件,然后使用 lsof 检查该文件是否打开。如果文件已打开,则假定正在写入该文件并返回 1(不完整)。如果文件未打开,则记录文件大小和时间戳,等待 5 秒,然后检查大小或时间戳是否已更改。如果不是,则假定文件完整并返回 0。否则,返回 1(不完整)。

您可以将此函数合并到脚本中,以确保您只处理完整的文件。

请注意,这只是一种方法,根据您的具体要求和环境,可能还有其他技术或优化。

© www.soinside.com 2019 - 2024. All rights reserved.