This shell script is supposed to add users to the system. The new users details are in a file. The shell is rejecting this script with the message:
syntax error near unexpected token 'done'.
What's wrong?
#!/bin/bash
#Purpose: Automatically add new users in a linux system based upon the data found within a text file
# Assign encryped passwords to each user
# Add users to groups or create new groups for these users
# Report errors and successful operations where necessary in log files
# post help options (echo)
#Root validation
if [[ $(id -u) -eq 0 ]]; then
#Argument validation
if [[ -z "$1" ]]; then
echo "No arguments found!"
echo "Please include a user detail text file as first argument"
echo "Please include a report text file as second argument"
echo "Please include an error report text file as the third argument"
echo "Use the -h argument (i.e. ./script -h) for help"
exit 1
fi
#Help validation and Help file
if [[ "$1" = "-h" ]]; then
echo "This is the help information file"
echo "This script is designed to add users to a linux system by reading information from a user detail file (such as userlist.txt)"
echo "The format of this user detail text file is "username password groupname fullname" seperated using TAB spacing"
echo "This script will read the first argument as the user detail file, the second and third arguments will be read as a success report file and error report file respectively"
exit
fi
#Reads first argument as user detail file for data
cat userlist.txt | while read uname password gname fullname
#Reads /etc/passwd for Username
egrep -w "^$uname" /etc/passwd
#If Username is found then error reports
if [ $? == 0 ]; then
echo "User Already Exists : Error adding user with username $uname;$gname;$fullname" >> Successes1.log
exit 1
else
#Reads /etc/group for Groupname
egrep -w "^$gname" /etc/group
#If Groupname is found then nothing
if [ $? == 0 ]; then
echo ""
else
#If Groupname not found then creates new group and reports
groupadd "$gname"
echo "Group Not Found: New Group $gname was created" >> Successes1.log
fi
#Retrieves Date
createddate=$(date)
#Perl password script takes input from Userlist
pass=$(perl -e 'print crypt($ARGV[0], "Password")' "$password")
#Adds Users with variables from userlist
useradd "$uname" -g "$gname" -c "$fullname" -p "$pass"
#Reports information to successlist and errorlist report files
if [ $? == 0 ]; then
groupid=$(id -g $uname)
userid=$(id -u $uname)
echo "User Successfully Added: $uname;$userid;$gname;$groupid;$createddate;$fullname" >> Successes1.log
else
groupid=$(id -g $uname)
userid=$(id -u $uname)
echo "Useradd Error Occurred: $uname;$userid;$gname;$groupid;$createddate;$fullname" >> Errors1.log
echo "Error: Must be root user to execute script"
exit
fi
done
Second attempt
Using some of the ideas from the answers, I came up with a second attempt:
#!/bin/bash
#Purpose: Automatically add new users in a linux system based upon the data found within a text file
# Assign encryped passwords to each user
# Add users to groups or create new groups for these users
# Report errors and successful operations where necessary in log files
# post help options (echo)
#Root validation
if [[ $(id -u) -eq 0 ]]; then
#Argument validation
if [[ -z "$1" ]]; then
echo "Usage: $0 usernames report errors" 1>&2
echo "Please include a user detail text file as first argument"
echo "Please include a report text file as second argument"
echo "Please include an error report text file as the third argument"
echo "Use the -h argument (i.e. ./script -h) for help"
exit 1
fi
fi
#Help validation and Help file
if [[ "$1" = "-h" ]]; then
echo "This is the help information file"
echo "This script is designed to add users to a linux system by reading information from a user detail file (such as userlist.txt)"
echo "The format of this user detail text file is "username password groupname fullname" seperated using TAB spacing"
echo "This script will read the first argument as the user detail file, the second and third arguments will be read as a success report file and error report file respectively"
exit
fi
#Reads first argument as user detail file for data
cat jan.txt | while read uname password gname fullname; do
#Reads /etc/passwd for Username
egrep -w "^$uname:" /etc/passwd >/dev/null 2>&1
#If Username is found then error reports
if [ $? == 0 ]
then
echo "User Already Exists : Error adding user with username $uname;$gname;$fullname" >> Errors1.log
else
#Reads /etc/group for Groupname
egrep -w "^$gname" /etc/group
#If Groupname is found then nothing
if [ $? == 0 ]; then
echo ""
else
#If Groupname not found then creates new group and reports
groupadd "$gname"
echo "Group Not Found: New Group $gname was created" >> Successes1.log
done < $1
#Retrieves Date
createddate=$(date)
#Perl password script takes input from Userlist
pass=$(perl -e 'print crypt($ARGV[0], "Password")' "$password")
#Adds Users with variables from userlist
useradd "$uname" -g "$gname" -c "$fullname" -p "$pass"
#Reports information to successlist and errorlist report files
if [ $? == 0 ]
then
groupid=$(id -g $uname)
userid=$(id -u $uname)
echo "User Successfully Added: $uname;$userid;$gname;$groupid;$createddate;$fullname" >> Successes1.log
else
groupid=$(id -g $uname)
userid=$(id -u $uname)
echo "Useradd Error Occurred: $uname;$userid;$gname;$groupid;$createddate;$fullname" >> Errors1.log
echo "Error: Must be root user to execute script"
exit 1
fi
fi
done
This does not seem to work properly either. What's wrong now?
Seems to show arguments and runs however no users nor group have been added therefore no logs have been created
The if starting at:
if [ $? == 0 ]; then
echo "User Already Exists : Error adding user with username ...
exit 1
else
is ended with the done instead of the fi that is required.
The while loop starting a couple of lines earlier:
cat userlist.txt | while read uname password gname fullname
is missing its do (another bug); if that was present, then it would also need the done at the end. Someone lost track of the indentation. (Using 2 characters per level is better than 0 or 1, but it is easier to track levels if you use 4 spaces per level.) Note that the shell hasn't gotten around to complaining about the lack of do because the syntax for a while loop is:
while cmd1
cmd2
cmd3 ...
do
and as far as the shell is concerned, it is still processing commands in the list cmd1, cmd2, cmd3, ....
Here's a semi-decently indented version of the script. There was a missing fi at the top of the script, too.
#!/bin/bash
#Purpose: Automatically add new users in a linux system based upon the data found within a text file
# Assign encryped passwords to each user
# Add users to groups or create new groups for these users
# Report errors and successful operations where necessary in log files
# post help options (echo)
#Root validation
if [[ $(id -u) -eq 0 ]]
then
#Argument validation
if [[ -z "$1" ]]
then
echo "No arguments found!"
echo "Please include a user detail text file as first argument"
echo "Please include a report text file as second argument"
echo "Please include an error report text file as the third argument"
echo "Use the -h argument (i.e. ./script -h) for help"
exit 1
fi
fi
#Help validation and Help file
if [[ "$1" = "-h" ]]
then
echo "This is the help information file"
echo "This script is designed to add users to a linux system by reading information from a user detail file (such as userlist.txt)"
echo "The format of this user detail text file is "username password groupname fullname" seperated using TAB spacing"
echo "This script will read the first argument as the user detail file, the second and third arguments will be read as a success report file and error report file respectively"
exit
fi
#Reads first argument as user detail file for data
cat userlist.txt | while read uname password gname fullname
do
#Reads /etc/passwd for Username
egrep -w "^$uname" /etc/passwd
#If Username is found then error reports
if [ $? == 0 ]
then
echo "User Already Exists : Error adding user with username $uname;$gname;$fullname" >> Successes1.log
exit 1
else
#Reads /etc/group for Groupname
egrep -w "^$gname" /etc/group
#If Groupname is found then nothing
if [ $? == 0 ]
then
echo ""
else
#If Groupname not found then creates new group and reports
groupadd "$gname"
echo "Group Not Found: New Group $gname was created" >> Successes1.log
fi
#Retrieves Date
createddate=$(date)
#Perl password script takes input from Userlist
pass=$(perl -e 'print crypt($ARGV[0], "Password")' $pass)
#Adds Users with variables from userlist
useradd "$uname" -g "$gname" -c "$fullname" -p "$pass"
#Reports information to successlist and errorlist report files
if [ $? == 0 ]
then
groupid=$(id -g $uname)
userid=$(id -u $uname)
echo "User Successfully Added: $uname;$userid;$gname;$groupid;$createddate;$fullname" >> Successes1.log
else
groupid=$(id -g $uname)
userid=$(id -u $uname)
echo "Useradd Error Occurred: $uname;$userid;$gname;$groupid;$createddate;$fullname" >> Errors1.log
echo "Error: Must be root user to execute script"
exit
fi
fi
done
There is still much room for improvement. The root validation block should exit if the user is not root; that happens instead a mile further down inside the loop. You can check the number of arguments better: $# gives you the number of arguments. If I tried yourscript.sh '' arg2 arg3, you'd claim there were no arguments when in fact the problem is that $1 is present but is an empty string. The standard convention for reporting how to use a command is something like:
echo "Usage: $0 usernames report errors" 1>&2
This reports the command's name, and the arguments expected. The 1>&2 sends the message to standard error instead of standard output. The logic here is a little bizarre even so. You check that the user is root and only then check that there are arguments. If the user is not root, you don't check the arguments. Not entirely sensible, I submit.
We can debate the UUOC (Useless Use of Cat). There's actually an award for it; I don't think this qualifies. However, it would be possible to write:
while read uname password gname fullname
do
...
done < $1
Hmmm...the script is supposed to take a file name argument that specifies the users, but the cat takes a fixed file name, not the file name argument!
Similarly, arguments 2 and 3 are studiously ignored; the log files are hard-coded.
egrep -w "^$uname" /etc/passwd
#If Username is found then error reports
if [ $? == 0 ]
This fragment can be improved several ways:
if egrep -w "^$uname:" /etc/passwd >/dev/null 2>&1
then
#If Username is found then error report
This tests the exit status of the egrep command directly; it also prevents a new user roo from being treated as pre-existing because of user root. It sends the output and error output to /dev/null so that you won't see anything when the user does exist.
It might be better not to exit when the user name is found; you could at least try to process the next entry. It is also odd that the report that the user exists (which terminates the processing) is recorded in Successes1.log rather than in Errors1.log; it is treated like an error.
The group check constructs are similar and should be similarly upgraded.
You read the password into $password with the read line; when it comes to creating the password, though, you have:
pass=$(perl -e 'print crypt($ARGV[0], "Password")' $pass)
On the first cycle, $pass is empty (most probably); you should have used $password in double quotes at the end:
pass=$(perl -e 'print crypt($ARGV[0], "Password")' "$password")
As with the egrep commands, you can check the status of the useradd command directly too. It is a bit sweeping to say if [ $? == 0 ] is the mark of a tyro, but it isn't too far off the truth.
The final exit in the script should be exit 1 to indicate an error exit. As already noted, this is preceded by the comment about 'you must be root', even though there was a check at the top for root privileges.
Caveat: I've not attempted to run the script; I could easily have missed some issues. It does, however, pass sh -v -n, so there are no gross syntactic errors left.
Once a shell script is syntactically correct, then you normally debug it using sh -x script (or, if it takes arguments, then sh -x script arg1 arg2 arg3 ...). This is the execution trace mode. The shell tells you, more or less inscrutably, what it is doing. The information is written to standard error. You can even trap the output for later scrutiny if you like with:
sh -x script arg1 arg2 arg3 2>script-x.log
The 2>script-x.log notation sends the standard error to the file script-x.log (choose your own meaningful name; I often use x or xxx for files I won't want to keep, but I also remove such files without necessarily even looking at them because I know they are throwaway files).
"done" is supposed to be paired with a previous "do"
It does not man th end of your script.
Your while is missing a do:
cat userlist.txt | while read uname password gname fullname
do
or
cat userlist.txt | while read uname password gname fullname; do
Related
I'm trying to get this script to loop back and restart if the user inputs a response that does not match the choices allowed but then enters a correct response the second time around. I tried using continue, but it loops infinitely. Any thoughts?
`
#!/bin/bash
#Obtaing user selection and input
echo " Gathering list of users on this machine..."
sleep 2
echo "$( ls /Users )"
echo "From the list above, which user did you want to work with?"
read userSelection
echo "What is that user's password?"
#Hiding User's Password
stty -echo
read userSelectionPassword
stty echo
echo "Did you want [enable], [disable], or check the current [status] of Secure Token for $userSelection?"
read taskSelection
#Converting input to lowercase
taskSelectionLower=$(echo $taskSelection | tr '[:upper:]' '[:lower:]')
#Running commands
while [ true ]
do
if [[ $taskSelectionLower == "enable" ]]; then
echo "Enabling..."
echo "$(sysadminctl -adminUser AdminUser -adminPassword AdminPass -secureTokenOn $userSelection -password $userSelectionPassword)"
break
elif [[ $taskSelectionLower == "status" ]]; then
echo "Displaying $userSelection current Secure Token status..."
echo "$( sysadminctl -secureTokenStatus $userSelection )"
break
elif [[ $taskSelectionLower == "disable" ]]; then
echo "Disabling..."
echo "$(sysadminctl -adminUser AdminUser -adminPassword AdminPass -secureTokenOff $userSelection -password $userSelectionPassword)"
break
else
echo "Incorrect selection made..."
echo "Did you want [enable], [disable], or check the current [status] of Secure Token for $userSelection?"
read taskSelection
exit
fi
done
`
Attempted using continue at the end of the condition, but loops infinitely.
Expected outcome would be for the for loop to restart, allowing the user to input a correct response and get the correct output.
The select command was designed exactly for this sort of interactive script.
Some hopefully useful observations -
echo " Gathering list of users on this machine..."
sleep 2 # why?
This sleep seems to serve no purpose but to annoy the user.
echo "$( ls /Users )" # why?? Don't do this.
This is exactly the same as
ls /Users # same output. Keep it simple.
Also, since you are bash instead of sh, rather than
taskSelectionLower=$(echo $taskSelection | tr '[:upper:]' '[:lower:]')
try declaring the variable as lowercase -
declare -l taskSelectionLower
read taskSelectionLower
or handle it with parameter parsing syntax -
read taskSelectionLower
taskSelectionLower="${taskSelectionLower,,}"
but why let them possibly mistype at all?
Consider using a select statement.
Rather than building your own loop, presenting options, worrying about formatting, etc, let tools that already do that handle it for you.
My rewrite using echo to show the commands to be executed - take those out and it should run fine.
#!/bin/bash
cd /c/Users
echo "Please select a valid user from this system."
select u in */; do
if [[ -d "$u" ]]
then userSelection="${u%/}"; break
else echo "Please enter a number from the presented options."
fi
done # get just the username
cd $OLDPWD # if needed
admSet() { # no reason to ask for the password just to get status...
read -sp "what's $userSelection's password? " userSelectionPassword
echo # reading the password leaves the cursor on the previous line
echo sysadminctl -adminUser AdminUser -adminPassword AdminPass \
-secureToken$1 "$userSelection" -password "$userSelectionPassword"
}
select taskSelection in enable disable status; do # case is controlled
case "$taskSelection" in
status) echo "Displaying $userSelection current Secure Token status..."
echo sysadminctl -secureTokenStatus $userSelection ;;
enable) echo "Enabling..." ; admSet On ;;
disable) echo "Disabling..." ; admSet Off ;;
*) echo "Please enter a number from the presented options."
continue ;;
esac
break
done
This question already has answers here:
When are square brackets required in a Bash if statement?
(3 answers)
Closed 1 year ago.
I'm fairly new to Linux and I'm working my way though a course of learning. I've been working on a script to create a new group, which checks for duplicates and then also does the same for a new user and configures some parameters for the user. I've gotten so far, but I suspect, I'm either over-complicating it, or just too much of a noob.
Here's my script:
#!/bin/bash
# Challenge Lab B: Bash Scripting
# Script settings in OS:
# 1. set user owner to root
# 2. set group owner to root
# 3. set permission to include setuid (4755)
# 4. run script with sudo
echo -n 'Enter new group: '
read group_name
echo 'checking for duplicates...'
while [ grep -q "$group_name" /etc/group == 0 ]
do
echo 'group already exists; try another.'
if [ grep -q "$group_name" /etc/group == 1 ];
then
break
fi
done
echo 'group does not exist.';
echo 'creating group.';
groupadd $group_name;
echo "$group_name group created";
echo -n 'Enter new user: '
read user_name
while [ grep -q "$user_name" /etc/passwd == 0 ]
do
echo 'user already exists; try another.'
if [ grep -q "$user_name" /etc/passwd == 1 ];
then
break
fi
done
echo 'user does not exist.';
echo 'creating user directory.';
mkdir /$user_name;
echo 'creating user.';
useradd -s /bin/bash -g $group_name $user_name;
echo "changing home directory user and group ownership to $user_name";
chown $user_name:$group_name /$user_name;
echo 'changing user and group mode to RWX and setting sticky bit';
chmod 1770 /$user_name
echo "Process complete"
And here's the result:
Enter new group: test1
checking for duplicates...
./test_sc: line 25: [: too many arguments
group does not exist.
creating group.
test1 group created
Enter new user: user1
./test_sc: line 57: [: too many arguments
user does not exist.
creating user directory.
creating user.
changing home directory user and group ownership to user1
changing user and group mode to RWX and setting sticky bit
Process complete
Clearly, it kind of works, but I'm sure the low-level handling of the duplicate isn't working based upon the result.
I'm sure many will look upon my work as terrible, but this is my first one, so please bear that in mind.
Cheers,
S
if [ grep -q "$user_name" /etc/passwd == 1 ];
The brackets are not just syntax: [ is a command.
Take note of the if syntax:
$ help if
if: if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi
Execute commands based on conditional.
...
The part you put after if is a command. if branches based on the exit status of the command.
You want
if ! grep -q "$user_name" /etc/passwd; then
You should remove square brackets this way if you want to check return value (true or false):
while [ grep -q "$group_name" /etc/group == 0 ]
change to:
while grep -q "$group_name" /etc/group; do
If you want to check that this value is incorrect, add ! before the command
You should do that not only for while loops, but also for if statements
Or if you want to check return value for a specific value, let's say 15:
grep something file
ret=$(echo $?)
if [ $ret == 15 ]; then
do something;
fi
$? will return the last return value from the command that you have executed in bash
I have a bash script that prompts the user for different information based on what they're trying to do. The prompts are usually done with read -p. Usually it works just fine, the user sees what is being asked, enters what they need to enter, and everything does what it needs to do.
See the following (sanitized) snippet of a function in the script:
#!/bin/bash
function_name() {
if [ "$this_value" == "default" ];then
echo "Value set to default."
read -p "Enter desired value here: " desired_value
desired_value=${desired_value^^}
if [ "${#desired_value}" != 3 ] ;then
echo "$desired_value is an invalid entry."
exit 1
fi
if [ "$desired_value" != "$(some command that returns something to compare against)" ];then
echo "$desired_value is an invalid entry."
exit 1
fi
read -p "You entered $desired_value. Is this correct? [y/N] " reply
reply=${reply,,}
case "$reply" in
y|yes)
$some command that does what I want it to do
;;
*)
echo "User did not enter yes"
exit 1
;;
esac
fi
}
Usually the Enter desired value here and is this correct? lines appear just fine. But in a few instances I've seen, for some reason the read prompt is just blank. A user will see the following:
./script.bash
##unrelated script stuff
##unrelated script stuff
Value set to default.
user_entered_value_here
User did not enter yes. Exiting.
This is a real example that just happened that finally made me come here to ask what is going on (and I modified appropriately to make it an SO post).
What's happening is these two blank lines appear instead of the read -p text. For the first one, the user entered user_entered_value_here because they already know what is supposed to be entered there even without the read prompt. The second one, the Y/N prompt, they don't know, so they see it apparently hanging, and hit Enter instead of y, causing it to trigger the * case option.
I don't understand why the read -p text is not appearing, and especially why it's appearing for most users but not all users. I suspect there's some kind of environmental setting that causes this, but for the life of me I can't figure out what. This is being run only on RHEL 6.2, under bash 4.1.2.
I looked at the man of bash to catch some kind of detail about the read built-in. It is specified that -p option displays the "prompt on standard error, without a trailing newline, before attempting to read any input. The prompt is displayed only if input is coming from a terminal".
Let's consider the simple script input.sh:
#!/bin/bash
read -p "Prompt : " value
echo The user entered: "$value"
Example of execution:
$ ./input.sh
Prompt : foo
The user entered: foo
If stderr is redirected:
$ ./input.sh 2>/dev/null
foo
The user entered: foo
If the input is a pipe
$ echo foo | ./input.sh
The user entered: foo
If the input is a heredoc
$ ./input.sh <<EOF
> foo
> EOF
The user entered: foo
Rewrote your script with shell agnostic grammar and fixed some errors like comparing the string length with a string comparator != = rather than a numerical comparator -ne -eq:
#!/usr/bin/env sh
this_value=default
toupper() {
echo "$1" | tr '[:lower:]' '[:upper:]'
}
function_name() {
if [ "$this_value" = "default" ]; then
echo "Value set to default."
printf "Enter desired value here: "
read -r desired_value
desired_value=$(toupper "$desired_value")
if [ "${#desired_value}" -ne 3 ]; then
printf '%s is an invalid entry.\n' "$desired_value"
exit 1
fi
if [ "$desired_value" != "$(
echo ABC
: some command that returns something to compare against
)" ]; then
echo "$desired_value is an invalid entry."
exit 1
fi
printf 'You entered %s. Is this correct? [y/N] ' "$desired_value"
read -r reply
reply=$(toupper "$reply")
case $reply in
'y' | 'yes')
: "Some command that does what I want it to do"
;;
*)
echo "User did not enter yes"
exit 1
;;
esac
fi
}
function_name
I have a shell script where I pass (2) parameters, one to pass a dbname, the other to call one of (2) filenames. I want to check if either filename exists, then proceed with calling that script, else exit because the user can enter the wrong string and construct my_foo.sql which I don't want. I don't think I have the condition for setting "or" correctly since putting the correct param still produces error. Is there a better way to write this?
Here is what I have so far.
#/usr/bin/ksh
if [ $# != 2 ]; then
echo "Usage: test.sh <dbname> <test|live>" 2>&1
exit 1
fi
# Check actual file name
CHKSCRIPT1=/tmp/my_test.sql;
CHKSCRIPT2=/tmp/my_live.sql;
if [ -f "CHKSCRIPT1" ] || [ -f "CHKSCRIPT2" ]
then
/bin/sqlplus -s foo/bar #/my_$2.sql
else
echo "Correct sql script does not exist. Enter test or live"
exit 1
fi
Your issue is that you're not referencing your variables correctly:
if [ -f "$CHKSCRIPT1" ] || [ -f "$CHKSCRIPT2" ]
...
fi
edit: Per #chepner, you shouldn't use -o
In addition to the problem you had with expanding the parameters, you should separate what the user types from what files need to exist. If the user enters "live", the only thing that matters is whether or not /tmp/my_live.sql exists. If the user enters "injection_attack", your script should not execute /tmp/my_injection_attack.sql (which presumably was created without your knowledge). The right thing to do is to first verify that a valid command was entered, then check if the appropriate file exists.
if [ $# != 2 ]; then
echo "Usage: test.sh <dbname> <test|live>" 2>&1
exit 1
fi
case $2 in
test|live)
filename="/tmp/my_{$2}.sql"
;;
*) echo "Must enter test or live"
exit 1
;;
esac
if [ -f "$filename" ]; then
/bin/sqlplus -s foo/bar #/my_$2.sql
else
echo "SQL script $filename does not exist."
exit 1
fi
My problem is to add a username to a file, I really stuck to proceed, please help.
Problem: I am having a file called usrgrp.dat. The format of this file is like:
ADMIN:srikanth,admin
DEV:dev1
TEST:test1
I am trying to write a shell script which should give me the output like:
Enter group name: DEV
Enter the username: dev2
My expected output is:
User added to Group DEV
If I see the contents of usrgrp.dat, it should now look like:
DEV:dev1,dev2
TEST:test1
And it should give me error saying user already present if I am trying to add already existing user in that group. I am trying this out with the following script:
#!/bin/sh
dispgrp()
{
groupf="/home/srikanth/scm/auths/group.dat"
for gname in `cat $groupf | cut -f1 -d:`
do
echo $gname
done
echo "Enter the group name:"
read grname
for gname in `cat $groupf | cut -f1 -d:`
do
if [ "$grname" = "$gname" ]
then
echo "Enter the username to be added"
read uname
for grname in `cat $groupf`
do
$gname="$gname:$uname"
exit 1
done
fi
done
}
echo "Group display"
dispgrp
I am stuck and need your valuable help.
#!/bin/sh
dispgrp()
{
groupf="/home/srikanth/scm/auths/group.dat"
tmpfile="/path/to/tmpfile"
# you may want to pipe this to more or less if the list may be long
cat "$groupf" | cut -f1 -d:
echo "Enter the group name:"
read grname
if grep "$grname" "$groupf" >/dev/null 2>&1
then
echo "Enter the username to be added"
read uname
if ! grep "^$grname:.*\<$uname\>" "$groupf" >/dev/null 2>&1
then
sed "/^$grname:/s/\$/,$uname/" "$groupf" > "$tmpfile" && mv "$tmpfile" "$groupf"
else
echo "User $uname already exists in group $grname"
return 1
fi
else
echo "Group not found"
return 1
fi
}
echo "Group display"
dispgrp
You don't need to use loops when the loops are done for you (e.g. cat, sed and grep).
Don't use for to iterate over the output of cat.
Don't use exit to return from a function. Use return.
A non-zero exit or return code signifies an error or failure. Use 0 for normal, successful return. This is the implicit action if you don't specify one.
Learn to use sed and grep.
Since your shebang says #!/bin/sh, the changes I made above are based on the Bourne shell and assume POSIX utilities (not GNU versions).
Something like (assume your shell is bash):
adduser() {
local grp="$1"
local user="$2"
local gfile="$3"
if ! grep -q "^$grp:" "$gfile"; then
echo "no such group: $grp"
return 1
fi
if grep -q "^$grp:.*\\<$user\\>" "$gfile"; then
echo "User $user already in group $grp"
else
sed -i "/^$grp:/s/\$/,$user/" "$gfile"
echo "User $user added to group $grp"
fi
}
read -p "Enter the group name: " grp
read -p "Enter the username to be added: " user
adduser "$grp" "$user" /home/srikanth/scm/auths/group.dat