使用ldapsearch查询Active Directory时能否返回未设置的空用户属性
解决方案
ldapsearch本身没有提供强制输出空属性的原生参数,因为LDAP协议默认不会返回用户未赋值的属性,你可以通过后处理ldapsearch输出的方式实现需求,以下是两种常用实现方案:
方案1:生成带空字段的类LDIF格式(匹配你期望的输出格式)
提前定义你需要查询的所有属性列表,通过awk处理ldapsearch的输出,对每个用户条目初始化所有属性为空值,再填充实际返回的属性值。
示例命令如下:
# 按你的需求修改属性列表、AD地址、绑定账号、搜索基DN等参数 TARGET_ATTRS="sn givenName othertelephone memberOf" AD_URL="ldap://你的AD服务器地址" BIND_DN="你的绑定账号DN(例如admin@example.com)" BIND_PWD="你的绑定密码" SEARCH_BASE="搜索基DN(例如OU=用户,DC=example,DC=com)" ldapsearch -x -LLL -H "$AD_URL" -D "$BIND_DN" -w "$BIND_PWD" -b "$SEARCH_BASE" "(objectClass=user)" $TARGET_ATTRS | awk -v attrs="$TARGET_ATTRS" ' BEGIN { split(attrs, attr_arr, " ") attr_num = length(attr_arr) } # 遇到新用户条目 /^dn: / { if (init_flag) { # 输出上一个用户的所有属性 for (i=1; i<=attr_num; i++) { print attr_arr[i] ": " entry[attr_arr[i]] } print "" delete entry } init_flag = 1 next } # 处理长属性值换行的场景(ldapsearch返回长值时会在新行开头加空格) /^ / { last_key = substr($0, 1, index($0, ":")-1) entry[last_key] = entry[last_key] substr($0, index($0, ":")+2) next } # 处理普通属性行 { if (index($0, ":") > 0) { key = substr($0, 1, index($0, ":")-1) val = substr($0, index($0, ":")+2) entry[key] = val } } END { # 输出最后一个用户的属性 if (init_flag) { for (i=1; i<=attr_num; i++) { print attr_arr[i] ": " entry[attr_arr[i]] } } }'
方案2:直接生成标准CSV文件(省略中间格式转换步骤)
如果你的最终目的是生成CSV,可以直接调整awk的输出逻辑,一步完成属性补全和CSV格式化,自动处理属性值中的逗号、双引号等特殊字符:
TARGET_ATTRS="sn givenName othertelephone memberOf" AD_URL="ldap://你的AD服务器地址" BIND_DN="你的绑定账号DN(例如admin@example.com)" BIND_PWD="你的绑定密码" SEARCH_BASE="搜索基DN(例如OU=用户,DC=example,DC=com)" OUTPUT_CSV="ad_users.csv" ldapsearch -x -LLL -H "$AD_URL" -D "$BIND_DN" -w "$BIND_PWD" -b "$SEARCH_BASE" "(objectClass=user)" $TARGET_ATTRS | awk -v attrs="$TARGET_ATTRS" ' BEGIN { split(attrs, attr_arr, " ") attr_num = length(attr_arr) # 输出CSV表头 for (i=1; i<=attr_num; i++) { printf "\"%s\"", attr_arr[i] if (i < attr_num) printf "," } print "" } /^dn: / { if (init_flag) { # 输出上一个用户的CSV行 for (i=1; i<=attr_num; i++) { gsub(/"/, "\"\"", entry[attr_arr[i]]) # 转义值中的双引号 printf "\"%s\"", entry[attr_arr[i]] if (i < attr_num) printf "," } print "" delete entry } init_flag = 1 next } /^ / { last_key = substr($0, 1, index($0, ":")-1) entry[last_key] = entry[last_key] substr($0, index($0, ":")+2) next } { if (index($0, ":") > 0) { key = substr($0, 1, index($0, ":")-1) val = substr($0, index($0, ":")+2) entry[key] = val } } END { # 输出最后一个用户的CSV行 if (init_flag) { for (i=1; i<=attr_num; i++) { gsub(/"/, "\"\"", entry[attr_arr[i]]) printf "\"%s\"", entry[attr_arr[i]] if (i < attr_num) printf "," } print "" } }' > "$OUTPUT_CSV"
其他可选方案
如果不想自己写处理脚本,也可以使用Python的python-ldap库实现同样的逻辑:提前定义目标属性列表,遍历每个查询结果时按列表取值,不存在则填空字符串即可,适合需要更复杂处理逻辑的场景。
内容的提问来源于stack exchange,提问作者StartedFromTheBottom
相关产品推荐
相关产品推荐

