如何从LDAP查询结果中格式化,枚举和执行每一行?

时间:2013-10-02 16:52:35

标签: linux bash sed grep zimbra

好的,所以我 JUST 两周前开始使用bash脚本,上周我遇到了一个我无法解决的问题。我将尽我所能描述我的问题并且我已经包含了我的脚本。我欢迎任何批评我对此代码的错误;实际上,我恳请你尽可能多地批评我的技术,以便我可以从中学习。


目标

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

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

  5. 用于此示例的假设

    • 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 个答案:

答案 0 :(得分:1)

如果您从我的第一条评论中包含(2),特别是printf版本,那么它仍然会有所帮助:

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

printf语句会在每个参数周围放置<| |>,这样就可以看出它们之间的区别:

<|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程序。