多线程BASH编程 - 通用方法?

NVR*_*RAM 3 bash shell multithreading mutex semaphore

好吧,我在所有演示中都运行了POV-Ray,但是POV仍然是单线程的,并且不会使用多个核心.所以,我开始考虑BASH的解决方案.

我写了一个通用函数,它接受一个命令列表并在指定数量的子shell中运行它们.这实际上有效,但我不喜欢它以线程安全的 多进程方式处理下一个命令的方式:

  • 作为参数,它需要一个带命令的文件(每行1个),
  • 要获得"下一个"命令,每个进程("线程")将:
    • 等到它可以创建一个锁文件,使用:ln $ CMDFILE $ LOCKFILE
    • 从文件中读取命令,
    • 删除第一行修改$ CMDFILE,
    • 删除$ LOCKFILE.

有更清洁的方法吗? 我无法让子shell正确读取FIFO中的单行.


顺便提一下,这一点是为了增强我在BASH命令行上可以做的事情,而不是找到非bash解决方案.我倾向于从命令行执行许多复杂的任务,并希望工具箱中有另一个工具.

同时,这是处理从文件中获取下一行的函数.如您所见,它每次读取/删除一行时都会修改磁盘文件.这似乎是hackish,但我没有想出更好的东西,因为FIFO没有用bash中的setvbuf()工作.

#
# Get/remove the first line from FILE, using LOCK as a semaphore (with
# short sleep for collisions).  Returns the text on standard output,
# returns zero on success, non-zero when file is empty.
#
parallel__nextLine() 
{
  local line rest file=$1 lock=$2

  # Wait for lock...
  until ln "${file}" "${lock}" 2>/dev/null
  do sleep 1
     [ -s "${file}" ] || return $?
  done

  # Open, read one "line" save "rest" back to the file:
  exec 3<"$file"
  read line <&3 ; rest=$(cat<&3)
  exec 3<&-

  # After last line, make sure file is empty:
  ( [ -z "$rest" ] || echo "$rest" ) > "${file}"

  # Remove lock and 'return' the line read:
  rm -f "${lock}"
  [ -n "$line" ] && echo "$line"
}
Run Code Online (Sandbox Code Playgroud)

pix*_*eat 7

#adjust these as required
args_per_proc=1 #1 is fine for long running tasks
procs_in_parallel=4

xargs -n$args_per_proc -P$procs_in_parallel povray < list
Run Code Online (Sandbox Code Playgroud)

请注意,nproc即将发布到coreutils 的命令将自动确定可以传递给-P的可用处理单元的数量