Associative array index question


 
Thread Tools Search this Thread
Top Forums Shell Programming and Scripting Associative array index question
# 8  
Old 09-28-2017
Quote:
Originally Posted by Riker1204
Eval occured to me because when I trace the output ( bash -x ) I get results like this: DN_COUNT[$NAME]=98 or DN_COUNT[$NAME]=1007 and so on. So of course eval then gives me the desired result. I'm not saying your wrong, but I just don't see how the mangling is occuring.
If your code's as you post it, it has to have occurred somewhere, but if it's not, other problems are possible.

Could you have done '$NAME' instead of "$NAME" ? That definitely will not work, and eval definitely would have "fixed" it. Using double quotes is the better answer of course.
Quote:
Also I did write the whole thing from scratch
What is the -d '\0' for?

Quote:
I tend to use the named pipes to feed with the null delimiter because I know C strings are terminated that way which allows for crazy characters
That's a no-op unless your input actually has nulls, and yours doesn't.
Quote:
and the named pipe always avoids subshells which tend to trip me up.
That's a consideration when using read to dump large lists of things into arrays and variables. But you may not need an array at all.

Code:
    make_dir () {
        for i in "/var/lib/ldap" "/var/lib/ldap/accesslog" "/var/tmp/bdb-log" "/etc/openldap/slapd.d" ; do
            if [ -d "$i" ] ; then
                :
            else
                mkdir "$i"
            fi
        done

        if [ $? -eq 0 ] ; then
            printf "%b\n" "Checking directories:                         [ \e[92mOK\e[0m ]"
        else
            printf "%b\n" "Missing directories, unable to create them:   [ \e[91mFAILED\e[0m ]"
        fi
        cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
    }

That if [ $? ] doesn't do what you think it does. It's only checking the very last loop, not any of the ones before. You can replace the whole thing with one mkdir call, anyway:

mkdir has -p which will replace most of your function:

Code:
    make_dir () {
        if ! mkdir -p "/var/lib/ldap" "/var/lib/ldap/accesslog" "/var/tmp/bdb-log" "/etc/openldap/slapd.d"
        then
            printf "%b\n" "Missing directories, unable to create them:   [ \e[91mFAILED\e[0m ]"
            return
        fi

        printf "%b\n" "Checking directories:                         [ \e[92mOK\e[0m ]"

        cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
    }

Code:
    set_permissions () {
        for i in "/var/lib/ldap" "/var/tmp/bdb-log" "/etc/openldap/slapd.d" ; do
            chown -R ldap:ldap "$i"
        done

        if [ $? -eq 0 ] ; then
            printf "%b\n" "Setting permissions:                          [ \e[92mOK\e[0m ]"
            return 0
        else
            printf "%b\n" "Unable to set permissions:                    [ \e[91mFAILED\e[0m ]"
            return 1
        fi
    }

Same problem here, your $? doesn't do what you think it does, you could have used if directly, and chown can accept multiple names anyway.

If your ldap permissions are changing all the time, it might be a good idea to find what's doing so...

Code:
    set_permissions () {
        if chown -R ldap:ldap "/var/lib/ldap" "/var/tmp/bdb-log" "/etc/openldap/slapd.d"
        then
            printf "%b\n" "Setting permissions:                          [ \e[92mOK\e[0m ]"
            return 0
        else
            printf "%b\n" "Unable to set permissions:                    [ \e[91mFAILED\e[0m ]"
            return 1
        fi
    }

Never, ever use kill -9 as anything but a last resort. You have to ask it to stop, wait, kill it politely, wait, kill it less politely, wait, and if it doesn't die, THEN you can murder it:

Code:
    stop_ldap () {
        pid_number=$(pgrep slapd)
        systemctl stop slapd
        sleep 2
        for SIG in TERM INT HUP KILL # Increasingly severe signals to kill it with
        do
                pgrep slapd >/dev/null || break
                kill -$SIG "$pid_number"
                sleep 1
        done
    }

I'll have to think about the rest.
# 9  
Old 09-28-2017
The permissions only get stomped on when running slaptest and slapcat because they are run as root. (During a recovery which hopefully is never again)

Also I will definitely be making the changes you suggested when I have time to work on it again.

Our servers lost access to their SAN (collective array of drives) due to a mistakenly pulled cable and something else and LDAP understandably doesn't like having its filesystem ripped out from under it.

It took us about an hour to get it back online last time simply because nobody could remember the commands to run. I've tested this script every which way I know how and it works every time in a matter of seconds, so we have it on the machine just in case disaster strikes again. ( and a remote backup too)

Thanks for the help. It is really appreciated. Seriously you have no idea. Also, one last bug in the script which I can't figure out.

When the script examines the backup files from our remote directory it doesn't display the top 5 files by DN count. Local files work fine. Overall it still works fine also, but its a bit bizarre, the trace doesn't give me any clue. No big deal as I have to move on to the next project. Just bugs me, pun intended!

Also one last comment, when I need to extract word by word from large multi-line files the "read -d "\0" -a array < <(some-input-here) always just "works" when other read commands fail, so I should be avoiding this? I think I need to revisit the read command entirely.

Last edited by Riker1204; 09-28-2017 at 06:38 PM..
# 10  
Old 09-28-2017
Code:
    case $1 in
    repair)    repair=true
               ;;
    testdb)    testdb=true
               ;;
    restore)   restore=true
               ;;
    rebuild)   rebuild=true
               ;;
    *)         printf "%s\n\n" "Usage ldap.sh <repair|restore|rebuild|test>"
               printf "%s\n"   "repair     ---> try to repair existing db via db_recover"
               printf "%s\n"   "restore    ---> try to restore from latest backup via slapadd"
               printf "%s\n"   "rebuild    ---> rebuild everything and restore latest backup"
               printf "%s\n\n" "testdb     ---> test service health; return a search"
               exit 1
               ;;
    esac

Why not cut out the middleman and just call ldap_repair, ldap_testdb, etc functions instead of setting variables?

Code:
rm -rf /var/lib/ldap/*
        rm -rf /etc/openldap/slapd.d/*
        rm -rf /var/tmp/bdb-log/*

You can put this in one call:

Code:
rm -rf /var/lib/ldap/* /etc/openldap/slapd.d/* /var/tmp/bdb-log/*

And once again, you really shouldn't be shoving the output of ls -l into variables. For one thing its redundant, and for another, did you know that if you turn off the -l, you won't need awk '{ print $9 }' ? For a third thing, the print $9 trick breaks down when filenames have spaces in them, which is a problem you seem to want to avoid.
# 11  
Old 09-28-2017
Quote:
Originally Posted by Riker1204
When the script examines the backup files from our remote directory it doesn't display the top 5 files by DN count. It still works fine, but its a bit bizarre, the trace doesn't give me any clue. No big deal as I have to move on to the next project. Just bugs me, pun intended!
If you're using the code I showed you, with grep -hc, it doesn't sort the output, but that's an easy fix:

Code:
grep -Hc "dn: " /localbackup/ldap/* | sort -t: -rn -k 2,2 | head -n 5

-rn for 'reverse' and 'numeric', -t: for delimiter :, -k 2,2 to sort on the second column alone.

Most of the rest of your code I will need context to understand at all.
# 12  
Old 09-28-2017
Yes I'm going to incorporate these changes when I get some time. We have old infrastructure and I'm under a bit of a time crunch as we have other systems that tend to halt because of various hardware related issues (Sudden losses of power, failing drives, etc....). I've tested all logical cases I can think of and it works everytime so I have to move on unfortunately. (Actually now that I think about it, with your suggestions I think I can cut out about half the script)

For context (sorry for the lack on comments), LDAP outputs a backup file of its database in an ldif file. We store 12 days worth on the local machine under /localbackup/ldap/ and these are also copied to an NFS share mounted at /backup/ldap/ in case of a total disaster on the local drive.. Each entry starts with the string "dn: " in this text file so getting the count of this is just a bit of a sanity check for the user in the case LDAP went really wonky and spit out an incomplete or empty backup. It just displays the count of the top 5 and the one your using. I was going to make it simply find the ldif with the highest "dn " entry but I ran out of time to finish Smilie

Anyways you've helped a lot.

Last edited by Riker1204; 09-28-2017 at 10:29 PM..
# 13  
Old 09-29-2017
Hi.

I put your script into file z9, then ran shellcheck on it, receiving this:
Code:
In z9 line 205:
        for i in 'cn=Standard' ; do
        ^-- SC1009: The mentioned parser error was in this for loop.

In z9 line 206:
           if ldapsearch -h localhost -p 389 -D "cn=root,dc=removed,dc=com" -w 'removed' -b "dc=removed" \
           ^-- SC1046: Couldn't find 'fi' for this 'if'.
           ^-- SC1073: Couldn't parse this if expression.

In z9 line 210:
               ldapsearch -h localhost -p 389 -D "cn=root,dc=removeddc=com" -w 'removed -b "dc=celeritas,dc=com" \
                                                                               ^-- SC1078: Did you forget to close this single quoted string?

In z9 line 212:
           elif ldapsearch -h localhost -p 389 -D "cn=root,dc=removed,dc=com" -w 'removed -b "dc=removed" \
                                                                                 ^-- SC1079: This is actually an end quote, but due to next char it looks suspect.

In z9 line 214:
           then
           ^-- SC1047: Expected 'fi' matching previously mentioned 'if'.
               ^-- SC1072: Unexpected keyword/token. Fix any mentioned problems and try again.

Some details for shellcheck:
Code:
shellcheck      analyse shell scripts (man)
Path    : /usr/bin/shellcheck
Version : 0.3.4
Type    : ELF 64-bit LSB executable, x86-64, version 1 (SYSV ...)
Help    : probably available with -h
Repo    : Debian 8.9 (jessie) 
Home    : http://hackage.haskell.org/package/ShellCheck (pm)

Best wishes ... cheers, drl
# 14  
Old 09-29-2017
Those missing quotes and errors from the end are simply copy and paste errors I was in a hurry to remove passwords from the document. I clipped some quotes along with it.
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Using associative array for comparison

Hello together, i make something wrong... I want an array that contains information to associate it for further processing. Here is something from my bash... You will know, what I'm trying to do. I have to point out in advance, that the variable $SYSOS is changing and not as static as in my... (2 Replies)
Discussion started by: Decstasy
2 Replies

2. Shell Programming and Scripting

Morse Code with Associative Array

Continuing my quest to learn BASH, Bourne, Awk, Grep, etc. on my own through the use of a few books. I've come to an exercise that has me absolutely stumped. The specifics: 1. Using ONLY BASH scripting commands (not sed, awk, etc.), write a script to convert a string on the command line to... (22 Replies)
Discussion started by: ksmarine1980
22 Replies

3. Shell Programming and Scripting

Associative Array with more than one item per entry

Hi all I have a problem where i have a large list ( up to 1000 of items) and need to have 2 items pulled from it into variables in a bash script my list is like the following and I could have it as an array or possibly an external text file maintained separately. Every line is different and... (6 Replies)
Discussion started by: kcpoole
6 Replies

4. Shell Programming and Scripting

Associative array

I have an associative array named table declare -A table table="fruit" table="veggie" table="GT" table="eminem" Now say I have a variable returning the value highway How do I find corresponding value GT ?? (this value that I find (GT in this case) is supposed to be the name of a mysql... (1 Reply)
Discussion started by: leghorn
1 Replies

5. Shell Programming and Scripting

Split string into map (Associative Array)

Hi Input: { committed = 782958592; init = 805306368; max = 1051394048; used = 63456712; } Result: A map (maybe Associative Array) where I can iterate through the key/value. Something like this: for key in $map do echo key=$key value=$map done Sample output from the map: ... (2 Replies)
Discussion started by: chitech
2 Replies

6. Shell Programming and Scripting

Help needed on Associative array in awk

Hi All, I got stuck up with shell script where i use awk. The scenario which i am working on is as below. I have a file text.txt with contents COL1 COL2 COL3 COL4 1 A 500 400 1 B 500 400 1 A 500 200 2 A 290 300 2 B 290 280 3 C 100 100 I could able to sum col 3 and col4 based on... (3 Replies)
Discussion started by: imsularif
3 Replies

7. UNIX for Dummies Questions & Answers

wh inode index starts from 1 unlike array index (0)

brothers why inode index starts from 1 unlike array inex which starts from 0 its a question from the design of unix operating system of maurice j.bach i need to know the answer urgently...someone help please (1 Reply)
Discussion started by: sairamdevotee
1 Replies

8. Filesystems, Disks and Memory

why the inode index of file system starts from 1 unlike array index(0)

why do inode indices starts from 1 unlike array indexes which starts from 0 its a question from "the design of unix operating system" of maurice j bach id be glad if i get to know the answer quickly :) (0 Replies)
Discussion started by: sairamdevotee
0 Replies

9. Shell Programming and Scripting

Perl: Sorting an associative array

Hi, When using sort on an associative array: foreach $key (sort(keys(%opalfabet))){ $value = $opalfabet{$key}; $result .= $value; } How does it handle double values? It seems to me that it removes them, is that true? If so, is there a way to get... (2 Replies)
Discussion started by: tine
2 Replies

10. Shell Programming and Scripting

Associative Array

Hi, I am trying to make an associative array to use in a popup_menu on a website. Here is what i have: foreach $entr ( @entries ) { $temp_uid = $entr->get_value(uid); $temp_naam = $entr->get_value(sn); $s++; } This is the popup_menu i want to use it in. popup_menu(-name=>'modcon',... (4 Replies)
Discussion started by: tine
4 Replies
Login or Register to Ask a Question