Parsing text in BASH - bash

I have a username system. The user picks a username, password and pin number and this is saved into UPP.db. I want to be able to parse this text so that a user can either be edited (Change password) or Deleted (Remove Line). I have coded a solution for both but both return me with an error and jump to the "Else" part of my If statement. I will provide the code for the edit section as the delete is pretty similar and would be redundant providing both.
echo "Please enter the username you wish to edit"
read usernamecheck
usernamesearch=$( grep $usernamecheck\$ UPP.db | cut -d" " -f1 )
if [ $usernamecheck = $usernamesearch ]
then
echo "Please enter $usernamesearch PIN"
read pincheck
pinupdate=$( grep $pincheck\$ UPP.db | cut -d" " -f3 )
if [[ $pin = $pinupdate && $usernamecheck = $usernamesearch ]]
then
echo "The user `grep "$pin"\$ UPP.db | cut -d" " -f1`'s password is about to be changed "
echo "Please enter the new password"
read newpass
passwordcheck=$( grep $pincheck\$ UPP.db | cut -d" " -f2 )
sed -i "s/$passwordcheck/$newpass/g" UPP.db
echo "Password changed"
else
echo "The PIN is incorrect"
fi
else
echo "This username is not reconised"
fi
;;

string equality comparisons will be more precise than regular expressions. Here, I use awk not grep to enable that. You might want to keep the bash man page handy while you read this.
read -p "Please enter the username you wish to edit: " usernamecheck
# extract all the fields at once
read -r db_user db_pass db_pin < <(
awk -v name="$usernamecheck" '$1 == name {print; exit}' UPP.db
)
if [[ -z $db_user ]]; then
echo "This username is not reconised"
else
read -p "Please enter $db_user PIN: " pincheck
if [[ "$db_pin" != "$pincheck" ]]; then
echo "The PIN is incorrect"
else
echo "Changing password for user $db_user:"
while true; do
read -s -p "Please enter the new password: " newpass
echo
read -s -p "Please re-enter the new password: " newpass2
echo
if [[ "$newpass" == "$newpass2" ]]; then
break
fi
echo "Passwords do not match. Try again."
done
ln UPP.db "UPP.db.$(date "+%Y%m%d%H%M%S")" # create a backup copy
temp=$(mktemp)
# update the password
awk -v newpw="$newpass" -v name="$db_user" '
$1 == name {$2 = newpw}
{print}
' UPP.db > "$temp" && mv "$temp" UPP.db
echo "Password changed"
fi
fi
Style tip: in an if-else-end construct, put the smaller block first, then the else-block is close to the condition. Aids readability.
If this plain text file, containing user passwords, is anywhere close to the internet, you're f*cked.

Related

Authentication issue with bash script

It works ("klist -A" shows valid principal):
password="<some_pwd>"
user="karim"
department="JUS"
echo $password | kinit $user#$domain.GOV
Password for karim#JUS.GOV:
But with the script I got the error:
Enter Password :Password for karim#JUS.GOV: kinit: Password incorrect while getting initial credentials
*Password for karim#JUS.GOV: kinit: Password incorrect while getting initial credentials
*Password for karim#JUS.GOV: kinit: Password incorrect while getting initial credentials
Each password's letter typing leads to the above message.
Script:
#!/bin/bash
password=""
echo "Provide user: "
read user
echo "Provide department's name (JUS, FIN, MIL): "
read department
pass_var="Provide password:"
while IFS= read -p "$pass_var" -r -s -n letter
do
if [[ $letter == $'\0' ]]
then
break
fi
password=password+"$letter"
pass_var="*"
if [[ $department == JUS ]];then
echo $password | kinit $user#$department.GOV
fi
done
Also, if user specify the department as JUS, FIN or MIL then the kinit command should be executed with the correct set department. I tried something like that but it does not work:
if [[ $department == JUS || FIN || MIL ]];then
Just fixing obvious errors:
#!/bin/bash
password=""
read -p "Provide username: " user
read -p "Provide department's name (JUS, FIN, MIL): " department
pass_var="Provide password: "
while IFS= read -p "$pass_var" -r -s -n 1 letter
do
if [[ $letter == $'\0' ]]
then
break
fi
password="$password$letter"
pass_var="*"
done
echo
if [[ $department == JUS ]]
then
echo "$password" | kinit "$user#$department.GOV"
fi
You can use a case or bash's =~ to match departments:
# ...
if [[ $department =~ JUS|FIN|MIL ]]
then
echo ...
fi
# ...
case "$department" in
JUS|FIN|MIL) echo ... ;;
esac

How to awk all lines instead of only looking at the first

I'm trying to write a script that allows you to enter your machine name, and then lets you know if the host is on the local network. Here's what I have:
#!/bin/bash
echo "Please enter the host you would like to ping:"
read -r host
output=$(ruptime | awk '{print $1}')
if [ "$output" == "$host" ];
then
echo "$host is up"
else
echo "$host is down"
fi
This works when I enter my machine name 'ubuntu' since I am the only one on my LAN and the awk statement outputs 'ubuntu'.
If I run for example:
#!/bin/bash
echo "Please enter the host you would like to ping:"
read -r host
output=$(cat /etc/hosts | awk '{print $1}')
if [ "$output" == "$host" ];
then
echo "$host is up"
else
echo "$host is down"
fi
The output is 2 lines: localhost and ubuntu. If I then run the script and enter either one of those, it says it's not found.
I think the awk is only looking for the value in the first line. How can I have the script check every line from the output of the awk and then compare it to what was entered?
Thanks in advance!
You're setting $output to all the names. You're not checking if $host is one of them, you're checking if $host is equal to all of them at once.
grep is a better way to do this.
if ruptime | grep -q -w "$host"
then echo "$host is up"
else echo "$host is down"
fi
Assuming that your goal is to look at whether a given name is in the first column of the output from ruptime, that might look like:
#!/usr/bin/env bash
hostname="target"
while read -r hostname _; do
[[ $hostname = "$target" ]] && { echo "$target is up"; break; }
done < <(ruptime)
read -r hostname _ puts only the first column of each line into hostname, putting remaining text into _.

Combine two Bash while loop statements

I am trying to combine 2 different logical statements in a single while loop, but having trouble getting the logic correct so that 2 different checks can be evaluated in the same loop. For example, I have the following 2 logical statements.
Logic 1
Determine if the entered username is blank and if it is ask the user to re-enter a different username.
echo -ne "User Name [uid]$blue:$reset "
read USERNAME
USERNAME=$(echo "$USERNAME" | tr "[:upper:]" "[:lower:]")
while [[ -z "$USERNAME" ]]; do
echo ""
printf "%s\n" "The User Name CAN NOT be blank"
echo ""
echo -ne "User Name [uid]$blue:$reset "
read USERNAME;
USERNAME=$(echo "$USERNAME" | tr "[:upper:]" "[:lower:]")
done
Logic 2
Determine if the read username already exists and if it does ask the user to re-enter a username.
echo -ne "User Name [uid]$blue:$reset "
read USERNAME
USERNAME=$(echo "$USERNAME" | tr "[:upper:]" "[:lower:]")
$(command -v getent) passwd "$USERNAME" &>/dev/null
while [[ $? -eq 0 ]]; do
echo ""
printf "%s\n" "$USERNAME exists in LDAP"
echo ""
echo -ne "User Name [uid]$blue:$reset "
read USERNAME;
USERNAME=$(echo "$USERNAME" | tr "[:upper:]" "[:lower:]")
$(command -v getent) passwd "$USERNAME" &>/dev/null
done
For achieving the described goal I have tried while loops and nested if statements and am just confused at this point. Basically as part of the script I would like these 2 logical statements to be combined when the user is asked to enter a username without the script exiting until a valid value is entered.
Don't use uppercase variable names!
#!/bin/bash
while true; do
echo -ne "User Name [uid]$blue:$reset "
read username
[ -z "$username" ] && echo -e "\nThe User Name CAN NOT be blank\n" && continue
username=$(tr [:upper:] [:lower:] <<< $username)
[ -z $(getent passwd "$username") ] && break || echo -e "\n$username exists in LDAP\n"
done
You could move the conditional check from the while statement to a pair of if statements. In this case, I've also moved the read and related commands to the top of the loop. This means you don't need extra read commands before the loop.
#!/bin/bash
while true; do
echo -ne "User Name [uid]$blue:$reset "
read username;
username=$(echo "$username" | tr "[:upper:]" "[:lower:]")
$(command -v getent) passwd "$username" &>/dev/null
if [[ -z "$username" ]]; then
echo ""
printf "%s\n" "The User Name CAN NOT be blank"
echo ""
continue #Skips the rest of the loop and starts again from the top.
fi
if [[ $? -eq 0 ]]; then
echo ""
printf "%s\n" "$username exists in LDAP"
echo ""
continue #Skips the rest of the loop and starts again from the top.
fi
#If execution reaches this point, both above checks have been passed
break #exit while loop, since we've got a valid username
done
As an aside, it's often recommended to avoid uppercase variable names, in order to avoid conflicts with system environment variables.

When running bash script that calls another script getting EOF error

The other script is just read statement that will be echo'ed into a file from this script
#!/usr/bin/bash
# createdb_wrapper.scr
# Log information about user of createdb.scr
Default_Dir=/export/home/cwatts/test
Default_Log=DB.Audit
while [ -z "${fname}" ]
do
echo "Please, enter your Fullname [ENTER]:"
read fname
done
Tried various ways to pull the information from the other script
dbname="./createDB.scr | awk '{print $1}'"
sh $dbname
while [ -z "${desc}" ]
do
echo "Please,enter a brief Description [ENTER]:
read desc
done
#Checks the directory exists, and creates if not
if [ ! -d $Default_Dir ] ;then
echo "directory doesn't exit, it will be created"
mkdir $Default_Dir
fi
echo `date -u` '|' $dbname '|' $fname '|' $desc >> $Default_Dir/$Default_Log
exit
You forgot the other quote:
echo "Please,enter a brief Description [ENTER]:
Should be
echo "Please,enter a brief Description [ENTER]:"
I also recommend this form:
#!/bin/bash
#
# createdb_wrapper.scr
# Log information about user of createdb.scr
#
DEFAULT_DIR='/export/home/cwatts/test'
DEFAULT_LOG='DB.Audit'
until read -p "Please, enter your Fullname [ENTER]: " FNAME && [[ -n $FNAME ]]; do
:
done
until read -p "Please,enter a brief Description [ENTER]: " DESC && [[ -n $DESC ]]; do
:
done
if [[ -d $DEFAULT_DIR ]]; then
echo "Directory does not exist. It will be created."
mkdir "$DEFAULT_DIR"
fi
echo "$(exec date -u) | $DBNAME | $FNAME | $DESC" >> "$DEFAULT_DIR/$DEFAULT_LOG"
Note: $DBNAME is not set.

New User creation script error

I have the script listed below that I can't seem to get the issue worked out of. I'm trying to make an interactive login script for a UNIX class that I'm in. I'm basically building out a command to pass into useradd. The command that I make when passed into the command line (while adding sudo) works as expected, but when I try to run it from my script (which is generating the text that I copy/paste into the command line) it gives me some errors... At this point I'm at a loss for what to try next to resolve the issue.
ERROR:
useradd -m --user-group jaredm2 #command that is attempting to run...
useradd: invalid option -- ' '
Usage: useradd [options] LOGIN
....rest of useradd error text....
SCRIPT:
#!/bin/bash
#Add a new user
FINALCOMMAND="-m"
#import useradd defaults...
. /etc/default/useradd
#Check if running as root
if [ "$(id -u)" != "0" ]; then
echo "This script must be ran as root"
exit 1
fi
#Get the new users Name
#echo -n "Please enter the users First and Last Name and press [ENTER]: "
#read Name
#Get the new users username
echo "The username must be 4-20 characters."
echo -n "Please enter the users requested username and press [ENTER]: "
read USERNAME
while [ $(grep -c "^${USERNAME}:" /etc/passwd) -ge 1 ] || [ ${#USERNAME} -le 3 ] || [ ${#USERNAME} -ge 21 ]
do
echo " "
echo "Error: Username is in use or invalid. Please select a different username."
echo " "
echo -n "Please enter the users requested username and press [ENTER]: "
read USERNAME
done #USERNAME will be valid from this point
#ASK about the default shell now
echo -n "Enter the new shell if you would like one (currently $SHELL) or leave blank for the default and press [ENTER]: "
read tempSHELL
if [ ${#tempSHELL} -ge 1 ]; then
SHELL="$tempSHELL"
FINALCOMMAND="$FINALCOMMAND ""-s $SHELL"
fi
#ASK about a different primary group
echo "Would you like to enter a non-default primary user group? Defaults to creating a new group that matches the username"
echo "Enter a new Primary Group or leave blank for the default and press [ENTER]: "
read newPrimaryGroup
if [ ${#newPrimaryGroup} -eq 0 ]; then
FINALCOMMAND="$FINALCOMMAND --user-group"
else
if [ $(grep -c "^${newPrimaryGroup}" /etc/group) -ge 1 ]; then
FINALCOMMAND="$FINALCOMMAND -g $newPrimaryGroup"
else
echo "Invalid group specified reverting to default!"
FINALCOMMAND="$FINALCOMMAND --user-group"
fi
fi
useradd -m --user-group jaredm2
#ASK about additional groups
echo "Would you like the new user to be a part of any additional groups? Leave blank if no additional groups are needed or enter additional groups in the format of GROUP1,GROUP2,... (NO SPACES) and press [ENTER]: "
read extraGroups
#remove spaces if the user entered any
extraGroups="${extraGroups//[[:space:]]}"
FINALEXTRAGROUPS=""
IFS=","
for g in $extraGroups
do
if [ $(grep -c "^${g}" /etc/group) -ge 1 ]; then
FINALEXTRAGROUPS="$FINALEXTRAGROUPS,$g"
else
echo "$g is invalid user will not be added..."
fi
done
FINALEXTRAGROUPS=$(echo "$FINALEXTRAGROUPS" | tail -c +2)
if [ ${#FINALEXTRAGROUPS} -ge 1 ]; then
FINALCOMMAND="$FINALCOMMAND -G $FINALEXTRAGROUPS"
fi
#ASK about the home directory
echo "Would you like to enter a new home directory for the user? Leave blank to use the default of $HOME/$USERNAME or enter your own and press [ENTER]: "
read NEWHOME
if [ ${#NEWHOME} -ge 1 ]; then
FINALCOMMAND="$FINALCOMMAND -d $NEWHOME"
fi
#ADD the username to the command
FINALCOMMAND=`echo "$FINALCOMMAND $USERNAME" | sed 's/ *$//g' | sed 's/^ *//g'`
echo "useradd $FINALCOMMAND"
#PASSCOMMAND="sudo passwd $USERNAME"
#ADD THE USER
`useradd $FINALCOMMAND`
`passwd $USERNAME`
`chfn $USERNAME`
UPDATE: ADDED DEBUG CONTENT
+ '[' 0 -ge 1 ']'
++ sed 's/^ *//g'
++ sed 's/ *$//g'
++ echo '/usr/sbin/useradd -m -U JaredM'
+ FINALCOMMAND='/usr/sbin/useradd -m -U JaredM'
++ '/usr/sbin/useradd -m -U JaredM'
./addnewuser.sh: line 89: /usr/sbin/useradd -m -U JaredM: No such file or directory
By using arrays you could prevent IFS related errors in the command-line and it's a lot cleaner. This one's already tested. I made some clean-ups to the code as well.
#!/bin/bash
#Add a new user
FINALCOMMAND=("-m")
#Import useradd defaults...
. /etc/default/useradd
#Check if running as root
if [ "$(id -u)" != "0" ]; then
echo "This script must be ran as root"
exit 1
fi
#Get the new users Name
#echo -n "Please enter the users First and Last Name and press [ENTER]: "
#read Name
#Get the new users username
echo "The username must be 4-20 characters."
echo -n "Please enter the users requested username and press [ENTER]: "
read USERNAME
while [ $(grep -c "^${USERNAME}:" /etc/passwd) -ge 1 ] || [ ${#USERNAME} -le 3 ] || [ ${#USERNAME} -ge 21 ]; do
echo " "
echo "Error: Username is in use or invalid. Please select a different username."
echo " "
echo -n "Please enter the users requested username and press [ENTER]: "
read USERNAME
done #USERNAME will be valid from this point
#ASK about the default shell now
echo -n "Enter the new shell if you would like one (currently $SHELL) or leave blank for the default and press [ENTER]: "
read tempSHELL
if [ ${#tempSHELL} -ge 1 ]; then
SHELL="$tempSHELL"
FINALCOMMAND=("${FINALCOMMAND[#]}" "-s" "$SHELL")
fi
#ASK about a different primary group
echo "Would you like to enter a non-default primary user group? Defaults to creating a new group that matches the username"
echo -n "Enter a new Primary Group or leave blank for the default and press [ENTER]: "
read newPrimaryGroup
if [ ${#newPrimaryGroup} -eq 0 ]; then
FINALCOMMAND=("${FINALCOMMAND[#]}" "--user-group")
else
if [ $(grep -c "^${newPrimaryGroup}" /etc/group) -ge 1 ]; then
FINALCOMMAND=("${FINALCOMMAND[#]}" "-g" "$newPrimaryGroup")
else
echo "Invalid group specified reverting to default!"
FINALCOMMAND=("${FINALCOMMAND[#]}" "--user-group")
fi
fi
#ASK about additional groups
echo -n "Would you like the new user to be a part of any additional groups? Leave blank if no additional groups are needed or enter additional groups in the format of GROUP1,GROUP2,... (NO SPACES) and press [ENTER]: "
read extraGroups
#remove spaces if the user entered any
extraGroups="${extraGroups//[[:space:]]}"
FINALEXTRAGROUPS=''
IFS=, read -a TEMP <<< "$extraGroups"
for g in "${TEMP[#]}"; do
if [ $(grep -c "^${g}" /etc/group) -ge 1 ]; then
FINALEXTRAGROUPS="$FINALEXTRAGROUPS,$g"
else
echo "$g is invalid user will not be added..."
fi
done
if [ ${#FINALEXTRAGROUPS[#]} -ge 1 ]; then
FINALCOMMAND=("${FINALCOMMAND[#]}" "-G" "${FINALEXTRAGROUPS:1}")
fi
#ASK about the home directory
echo -n "Would you like to enter a new home directory for the user? Leave blank to use the default of $HOME/$USERNAME or enter your own and press [ENTER]: "
read NEWHOME
if [ ${#NEWHOME} -ge 1 ]; then
FINALCOMMAND=("${FINALCOMMAND[#]}" "-d" "$NEWHOME")
fi
#ADD the username to the command
FINALCOMMAND=("${FINALCOMMAND[#]}" "$USERNAME")
#PASSCOMMAND="sudo passwd $USERNAME"
#ADD THE USER
echo "useradd ${FINALCOMMAND[#]}"
useradd "${FINALCOMMAND[#]}"
passwd "$USERNAME"
chfn "$USERNAME"
Note: In newer versions of bash you could just use += to append a value to an array e.g. ARRAY+=("value")
Also by my additional preferences I would improve the code further this way, but that's not the best of it yet:
#!/bin/bash
shopt -s extglob
# Check if running as root.
if [[ "$(id -u)" != 0 ]]; then
echo "This script must be ran as root."
exit 1
fi
# Initialize useradd command variable.
USERADDCOMMAND=("useradd" "-m")
# Import useradd defaults.
. /etc/default/useradd
# Get the new user's name.
#echo -n "Please enter the users First and Last Name and press [ENTER]: "
#read NAME
# Get the new users username.
echo "The username must be 4-20 characters."
while :; do
read -p "Please enter the user's requested username and press [ENTER]: " USERNAME
[[ ${#USERNAME} -ge 4 && ${#USERNAME} -le 20 && $USERNAME == +([[:alpha:]])*([[:alnum:]_-]) ]] || {
echo "Error: Username is invalid. Please enter a different username."
continue
}
[[ $(grep -c "^${USERNAME}:" /etc/passwd) -ge 1 ]] && {
echo "Error: Username is in use. Please enter a different username."
continue
}
break
done
# Ask about the default shell.
read -p "Enter the new shell if you would like one (currently $SHELL) or leave blank for the default and press [ENTER]: " SHELL_
if [[ ${#SHELL_} -ge 1 ]]; then
USERADDCOMMAND=("${USERADDCOMMAND[#]}" "-s" "$SHELL_")
else
# We use this if we really are to use SHELL specified in $SHELL but it still needs further workarounds like checking if $SHELL is valid. Those could be easily done but it depends if this one's really necessary.
#USERADDCOMMAND=("${USERADDCOMMAND[#]}" "-s" "$SHELL")
:
fi
# Ask about a different primary group.
echo "Would you like to enter a non-default primary user group? Defaults to creating a new group that matches the username."
echo -n "Enter a new Primary Group or leave blank for the default and press [ENTER]: "
read NEWPRIMARYGROUP
if [[ ${#NEWPRIMARYGROUP} -eq 0 ]]; then
USERADDCOMMAND=("${USERADDCOMMAND[#]}" "--user-group")
else
if [[ $(grep -c "^${NEWPRIMARYGROUP}" /etc/group) -ge 1 ]]; then
USERADDCOMMAND=("${USERADDCOMMAND[#]}" "-g" "$NEWPRIMARYGROUP")
else
echo "Invalid group specified reverting to default!"
USERADDCOMMAND=("${USERADDCOMMAND[#]}" "--user-group")
fi
fi
# Ask about additional groups.
echo -n "Would you like the new user to be a part of any additional groups? Leave blank if no additional groups are needed or enter additional groups in the format of GROUP1,GROUP2,... (NO SPACES) and press [ENTER]: "
read EXTRAGROUPS
# Remove spaces if the user entered any.
EXTRAGROUPS="${EXTRAGROUPS//[[:space:]]}"
FINALEXTRAGROUPS=''
IFS=, read -a TEMP <<< "$EXTRAGROUPS"
for G in "${TEMP[#]}"; do
if [[ $(grep -c "^${g}" /etc/group) -ge 1 ]]; then
FINALEXTRAGROUPS="$FINALEXTRAGROUPS,$G"
else
echo "$G is an invalid user and will not be added."
fi
done
if [[ ${#FINALEXTRAGROUPS[#]} -ge 1 ]]; then
USERADDCOMMAND=("${USERADDCOMMAND[#]}" "-G" "${FINALEXTRAGROUPS:1}")
fi
# Ask about the home directory
read -p "Would you like to enter a new home directory for the user? Leave blank to use the default of $HOME/$USERNAME or enter your own and press [ENTER]: " NEWHOME
if [[ ${#NEWHOME} -ge 1 ]]; then
USERADDCOMMAND=("${USERADDCOMMAND[#]}" "-d" "$NEWHOME")
fi
# Add the username to the command
USERADDCOMMAND=("${USERADDCOMMAND[#]}" "$USERNAME")
# Add THE USER
echo "> ${USERADDCOMMAND[*]}"
"${USERADDCOMMAND[#]}"
echo "> passwd $USERNAME"
passwd "$USERNAME"
echo "> chfn $USERNAME"
chfn "$USERNAME" # -f "$NAME"
If the man -s8 useradd does not mention --user-group option available to use, then -U will not work. There's still another solution worth trying:
The default behavior (if the -g, -N, and -U options are not specified)
is defined by the USERGROUPS_ENAB variable in /etc/login.defs.
Another way is, you have to chain the useradd command with a groupadd command with the same username supplied as parameters to both the commands.
EDIT:
This must work. First create the group and then create the user and add this new user to the group. Since, you are doing this in a script this should do the job very well.
Do this:
groupadd jaredm2
useradd -m -g jaredm2 jaredm2
Instead of this:
useradd -m --user-group jaredm2
Note that certain other programs which would've been installed in your OS, may have changed your binary or access to it or even created an alias for it. Your which output suggests that it is linked to the useradd binary in bin directory, precisely where it should be.
So I guess:
the binary might have been changed or replaced by a process, by package installers or something else
there's some mismatch between the binary version and the man page version(most likely if you have upgraded your OS improperly, at some point of time)
I think, the only solutions would be using the above pair of commands or changing the useradd binary you are using manually.
The problem is caused by your script you made ​​the use magic quotes `...` to execute your shell commands.
These quotes should only be used if you want to store the return of a command in a variable:
example the instruction below:
FINALCOMMAND=`echo "$FINALCOMMAND $USERNAME" | sed 's/ *$//g' | sed 's/^ *//g'`
Otherwise it is not necessary to use this quote and they can produce bugs like yours.
you can put in your script:
useradd $FINALCOMMAND
passwd $USERNAME
chfn $USERNAME
instead of:
`useradd $FINALCOMMAND`
`passwd $USERNAME`
`chfn $USERNAME`
Judging from your update with debug content, it seems like what you are doing is different from the script you posted.
Anyway, from the debug output, I suspect you're trying to run the adduser command using double quotes
"$FINALCOMMAND"
or maybe enclosed in backticks too, as that seems to be the only situation that triggers the "No such file or directory" error message.
Getting rid of the double quotes should fix the problem.
p/s: Don't use command substitution (``) unless you're actually using the output (e.g. for testing or assigning to variables), or else something like this might happen
$ `echo Just saying hi`
Just: command not found
I fixed the bug in your script, simply remove the line IFS=","
It is a misuse of the environment variable IFS (Internal Field Separator)
The script becomes:
#!/bin/bash
#Add a new user
FINALCOMMAND="-m"
#import useradd defaults...
. /etc/default/useradd
#Check if running as root
if [ "$(id -u)" != "0" ]; then
echo "This script must be ran as root"
exit 1
fi
#Get the new users Name
#echo -n "Please enter the users First and Last Name and press [ENTER]: "
#read Name
#Get the new users username
echo "The username must be 4-20 characters."
echo -n "Please enter the users requested username and press [ENTER]: "
read USERNAME
while [ $(grep -c "^${USERNAME}:" /etc/passwd) -ge 1 ] || [ ${#USERNAME} -le 3 ] || [ ${#USERNAME} -ge 21 ]
do
echo " "
echo "Error: Username is in use or invalid. Please select a different username."
echo " "
echo -n "Please enter the users requested username and press [ENTER]: "
read USERNAME
done #USERNAME will be valid from this point
#ASK about the default shell now
echo -n "Enter the new shell if you would like one (currently $SHELL) or leave blank for the default and press [ENTER]: "
read tempSHELL
if [ ${#tempSHELL} -ge 1 ]; then
SHELL="$tempSHELL"
FINALCOMMAND="$FINALCOMMAND ""-s $SHELL"
fi
#ASK about a different primary group
echo "Would you like to enter a non-default primary user group? Defaults to creating a new group that matches the username"
echo "Enter a new Primary Group or leave blank for the default and press [ENTER]: "
read newPrimaryGroup
if [ ${#newPrimaryGroup} -eq 0 ]; then
FINALCOMMAND="$FINALCOMMAND --user-group"
else
if [ $(grep -c "^${newPrimaryGroup}" /etc/group) -ge 1 ]; then
FINALCOMMAND="$FINALCOMMAND -g $newPrimaryGroup"
else
echo "Invalid group specified reverting to default!"
FINALCOMMAND="$FINALCOMMAND --user-group"
fi
fi
#useradd -m --user-group jaredm2
#ASK about additional groups
echo "Would you like the new user to be a part of any additional groups? Leave blank if no additional groups are needed or enter additional groups in the format of GROUP1,GROUP2,... (NO SPACES) and press [ENTER]: "
read extraGroups
#remove spaces if the user entered any
extraGroups="${extraGroups//[[:space:]]}"
FINALEXTRAGROUPS=""
#IFS=","
for g in $extraGroups
do
if [ $(grep -c "^${g}" /etc/group) -ge 1 ]; then
FINALEXTRAGROUPS="$FINALEXTRAGROUPS,$g"
else
echo "$g is invalid user will not be added..."
fi
done
FINALEXTRAGROUPS=$(echo "$FINALEXTRAGROUPS" | tail -c +2)
if [ ${#FINALEXTRAGROUPS} -ge 1 ]; then
FINALCOMMAND="$FINALCOMMAND -G $FINALEXTRAGROUPS"
fi
#ASK about the home directory
echo "Would you like to enter a new home directory for the user? Leave blank to use the default of $HOME/$USERNAME or enter your own and press [ENTER]: "
read NEWHOME
if [ ${#NEWHOME} -ge 1 ]; then
FINALCOMMAND="$FINALCOMMAND -d $NEWHOME"
fi
#ADD the username to the command
FINALCOMMAND=`echo "$FINALCOMMAND $USERNAME" | sed 's/ *$//g' | sed 's/^ *//g'`
echo "useradd $FINALCOMMAND"
#PASSCOMMAND="sudo passwd $USERNAME"
#ADD THE USER
useradd $FINALCOMMAND
passwd $USERNAME
chfn $USERNAME

Resources