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]