【问题标题】:bash: how to keep some delay between multiple instances of a scriptbash:如何在脚本的多个实例之间保持一些延迟
【发布时间】:2020-05-13 06:03:43
【问题描述】:

我正在尝试使用脚本下载 100 个文件

我不希望任何时候发生的下载次数不超过 4 次。

所以我创建了一个文件夹/home/user/file_limit。在脚本中,它会在下载之前在此处创建一个文件,下载完成后它将删除它。

脚本会检查文件夹中的文件数量是否小于 4,然后才允许在文件夹 /home/user/file_limit 中创建文件

我正在运行这样的脚本

    today=`date +%Y-%m-%d-%H_%M_%S_%N`;
    while true
    do
        sleep 1
        # The below command will find number of files in the folder /home/user/file_limit
        lines=$(find /home/user/file_limit -iname 'download_*' -type f| wc -l)
        if [ $lines -lt 5 ]; then
            echo "Create file"
            touch "/home/user/file_limit/download_${today}"
            break;
        else
            echo "Number of files equals 4"
        fi
    done

    #After this some downloading happens and once the downloading is complete

    rm "/home/user/file_limit/download_${today}"

我面临的问题是当 100 个这样的脚本正在运行时。例如,当文件夹中的文件数量少于 4 个时,会同时执行许多 touch "/home/user/file_limit/download_${today}" 并创建文件。所以文件总数超过了 4 个,这是我不想要的,因为更多的下载会导致我的系统变慢。

如何确保检查lines=$(find /home/user/file_limit -iname 'download_*' -type f| wc -l)的每个脚本之间存在延迟,以便只执行一个触摸命令。

或者如何确保lines=$(find /home/user/file_limit -iname 'download_*' -type f| wc -l) 命令被队列中的每个脚本检查。没有两个脚本可以同时检查。

【问题讨论】:

  • 这有点 XY 问题。链接的重复答案 X(您实际想要解决的问题)。这个问题是关于 Y(解决你的方法中的问题)。另外,这里有一些关于 Y 部分的信息: ¶ 添加延迟不会解决问题。您需要一个 lockmutexsemaphore 来确保以原子方式执行文件的检查和创建。也就是说,如果一个进程执行“检查和创建文件”部分,其他进程也不能执行这部分。 GNU parallel 为此提供了实用程序 sem
  • 我不想要 X 方式,因为我必须在下载过程中做更多的事情,而不仅仅是 wget。那你能详细解释一下Y方式吗
  • 另外,对于使用并行,您必须知道要并行运行的项目列表。这里可以启动一个新的脚本实例,并且当目录中的文件数小于4时它也会等待触摸文件
  • 除了bugs parallel 完全有能力在事先不知道完整列表的情况下处理一系列工作。此外,您可以像在 shell 中一样在 parallel 中执行多个命令,例如 seq 3 | parallel 'echo 1st step for {}; echo 2nd step for {}' 为每个输入执行命令 echo 1st echo 2nd。无论如何,我为你的问题添加了一个答案(尽管与直接使用 parallel 相比,它可能不是最好的方法)。

标签: linux bash queue


【解决方案1】:

如何确保检查lines=$(find ... | wc -l)的每个脚本之间存在延迟,以便只执行一个触摸命令

添加延迟不会解决问题。您需要一个锁、互斥锁或信号量来确保以原子方式执行文件的检查和创建。

锁将并行进程的数量限制为 1。可以使用flock(通常预先安装)创建锁。 信号量是通用锁,将并发进程的数量限制为任意数量 N。信号量可以使用 sem 创建(GNU 并行的一部分,必须安装)。

以下脚本允许并行下载 4 次。如果 4 次下载正在运行并且您第 5 次启动脚本,则第 5 次下载将暂停,直到 4 次正在运行的下载之一完成。

#! /usr/bin/env bash

main() {
  # put your code for downloading here
}
export -f main
sem --id downloadlimit -j4 main

【讨论】:

  • 在代码中间如何并行运行部分代码并从中捕获返回值并从那里继续我的代码。
  • 为此,您的脚本应具有以下结构: (1) 第一部分 (2) 此答案中的代码,中间部分在里面main--fg 添加到 sem (3) 最后一部分。 ¶ 检查退出代码有点棘手。 sem 不转发退出代码。您可以打印退出代码并读取它 (read code < <(sem … 'main; echo $?')) 或将其写入文件 (sem … 'main; echo $? > /tmp/exitcode')。
  • export -f 做了什么。
  • 我使用的是zsh,上面写着-f no such option for export
  • @SanthoshYedidi 嗯,为什么在使用zsh 时将您的问题标记为bash?我明确为 bash 添加了 shebang,以指出该脚本依赖于 bashism。我不是zsh方面的专家。希望另一位用户想帮助您。祝你好运。
【解决方案2】:

我的解决方案启动最大 MAXPARALELLJOBS 个进程并等待所有这些进程完成...

希望对您的问题有所帮助。

MAXPARALELLJOBS=4
count=0
while <not done the job>
 do
 ((count++))
 ( <download job> ) &
 [ ${count} -ge ${MAXPARALELLJOBS} ] && count=0 && wait
 done

【讨论】:

    猜你喜欢
    • 2023-03-03
    • 2011-09-22
    • 1970-01-01
    • 2017-10-25
    • 2021-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多