【问题标题】:How do I format, enumerate, and execute each line from LDAP query result?如何格式化、枚举和执行 LDAP 查询结果中的每一行?
【发布时间】:2013-10-02 16:52:35
【问题描述】:

好的,所以我只是在两周前开始编写 bash 脚本,上周我遇到了一个无法解决的问题。我会尽我所能描述我的问题,并且我已经包含了我的脚本。我欢迎对我在这段代码中做错的任何批评;实际上,我恳请您尽可能多地批评我的技术,以便我从中学习。


目标

我为我的公司安装了一个新的 Zimbra Collaboration Suite,并且正在迁移用户帐户。我正在尝试创建一个 bash 脚本来执行以下操作:

  1. 通过 LDAP 从活动目录中提取所有用户帐户。
  2. 格式化 LDAP 查询结果以在 zmprov ca 命令中使用。
  3. 枚举格式化结果的行数。
  4. 遍历每一行并将其作为zmprov 命令运行。

本示例的假设

  • bash 文件的名称 = zdap
  • 我的 Active Directory 域 = MYLOCALDOMAIN
  • 我的 LDAP 用户名 = admin
  • 我的 LDAP 密码 = P@ssw0rd
  • 我的 LDAP IP 地址 = 1.2.3.4

脚本

这是我的脚本:

#!/bin/bash

#Use this script to pull user information from Company Active Directory

argerror="Usage: company-ldap domain username"

if [ "$1" == "local" ]; then
    domain=MYLOCALDOMAIN
    ou=MAIN
else
    echo "$argerror"
    exit
fi

if [ -z $2 ]; then 
    echo "$argerror"
    exit
else
    user=$2
fi

password=P@ssw0rd

ldapsearch -h 1.2.3.4 -p 389 -D "cn=$user,ou=$ou,dc=$domain,dc=COM" \
           -w "$password" -b "ou=$ou,dc=$domain,dc=COM" \
           "(&(name=*)(mail=*)(givenName=*)(sn=*))" \
           'name' 'mail' 'givenName' 'sn' -LLL -S 'name' |
grep -B 1 'name\|mail\|sn\|givenName' |
grep -v '^dn:' | tr '\n' ' ' |
sed -e 's/ -- /\n/g' |
awk '{s=""; for (i=1;i<NF;i++) s = s $i " ";print $NF " " s}' |
sed -e 's/sn: /sn '\''/g' |
sed -e 's/ givenName: /'\'' gn '\''/g' |
sed -e 's/ mail: / /g' |
sed -e 's/ name: /'\'' displayName '\''/g' |
awk '{print "ca " $0"'\''"}' |
sed -e 's/ '\''$/'\''/g' |
awk '{($2 = $2 " tempzimbrapw1234"); print $0}' |
while read line ; do zmprov $line ; done

我用这个来调用命令:

./zdap local admin

请求编辑... 给定用户 (Joe Smith) 的 zmprov 命令如下所示:

zmprov ca joe.smith@mylocaldomain.com tempzimbrapw1234 sn 'Smith' gn 'Joe' displayName 'Joe Smith'

结果和我的问题

  • ldap 查询运行完美(例如,如果我单独运行该命令,它将返回正确的 ldap 结果...所以问题与 LDAP 凭据/连接/查询无关)。
  • 如果我回显该命令,它看起来也很好(例如,如果我键入 命令输出以匹配回显的版本,它实际上会添加 我想要的帐户)。

但是,当我运行我编写的 zdap bash 脚本时,我希望从 Zimbra 获得创建帐户的确认,但却收到以下消息:

zimbra@CPU-00154:~$ ./zdap local admin
usage: createAccount(ca) {name@domain} {password} [attr1 value1 [attr2 value2..
For general help, type : zmprov --help

不幸的是,我尝试了太多解决方案,无法在此处全部列出。我花了一周时间阅读手册、论坛等,并尝试了大量的调整、调整、新命令等,但无济于事。

再一次,如果对我的脚本或完成此任务的整体方法提出任何批评,我将不胜感激。请尝试在您的建议中包含示例,以便我可以在这里看到我做错了什么。提前谢谢你。

编辑:

我想我应该包含 LDAP 查询结果的格式,这样你就可以看到我的命令正在处理什么:

dn: CN=admin,OU=MAIN,DC=MYLOCALDOMAIN,DC=COM
name: admin
mail: admin@mylocaldomain.com
--    
dn: CN=Jane Doe,OU=MAIN,DC=MYLOCALDOMAIN,DC=COM    
name: Jane Doe
mail: jane.doe@mylocaldomain.com
--    
dn: CN=Joe Smith,OU=MAIN,DC=MYLOCALDOMAIN,DC=COM    
name: Joe Smith
mail: joe.smith@mylocaldomain.com

更新

我设法使用printf 命令解决了这个问题(特别感谢 rici 的建议)。 printf 的输出是这样的......

<|zmprov|> <|ca|> <|joe.smith@mylocaldomain.com|> <|tempzimbrapw1234|> <|#|> <|sn|> <|'Smith'|> <|gn|> <|'Joe'|> <|displayName|> <|'Joe|> <|Smith'|>

如您所见,最后一个参数 (displayName) 的值被误解了。

【问题讨论】:

  • 如果您还添加了 (1) 您期望 zmprov 命令行的外观,以及 (2) 它的实际外观,将会有所帮助。要获得 (2),请在该行中将 echo 放在 zmprov 之前。或者,更好的是,使用printf '&lt;|%s|&gt; ' zmprov $line &amp;&amp; printf '\n'
  • @rici 很好的评论,我现在就补充。

标签: linux bash sed grep zimbra


【解决方案1】:

如果您在我的第一条评论中包含 (2) 仍然会有所帮助,尤其是 printf 版本:

printf '<|%s|> ' $line && printf '\n'

printf 语句会将&lt;| |&gt; 放在每个参数周围,这样可以看到以下之间的区别:

<|zmprov|> <|ca|> ... <|displayName|> <|'Joe Smith'|>

<|zmprov|> <|ca|> ... <|displayName|> <|'Joe|> <|Smith'|>

但我冒昧地猜测你真正想要的是:

<|zmprov|> <|ca|> ... <|displayName|> <|Joe Smith|>

Shell 脚本引用需要一些时间来理解。像 printf 语句这样的工具会有所帮助。用简单的命令做一些实验。注意变量是如何扩展的。 (请注意,变量的中的引号只是普通字符。)还要确保您了解zmprov $linezmprov "$line"之间的区别。

最后,阅读关于引用的 bash 常见问题解答:http://mywiki.wooledge.org/BashFAQ/050

另外,sed 可以在一次调用中执行多个命令,awk 可以完成大部分 sed 可以做的事情。我怀疑您可以将那条庞大的行简化为一个简单的awk 程序。

【讨论】:

  • 您能否详细说明“...确保您了解zmprov $linezmprov "$line" 之间的区别?
  • @Lopsided:两个都试试。使用神奇的printf 命令。特别是,尝试使用 $line 的值,其中包含空格,例如 line="This value is five words"
  • 感谢您抽出宝贵时间回答这个问题。我会将此标记为正确,因为它肯定会帮助我解决此问题。再次感谢。
猜你喜欢
  • 2023-02-07
  • 1970-01-01
  • 2013-06-10
  • 1970-01-01
  • 2021-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多