我有一个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
。测试是在Ubuntu 16.04上使用Bash 4.3进行的,在Mac OS X上使用Bash 4.4进行。
后者在test.bash
中似乎发生的事情是getopts
拒绝处理-c
,因此prunner
将尝试直接执行参数而不是-t
它给出了前缀命令。奇怪的是,我能够观察它接受getopts
选项,因此set -x
至少部分有效。使用echo
进行Bash调试无法解释为什么会发生这种情况。
以下是相关功能,经过轻微修改后使用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
选项在使用管道输送到标准输入时[
{
id: 10
name : abc
},
{
id: 11
name : xyz
}
]
无法正常工作?
答案 0 :(得分:4)
My guess is that you are executing the two commands in the same shell. In that case, in the second invocation, OPTIND
will have the value 3 (which is where it got to on the first invocation) and that is where getopts
will start scanning.
If you use getopts
to parse arguments to a function (as opposed to a script), declare local OPTIND=1
to avoid invocations from interfering with each other.
答案 1 :(得分:0)
Perhaps you are already doing this, but make sure to pass the top-level shell parameters to your function. The function will receive the parameters via the call, for example:
xyz () {
echo "First arg: ${1}"
echo "Second arg: ${2}"
}
xyz "This is" "very simple"
In your example, you should always be calling the function with the standard args so that they can be processed in the method via getopts.
prunner "$@"
Note that pruner will not modify the standard args outside of the function.