0

I have problem with displaying array from below script (it shows how many days left until password expires):

#!/bin/bash
WARN=30
USERS=$(awk -F: '{if ($3 >= 1000) { print $1 } }' /etc/passwd)
DATE=$(date "+%s")
for USER in $USERS
do
    GET_EXP_DATE=$(/usr/sbin/lchage -l $USER | grep 'Password Expires' | cut -d: -f2)
    if [[ ${GET_EXP_DATE} == *"Never"* ]]
    then
            GET_EXP_DATE=01/01/2000
    fi
    PW_EXP_DATE=$(date -d "$GET_EXP_DATE" "+%s")
    DIFF=$(($PW_EXP_DATE-$DATE))
    let DAYS=$(($DIFF/(60*60*24)))

    # Do not send notification to legacy/non-expiring accounts - 365 days
    # and more from pw change
    if (($DAYS<=$WARN && $DAYS>=-365))
    then
            USER_ARRAY=${USER}
            DAYS_ARRAY=${DAYS}
    fi
    echo "${USER_ARRAY[@]} has ${DAYS_ARRAY[@]} days to password expiry"
done

Example output is:

 has  days to password expiry
 has  days to password expiry
 has  days to password expiry
 has  days to password expiry
 has  days to password expiry
 has  days to password expiry
 has  days to password expiry
andjac has -255 days to password expiry
apoole has -255 days to password expiry
rubtho has -255 days to password expiry
rubtho has -255 days to password expiry
rubtho has -255 days to password expiry
pfowle has -255 days to password expiry
pglomr has -255 days to password expiry
vrajan has -255 days to password expiry
vrajan has -255 days to password expiry
vrajan has -255 days to password expiry
vrajan has -255 days to password expiry
vrajan has -255 days to password expiry
vrajan has -255 days to password expiry
vrajan has -255 days to password expiry
vrajan has -255 days to password expiry

First lines are empty, and some are duplicated. It's array issue, as simple cmd:

echo $USER $DAYS

shows correct values.

2
  • A string with spaces in it is not an array. And as a matter of good practice, avoid all-caps variable names: They're used for environment variables with meaning to the operating system; using them for your own variables as well means you can overwrite a system variable by mistake (and, indeed, you are overwriting the system-defined variable USER here from your code). See the relevant POSIX specification for guidelines/conventions. Commented Oct 27, 2016 at 16:49
  • Thanks for heads up! Commented Oct 28, 2016 at 8:38

2 Answers 2

2

The problem is you haven't defined any arrays.

#!/bin/bash
warn=30
readarray -t users < <(awk -F: '{if ($3 >= 1000) { print $1 } }' /etc/passwd)
current_date=$(date "+%s")
for user in "${users[@]}"
do
    get_exp_date=$(/usr/sbin/lchage -l "$user" | grep 'Password Expires' | cut -d: -f2)
    if [[ ${get_exp_date} == *"Never"* ]]
    then
      get_exp_date=01/01/2000
    fi
    pw_exp_date=$(date -d "$get_exp_date" "+%s")
    date_diff=$(($pw_exp_date - $current_date))
    days=$(($date_diff / (60*60*24)))

    # Do not send notification to legacy/non-expiring accounts - 365 days
    # and more from pw change
    if (($days <= $warn && $days >= -365))
    then
      user_array+=( "$user" )
      days_array+=( "$days" )
    fi
done

for ((i=0; i < ${#user_array[@]}; i++)); do
  echo "${user_array[i]} has ${days_array[i]} days to password expiry"
done

In general, don't use all-caps variable names for your own variables; assume any such value is already reserved for some other purpose.

Sign up to request clarification or add additional context in comments.

5 Comments

user_array+=( "$user" ) would be safer -- some platforms, such as cygwin, can have usernames with whitespace. Similar for -l $user vs -l "$user", &c.
Hi chepner, thanks for your answer! Unfortunately when I run your script I'm getting no (empty) results - possibly there's something wrong with (changed) date calculations. I tried to fix my script using yours and at the and I'm getting right output but in format (all glued in one line): ./check_pass_expiry_new.sh andjacapoolerubthopfowlepglomrvrajanosteelluhartjalanddfarretwhinctakhtakarokiamitranarkalecadma has -256-256-256-256-256-2560-1651070-256-238-256-133-349-22501-364-351-176-347-179-289 days to password expiry
@h3938116, which version of bash are you running? If the original code didn't work, I'm wondering if you don't have readarray, which was added in 4.0. In any event, could you post the output of chepner's script when run with bash -x thescript 2>&1 | tee logfile to gist.github.com? Feel free to add the set -x output of your own script as adopted as a separate file in the same gist, but please include its source (again, as a separate file) if you so so. BTW, appending to the first entry rather than adding a new entry to the array would be caused by leaving the parentheses out.
I fixed one minor typo in the second loop, changed from users_array to user_array.
And it works!!! Btw "}" is missing in last user_array call (should be: ${user_array[i]} ). THANK YOU ALL!!!
0

Are you married to using an array? Just echo the results as you find them.

#!/bin/bash
WARN=30
USERS=$(awk -F: '{if ($3 >= 1000) { print $1 } }' /etc/passwd)
DATE=$(date "+%s")
for USER in $USERS
do
    GET_EXP_DATE=$(/usr/sbin/lchage -l $USER | grep 'Password Expires' | cut -d: -f2)
    if [[ ${GET_EXP_DATE} == *"Never"* ]]
    then
            GET_EXP_DATE=01/01/2000
    fi
    PW_EXP_DATE=$(date -d "$GET_EXP_DATE" "+%s")
    DIFF=$(($PW_EXP_DATE-$DATE))
    let DAYS=$(($DIFF/(60*60*24)))

    # Do not send notification to legacy/non-expiring accounts - 365 days
    # and more from pw change
    if (($DAYS<=$WARN && $DAYS>=-365))
    then
        echo "$USER has $DAYS days to password expiry"
        #your mail code here
    fi
done

2 Comments

:) Thanks. Reason why I'm using array is because I want to mail the output but don't want to put it in external file.
I know, but it's one generic list/report, not mail to every user. But thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.