Reputation: 209
I was trying to write a bash script to notify expiring user passwords. I am encountering an issue when at string comparison with 'never'. How do i avoid this?
I referred to Shell script to send email before password expires and tweaked a little. However i am facing the issue at string comparison. I intend to skip the code execution if $userexp is equal to never. However it is not happening and proceeding with the execution with next part of code and i am getting below error date: invalid date ‘ never’
#!/bin/bash
#
user=user
HOST=`uname -n`
# convert current date to seconds
currentdate=$(date +%s)
# find expiration date of user
userexp=$(chage -l $user | grep 'Password expires' | cut -d: -f2)
if [[ ! -z $userexp ]]
then
# convert expiration date to seconds
#passexp=$(date -d "$userexp" "+%s")
if [ "$userexp" = "never" ]
then
echo "Password for $user in $HOST is set to never expire"
else
# convert expiration date to seconds
passexp=$(date -d "$userexp" "+%s")
# find the remaining days for expiry
(( exp = $passexp - $currentdate ))
# convert remaining days from sec to days
(( expday = $exp / 86400 ))
if (($expday < 10 ))
then
echo "Password for $user in $HOST will expire in $expday day/s"
else
echo "Password for $user in $HOST still have much time to expire"
fi
fi
fi
Why is that my string comparison not working as expected and how can i fix it.
Upvotes: 1
Views: 628
Reputation: 19545
I fixed and tested your script. Issues were caused by lack of quoting sub-shell and variables
I have also secured the output of chage
to the POSIX
locale.
#!/usr/bin/env bash
# get user from argument 1 or default to current user
user="${1:-$(id --user --name)}"
host="$(uname --nodename)"
printf -v userhost_msg $"Password for %s in %s" "$user" "$host"
# convert current date to seconds
currentdate="$(date +%s)"
# find expiration date of user
userexp="$(
sed -n 's/Password expires[[:space:]]*:[[:space:]]\+\(.*\)$/\1/p' < <(
# use POSIX language to have predictable output from chage
LC_TIME=POSIX LC_MESSAGES=POSIX chage --list "$user"
)
)"
if [ -n "$userexp" ]; then
if [ "$userexp" = "never" ]; then
printf $"%s is set to never expire.\n" "$userhost_msg"
else
# convert expiration date to seconds
passexp=$(date -d "$userexp" "+%s")
# convert remaining days from sec to days
((expday = (passexp - currentdate) / 86400))
if ((expday < 10)); then
printf $"%s will expire in %d day/s.\n" "$userhost_msg" "$expday"
else
printf $"%s still have much time to expire.\n" "$userhost_msg"
fi
fi
fi
Upvotes: 1
Reputation: 3256
You need to deal with th space if the answer is 'never'
userexp=$(chage -l $user | grep 'Password expires' | cut -d: -f2)
The code above will return ' never', repair the space at the beggining.
You must trim the var userexp
if [ "${userexp##*( )} = "never" ]
add a space in the comparison
if [ "$"userexp" = " never" ] #add a space in never
or check if string contains substring
if [[ "$"userexp" = *"never"* ]]
Upvotes: 1
Reputation: 1365
if $userexp
is equal to "never" your code, even if not the best you could make (no offense :) ), should work. It think it could be that there is a leading space in your case, i.e., _never where _ is a blankspace. Check it out, if that is the case, change "never"
to " never"
in your if condition.
Upvotes: 2