ldapsearch批量查询时如何实现按用户分组格式化输出?
问题根源
之前的处理管道没有做用户维度的上下文绑定:从LDAP返回流中提取出userid、各邮箱字段的孤立值后,没有将同一用户的属性做归组关联,所以无论怎么对全局提取的字符串做拼接,都会把所有用户的字段值混在一起,无法实现按用户拆分输出的目标。
LDAP返回结果天然具备适合归组的结构:每个匹配到的用户的所有属性行是连续聚集的,不同用户的结果块之间用空行分隔,这个特性是实现正确格式化的核心依据。
适配批量场景的格式化方案
方案1:单用户单行,逗号拼接所有关联邮箱
该方案输出符合第一种预期格式,可直接复用如下命令:
ldapsearch -Y GSSAPI -b dc=level1,dc=level2,dc=level3 '(userid=*)' userid mail1 mail2 mail3 \ | awk ' BEGIN { RS=""; FS="\n" } { userid=""; mails="" for (i=1; i<=NF; i++) { # 去掉行首可能存在的多余空格 gsub(/^[ ]+/, "", $i) # 提取当前块内的userid值 if ($i ~ /^userid: /) { split($i, u, ": ") userid = u[2] } # 收集当前块内所有邮箱字段值 if ($i ~ /^mail[0-9]*: /) { split($i, m, ": ") mails = mails "," m[2] } } # 输出单用户的完整行,去掉拼接时多生成的首个逗号 if (userid != "") print userid substr(mails, 2) } '
处理逻辑说明:
- 通过awk设置记录分隔符为空行,直接将每个用户的独立结果块作为处理单元,从根源上避免跨用户的内容混淆
- 自动适配每个用户的邮箱数量差异,不管用户绑定1个还是N个邮箱,都会自动收集后拼接为单行内容
方案2:单用户-单邮箱映射,每行独立配对
该方案是更优的输出格式,对应第二种预期效果,命令如下:
ldapsearch -Y GSSAPI -b dc=level1,dc=level2,dc=level3 '(userid=*)' userid mail1 mail2 mail3 \ | awk ' BEGIN { RS=""; FS="\n" } { userid=""; mail_list="" for (i=1; i<=NF; i++) { gsub(/^[ ]+/, "", $i) if ($i ~ /^userid: /) { split($i, u, ": ") userid = u[2] } if ($i ~ /^mail[0-9]*: /) { split($i, m, ": ") # 收集当前用户的所有邮箱到临时列表 mail_list = mail_list " " m[2] } } # 逐行输出用户-邮箱配对 if (userid != "") { n = split(mail_list, mail_arr, " ") for (j=1; j<=n; j++) { if (mail_arr[j] != "") print userid "," mail_arr[j] } } } '
注:如果你的环境中邮箱对应的属性名是查询参数里提到的
email1/email2/email3而非返回示例的mail1/mail2/mail3,只需要把awk脚本中的匹配规则从/^mail[0-9]*: /改成/^email[0-9]*: /即可,其余逻辑无需调整。
批量场景优化提示
如果需要查询数十万规模的用户,不要通过循环逐个用户调用ldapsearch——单次调用的GSSAPI认证、LDAP服务器连接的开销很高,循环执行会导致耗时极长。直接将查询过滤条件设置为(userid=*),一次性拉取所有目标用户的属性后在本地做格式化,整体运行效率会提升几个数量级。
内容的提问来源于stack exchange,提问作者formicaman
相关产品推荐
相关产品推荐

