I am trying to write a pretty printer for LDAP entries which only fetches the root LDAP record once and then pipes the output into tee
that invokes the pretty printer for each section.
For illustration's sake, say my group_entry
function returns the LDIF of a specific LDAP DN. The details of which aren't important, so let's say it always returns:
dn: cn=foo,dc=example,dc=com
cn: foo
owner: uid=foo,dc=example,dc=com
owner: uid=bar,dc=example,dc=com
member: uid=foo,dc=example,dc=com
member: uid=baz,dc=example,dc=com
member: uid=quux,dc=example,dc=com
custom: abc123
I can easily extract the owners and members separately with a bit of grep
'ing and cut
'ing. I can then pipe those secondary DNs into another LDAP search query to get their real names. For sake of example, let's say I have a pretty_print
function, that is parametrised on the LDAP attribute name, which does all that I just mentioned and then formats everything nicely with AWK:
$ group_entry | pretty_print owner
Owners:
foo Mr Foo
bar Dr Bar
$ group_entry | pretty_print member
Members:
foo Mr Foo
baz Bazzy McBazFace
quux The Artist Formerly Known as Quux
These work fine individually, but when I try to tee
them together, nothing happens:
$ group_entry | tee >(pretty_print owner) | pretty_print member
Members:
[Sits there waiting for Ctrl+C]
Obviously I have some misunderstanding about how this is supposed to work, but it escapes me. What am I doing wrong?
EDIT For sake of completeness, here's my full script:
#!/usr/bin/env bash
set -eu -o pipefail
LDAPSEARCH="ldapsearch -xLLL"
group_entry() {
local group="$1"
${LDAPSEARCH} "(&(objectClass=posixGroup)(cn=${group}))"
}
get_attribute() {
local attr="$1"
grep "${attr}:" | cut -d" " -f2
}
get_names() {
# We strip blank lines out of the LDIF entry, then we always have "dn"
# followed by "cn" records; we strip off the attribute name and
# concatenate those lines, then sort. So we get a sorted list of:
# {{distinguished_name}} {{real_name}}
xargs -n1 -J% ${LDAPSEARCH} -s base -b % cn \
| grep -v "^$" \
| cut -d" " -f2- \
| paste - - \
| sort
}
pretty_print() {
local attr="$1"
local -A pretty=([member]="Members" [owner]="Owners")
get_attribute "${attr}" \
| get_names \
| gawk -F'\t' -v title="${pretty[${attr}]}:" '
BEGIN { print title }
{ print "-", gensub(/^uid=([^,]+),.*$/, "\\1", "g", $1), "\t", $2 }
'
}
# FIXME I don't know why tee with process substitution doesn't work here
group_entry "$1" | pretty_print owner
group_entry "$1" | pretty_print member