shell 重定向的一处妙用
偶然在 dracut 的代码中发现一个使用重定向很巧妙的地方。见 modules.d/90kernel-modules/module-setup.sh 文件。
之前的老代码是这样的:
[bash]
#
local _f
while read _f; do case "$_f" in
*.ko) [[ $(< $_f) =~ $_blockfuncs ]] && echo "$_f" ;;
*.ko.gz) [[ $(gzip -dc <$_f) =~ $_blockfuncs ]] && echo "$_f" ;;
esac
done
[/bash]
意思很清楚吧?就是在内核模块(注意是二进制格式)中匹配一些函数(字符串)。这样会很慢,因为 bash 要在庞大的二进制文件流中匹配一些指定字符串。
于是,就有人想了一个方法加速这个处理过程,把原来的单个数据流分成两个并行的数据流,同时进行匹配!很巧妙!
[bash]
#
function bmf1() {
local _f
while read _f; do case "$_f" in
*.ko) [[ $(< $_f) =~ $_blockfuncs ]] && echo "$_f" ;;
*.ko.gz) [[ $(gzip -dc &${side2}; fi
done
| bmf1 1>&${merge} ) {side2}>&1
| bmf1 ) {merge}>&1
[/bash]
经过 refactor 之后的或许更好理解一些:
[bash]
# subfunctions inherit following FDs
local _merge=8 _side2=9
function bmf1() {
local _f
while read _f; do case "$_f" in
*.ko) [[ $(< $_f) =~ $_blockfuncs ]] && echo "$_f" ;;
*.ko.gz) [[ $(gzip -dc &${_side2}
fi
done | bmf1 1>&${_merge}
}
# Use two parallel streams to filter alternating modules.
eval "( ( rotor ) ${_side2}>&1 | bmf1 ) ${_merge}>&1"
[/bash]