Как отформатировать, перечислить и выполнить каждую строку из результата запроса 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
  • Мой IP-адрес LDAP = 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 [email protected] 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: [email protected]
--    
dn: CN=Jane Doe,OU=MAIN,DC=MYLOCALDOMAIN,DC=COM    
name: Jane Doe
mail: [email protected]
--    
dn: CN=Joe Smith,OU=MAIN,DC=MYLOCALDOMAIN,DC=COM    
name: Joe Smith
mail: [email protected]

ОБНОВИТЬ

Мне удалось решить проблему с помощью команды printf (особая благодарность rici за это предложение). Вывод из printf был таким...

<|zmprov|> <|ca|> <|[email protected]|> <|tempzimbrapw1234|> <|#|> <|sn|> <|'Smith'|> <|gn|> <|'Joe'|> <|displayName|> <|'Joe|> <|Smith'|>

Как видите, значение последнего аргумента (displayName) интерпретировалось неправильно.


person Lopsided    schedule 02.10.2013    source источник
comment
Было бы полезно, если бы вы также добавили (1) ожидаемый вид командной строки zmprov и (2) как она выглядит на самом деле. Чтобы получить (2), поставьте echo перед zmprov в этой строке. Или, что еще лучше, используйте printf '<|%s|> ' zmprov $line && printf '\n'   -  person rici    schedule 02.10.2013
comment
@rici Отличный комментарий, сейчас добавлю.   -  person Lopsided    schedule 02.10.2013


Ответы (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".

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

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

person rici    schedule 02.10.2013
comment
Не могли бы вы уточнить... убедиться, что вы понимаете разницу между zmprov $line и zmprov "$line"? - person Lopsided; 02.10.2013
comment
@Lopsided: Попробуйте оба. Используйте волшебную команду printf. В частности, попробуйте их со значениями $line, в которых есть пробелы, например line="This value is five words". - person rici; 03.10.2013
comment
Спасибо, что нашли время ответить на этот вопрос. Я отмечу это правильно, потому что это, безусловно, поможет мне решить эту проблему. Спасибо еще раз. - person Lopsided; 03.10.2013