Как мне отформатировать, перечислить и выполнить каждую строку из результата запроса LDAP?

Итак, я ПРОСТО начал использовать 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

Запрошено редактировать...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 ответ

Решение

Было бы полезно, если бы вы включили (2) в мой первый комментарий, особенно printf версия:

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

Тот printf заявление поставит <||> вокруг каждого аргумента, что позволяет увидеть разницу между:

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

а также

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

Но я рискну догадаться, что вы действительно хотите:

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

Цитирование сценариев оболочки занимает немного времени, чтобы разобраться. Такие инструменты, как этот оператор printf, помогут. Поэкспериментируйте немного с простыми командами. Обратите внимание на то, как раскрываются переменные. (И обратите внимание, что кавычки в значениях переменных - это просто обычные символы.) Также убедитесь, что вы понимаете разницу между zmprov $line а также zmprov "$line",

Наконец, прочтите bash FAQ по цитированию: http://mywiki.wooledge.org/BashFAQ/050

Также, sed может выполнить более одной команды за один вызов, и awk может сделать большинство вещей sed сможет сделать. Я подозреваю, что вы могли бы упростить эту массивную линию в простой awk программа.

Другие вопросы по тегам