问题描述
在第一时间,我已经编写了代码,并且运行良好。
# version1
all_num=10
thread_num=5
a=$(date +%H%M%s)
seq 1 ${all_num} | xargs -n 1 -I {} -P ${thread_num} sh -c 'echo abc{}'
b=$(date +%H%M%s)
echo -e "startTime:\t$a"
echo -e "endTime:\t$b"
get_file(i){
echo "abc"+i
}
all_num=10
thread_num=5
a=$(date +%H%M%s)
seq 1 ${all_num} | xargs -n 1 -I {} -P ${thread_num} sh -c "$(get_file {})"
b=$(date +%H%M%s)
echo -e "startTime:\t$a"
echo -e "endTime:\t$b"
解决方法
因为不能保证/bin/sh
支持 打印在评估时定义您的函数的文本,或者通过环境导出函数,所以我们需要用困难的方式做到这一点,只是在xargs开始的sh
副本中复制函数的文本。
此站点中已经存在其他问题,描述了如何使用bash来完成此任务,这相当容易。见f / e How can I use xargs to run a function in a command substitution for each match?
#!/bin/sh
all_num=10
thread_num=5
batch_size=1 # but with a larger all_num,turn this up to start fewer copies of sh
a=$(date +%H%M%S) # warning: this is really inefficient
seq 1 ${all_num} | xargs -n "${batch_size}" -P "${thread_num}" sh -c '
get_file() { i=$1; echo "abc ${i}"; }
for arg do
get_file "$arg"
done
' _
b=$(date +%H%M%S)
printf 'startTime:\t%s\n' "$a"
printf 'endTime:\t%s\n' "$b"
注意:
-
echo -e
不保证可以与/bin/sh
一起使用。而且,要使外壳真正兼容,需要echo -e
将-e
写入其输出。请参阅Why isprintf
better thanecho
?上的UNIX & Linux Stack Exchange和the POSIXecho
specification的APPLICATION USAGE部分。 - 将
{}
放在sh -c '...{}...'
的位置确实是个坏主意。考虑传递给您的文件名包含$(rm -rf ~)'$(rm -rf ~)'
的情况-无法将其安全地插入未加引号的上下文或带双引号的上下文或单引号上下文,或者或 Heredoc。 - 请注意,
seq
也是非标准的,不能保证在所有符合POSIX的系统上都存在。i=0; while [ "$i" -lt "$all_num" ]; do echo "$i"; i=$((i + 1)); done
是可以在所有POSIX系统上使用的替代方法。