【发布时间】:2018-03-22 23:20:05
【问题描述】:
我有一个 Bash 函数 library,其中一个函数在测试中被证明是有问题的。 prunner 是一个函数,旨在提供 GNU Parallel 的一些功能,并避免尝试在 Perl 中使用其他 Bash 函数的范围问题。它支持使用-c 设置针对参数列表运行的命令,以及使用-t 设置同时运行的后台作业数。
在测试中,我最终得到了以下场景:
-
prunner -c "gzip -fk" *.out- 在test.bash中按预期工作并以交互方式工作。 -
find . -maxdepth 1 -name "*.out" | prunner -c echo -t 6- 不起作用,貌似忽略了-c echo。
在带有 Bash 4.3 的 Ubuntu 16.04 和带有 Bash 4.4 的 Mac OS X 上进行了测试。
在test.bash 中,后者似乎发生的事情是getopts 拒绝处理-c,因此prunner 将尝试在没有给出前缀命令的情况下直接执行参数。奇怪的是我能够观察到它接受-t 选项,所以getopts 至少部分工作。使用 set -x 进行 Bash 调试无法解释为什么会发生这种情况。
这是有问题的函数,稍作修改以使用 echo 而不是 log 和 quit,以便可以与我的库的其余部分分开使用:
prunner () {
local PQUEUE=()
while getopts ":c:t:" OPT ; do
case ${OPT} in
c) local PCMD="${OPTARG}" ;;
t) local THREADS="${OPTARG}" ;;
:) echo "ERROR: Option '-${OPTARG}' requires an argument." ;;
*) echo "ERROR: Option '-${OPTARG}' is not defined." ;;
esac
done
shift $(($OPTIND-1))
for ARG in "$@" ; do
PQUEUE+=("$ARG")
done
if [ ! -t 0 ] ; then
while read -r LINE ; do
PQUEUE+=("$LINE")
done
fi
local QCOUNT="${#PQUEUE[@]}"
local INDEX=0
echo "Starting parallel execution of $QCOUNT jobs with ${THREADS:-8} threads using command prefix '$PCMD'."
until [ ${#PQUEUE[@]} == 0 ] ; do
if [ "$(jobs -rp | wc -l)" -lt "${THREADS:-8}" ] ; then
echo "Starting command in parallel ($(($INDEX+1))/$QCOUNT): ${PCMD} ${PQUEUE[$INDEX]}"
eval "${PCMD} ${PQUEUE[$INDEX]}" || true &
unset PQUEUE[$INDEX]
((INDEX++)) || true
fi
done
wait
echo "Parallel execution finished for $QCOUNT jobs."
}
谁能帮我确定为什么-c 选项在通过管道传输到标准输入时无法正常工作prunner?
【问题讨论】:
-
printf替换echo的行为如何? -
感谢您将
log替换为echo以使您的功能更加独立。进一步考虑这个想法并删除重现问题不需要的所有其他内容怎么样? (这是MCVE中的M) -
小提示:变量名不要全部大写。将名称全部大写的变量视为保留供系统使用,因为这是一般约定。如果您虔诚地将变量声明为本地变量,则差异较小,但最好的做法仍然是避免在所有大写字母中使用名称(当然,引用系统环境变量时除外)。
-
您能否详细说明为什么不使用
parallel --embed将 GNU Parallel 作为函数嵌入到您的 shell 脚本中?