【问题标题】:Parallel processing or threading in Shell scriptingShell 脚本中的并行处理或线程
【发布时间】:2012-06-18 16:38:29
【问题描述】:

我正在 shell 中编写一个脚本,其中一个命令正在运行并且需要 2 分钟。每次。此外,我们对此无能为力。但是如果我想在脚本中运行这个命令 100 次,那么总时间就是 200 分钟。这将产生一个大问题。没有人愿意等待 200 分钟。我想要的是并行运行所有 100 个命令,以便输出将在 2 分钟内完成,或者可能需要更多时间,但不要花费 200 分钟。

如果有人能以任何方式帮助我,我们将不胜感激。

【问题讨论】:

标签: shell unix


【解决方案1】:

GNU Parallel 是你想要的,除非你想重新发明轮子。这里有一些更详细的examples,但它的短:

ls | parallel gzip # gzip all files in a directory

【讨论】:

    【解决方案2】:

    ...并行运行所有 100 个命令,以便输出将在 2 分钟内出现

    这只有在您的系统上有 200 个处理器时才有可能。

    shell 脚本中没有这样的实用程序/命令来并行运行命令。你可以做的是在后台运行你的命令:

    for ((i=0;i<200;i++))
    do
       MyCommand &
    done
    

    使用&amp;(后台),每次执行都会尽快安排。但这并不能保证您的代码将在 200 分钟内执行完毕。这取决于您的系统上有多少个处理器。

    如果您只有一个处理器,并且每次执行命令(需要 2 分钟)都在 2 分钟内进行一些计算,那么处理器正在做一些工作,这意味着不会浪费任何周期。在这种情况下,并行运行命令并没有帮助,因为只有一个处理器也不是空闲的。因此,这些进程将只是等待轮到它们执行。

    如果您有多个处理器,那么上述方法(for 循环)可能有助于减少总执行时间。

    【讨论】:

    • 如果脚本是 IO 绑定的,则不需要 200 个处理器。事实上,只需 1 个处理器即可实现显着的加速。
    • @WilliamPursell 没错。但这真的取决于命令在 2 分钟 内做什么。
    【解决方案3】:

    正如@KingsIndian 所说,您可以在后台执行任务,这可以让它们并行运行。除此之外,您还可以通过进程 ID 跟踪它们:

    #!/bin/bash
    
    # Function to be backgrounded
    track() {
      sleep $1
      printf "\nFinished: %d\n" "$1"
    }
    
    start=$(date '+%s')
    
    rand3="$(jot -s\  -r 3 5 10)"
    
    # If you don't have `jot` (*BSD/OSX), substitute your own numbers here.
    #rand3="5 8 10"
    
    echo "Random numbers: $rand3"
    
    # Make an associative array in which you'll record pids.
    declare -A pids
    
    # Background an instance of the track() function for each number, record the pid.
    for n in $rand3; do
      track $n &
      pid=$!
      echo "Backgrounded: $n (pid=$pid)"
      pids[$pid]=$n
    done
    
    # Watch your stable of backgrounded processes.
    # If a pid goes away, remove it from the array.
    while [ -n "${pids[*]}" ]; do
      sleep 1
      for pid in "${!pids[@]}"; do
        if ! ps "$pid" >/dev/null; then
          unset pids[$pid]
          echo "unset: $pid"
        fi
      done
      if [ -z "${!pids[*]}" ]; then
        break
      fi
      printf "\rStill waiting for: %s ... " "${pids[*]}"
    done
    
    printf "\r%-25s \n" "Done."
    printf "Total runtime: %d seconds\n" "$((`date '+%s'` - $start))"
    

    您还应该查看coprocesses 上的 Bash 文档。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-02
      • 2023-03-23
      • 2016-01-04
      • 2011-12-23
      • 1970-01-01
      • 2019-11-21
      相关资源
      最近更新 更多