MacOS 10.15下为gupdatedb集成parallel实现多线程建库
解决MacOS 10.15下用parallel加速gupdatedb的可行方案
我明白你想给gupdatedb加多线程加速的需求,之前踩的那些坑(直接替换find变量报错、脚本挂起、parallel的citation提示、路径重复)我都碰到过,下面给你一套能跑通的方案,目标是用8线程的gfind来构建定位数据库:
1. 先准备环境
确保你已经通过brew装好了需要的工具:
brew install findutils parallel
2. 备份原gupdatedb脚本
先找到findutils的安装目录,然后备份脚本防止改坏:
FINDUTILS_PREFIX=$(brew --prefix findutils) cp $FINDUTILS_PREFIX/libexec/gupdatedb $FINDUTILS_PREFIX/libexec/gupdatedb.bak
3. 修改gupdatedb脚本核心逻辑
编辑脚本:
nano $FINDUTILS_PREFIX/libexec/gupdatedb
3.1 跳过parallel的citation提示
在脚本开头(比如#!/bin/sh下面)添加一行,避免每次运行都要确认citation:
export PARALLEL_CITATION=1
3.2 设置线程数
在脚本里找个合适的位置(比如BINDIR定义之后)添加线程数变量:
# 设置要使用的线程数,这里设为8 NUM_THREADS=8
3.3 替换原find调用逻辑
找到脚本里调用$find来扫描路径的核心行,一般是类似这样的:
"$find" "${SEARCHPATHS[@]}" $FINDOPTIONS -fprint "$TMPFILE"
把这整行替换成下面的代码:
# 用parallel分块调用gfind,多线程扫描路径 printf "%s\n" "${SEARCHPATHS[@]}" | parallel -j$NUM_THREADS --lb "$BINDIR/gfind" {} $FINDOPTIONS -fprint0 | xargs -0 >> "$TMPFILE"
这段代码的作用:
printf "%s\n" "${SEARCHPATHS[@]}":把要扫描的路径列表转成每行一个,方便parallel处理parallel -j$NUM_THREADS --lb:启动8个线程,--lb保证输出有序(可选,数据库构建不要求顺序的话可以去掉)"$BINDIR/gfind" {} $FINDOPTIONS -fprint0:每个线程调用gfind处理一个路径,用-fprint0输出null分隔的结果,避免空格路径出错xargs -0 >> "$TMPFILE":把所有线程的输出合并到临时文件里,和原逻辑的结果一致
3.4 解决路径重复问题
MacOS 10.15里/和/System/Volume/Data是同一个挂载点(APFS的特性),会导致重复扫描。我们可以在脚本里排除其中一个路径:
找到定义SEARCHPATHS的地方,添加一行过滤代码:
# 移除重复的/System/Volume/Data路径 SEARCHPATHS=(${SEARCHPATHS[@]//\/System\/Volume\/Data/})
或者,如果找不到SEARCHPATHS的定义,也可以在FINDOPTIONS里添加排除规则:
# 在FINDOPTIONS里添加排除/System/Volume/Data的规则 FINDOPTIONS="$FINDOPTIONS -path '/System/Volume/Data' -prune -o"
4. 测试修改后的脚本
运行gupdatedb测试:
gupdatedb
如果一切正常,你会看到多个gfind进程在活动(可以用top或者ps aux | grep gfind查看),数据库构建速度会比单线程快很多。
为什么之前的方法不行?
- 直接替换
find变量为parallel ... gfind:脚本里的checkbinary函数会把整个字符串当成一个命令去检查,它以为-j32是可执行文件,所以报错 - 变量传递的写法错误:
{}和:::是parallel的语法,不能直接塞到find变量里,脚本调用时会把这些当成无效参数,导致挂起 - 子目录数少于线程数的问题:parallel会自动适配,有多少路径就启动多少线程,不会浪费资源,不用额外处理
内容的提问来源于stack exchange,提问作者user1773603
相关产品推荐
相关产品推荐

