bashdebianexpectpasswd

expect doesn't pass input to passwd in bash script


I'm attempting to pass the $PASSWORD variable contents into passwd using expect. This appears to work, adding the users but once you attempt to log in via ssh with one of the users, it doesnt work. If i set the password manually, it's then fine.

Had anyone encountered this issue before?

USERS=(user1 user2 user3)



generatePassword ()
{
        pwgen 16 -N 1
}

# Check if user is root
if [ $(whoami) != 'root' ]; then
        echo "Must be root to run $0"
        exit 1;
fi

# Check if pwgen is installed:
if [[ $(dpkg -s pwgen > /dev/null 2>&1; echo ${PIPESTATUS} ) != '0' ]]; then
        echo -e "pwgen is not installed, this script will not work without it\n\n'apt-get install pwgen'\n"
        exit 1;
    else
        echo -e "Starting Script...\n\n"
fi

# Iterate through users and add them with a password
for i in ${USERS[@]}; do
        PASSWORD=$(generatePassword)
        echo "$i $PASSWORD" >> passwords

        useradd -m "${i}"

        echo -e "Adding $i with a password of '$PASSWORD'\n"

        expect -c "
            spawn passwd ${i}

            expect \"Enter new UNIX password:\"
            send -- \"$PASSWORD\r\"
            send -- \"\r\"
            expect \"Retype new UNIX password:\"
            send -- \"$PASSWORD\r\"
            send -- \"\r\"
             "
            echo -e "\nADDED $i with a password of '$PASSWORD'\n"
done

Solution

  • You con't need expect at all: use chpasswd instead of passwd

    #!/bin/bash
    users=(user1 user2 user3)
    
    # Check if user is root
    if [[ "$(id -un)" != 'root' ]]; then
        echo "Must be root to run $0"
        exit 1
    fi
    
    # Check if pwgen is installed:
    if ! dpkg -s pwgen > /dev/null 2>&1; then
        printf "pwgen is not installed, this script will not work without it\n\n'apt-get install pwgen'\n"
        exit 1
    else
        printf "Starting Script...\n\n"
    fi
    
    # Iterate through users and create a password
    passwords=()
    for user in "${users[@]}"; do
        useradd -m "$user"
        password="$user:$(pwgen 16 -N 1)"
        passwords+=("$password")
        echo "Adding user '$user' with '$password'"
    done 
    
    printf "%s\n" "${passwords[@]}" | chpasswd
    

    I've added several quotes which are required.
    I've simplified the dpkg checking.

    Or, perhaps simpler, newusers to perform the "useradd" and "passwd" functions atomically.

    for user in "${users[@]}"; do
        password="$user:$(pwgen 16 -N 1)"
        password=${password//:/-}         # replace all colon with hyphen
        printf "%s:%s::::/home/%s:/bin/bash\n" "$user" "${password//:/-}" "$user"
    done | newusers
    

    I don't think newusers populates the home directory from /etc/skel though.