I've a simple linux script (made by my friend), which adds users to the system from userlist file. it also creates user home dir and copies certain files to the directory. To be honest, am a newbie in scripting so am unable to fully understand how the script is working. unfortunately, my friend is out of town so i cant get any help from him as of now. Thats why i posted it here. I hope someone from this forum could help me out on it. Code link :
#!/bin/sh
#set -x
################### Method to Create a User ########################
createUser() {
for w in `cat $1`;
do
export user=$(printf '%s\n' "$w";)
useradd -d $4$user -m $user -p $(perl -e 'print
crypt("password", "password")') > /dev/null
if [[ $? -ne 0 ]]; then
echo "User $user you are trying to add already exists."
echo "Exiting..."
exit 1;
fi
echo "$user added with home_directory $4$user and
default password: password"
echo "Copying files..."
copyFiles $1 $2 $3 $4
done
return 0;
}
################### Create User Ends ################################
################## Copying User Files ##############################
copyFiles() {
cd $4$user
old=_old
if [[ $? -eq 0 ]]; then
echo "file for $4$user already exists !"
echo "Do you want to overwrite the file (y/n):\c"
read answer
if [[ $answer -eq y || $answer -eq Y ]]; then
mv $4$user $4$user$old > /dev/null
mkdir /$4/$user > /dev/null
for i in `cat $2`
do
cp $3$i $4$user > /dev/null
done
elif [[ $answer -eq n || $answer -eq N ]]; then
for i in `cat $2`
do
cp $3$i $4$user > /dev/null
done
fi
chmod 700 $4$user /dev/null
fi
}
################# Copying User Files Ends ###########################
################################### Main ##############################
clear
# check command line arguments count
if [[ $# -lt 4 ]] ; then
echo "Command line arguments are need to run the script"
echo "Usage: <Script Name> path_to_username_list
files_list_path master_copies_path users_home_folder_path"
echo "Exiting..."
exit 1;
fi
# validate command line arguments
wd=$(pwd)
if [[ $# -ne 0 ]]; then
ls $1 > /dev/null
if [[ $? -ne 0 ]]; then
echo "Error: Path to username list doesnt
exist, Please provide correct path"
echo "Exiting..."
exit 1;
fi
ls $2 > /dev/null
if [[ $? -ne 0 ]]; then
echo "Error: Path to file listing file names
to be copied doesnot exist"
echo "Exiting..."
exit 1;
fi
ls $3 > /dev/null
if [[ $? -ne 0 ]]; then
echo "Error: Path to the master copies doestnot exist"
echo "Exiting..."
exit 1;
fi
fi
for i in `cat $2`
do
ls /$3/$i > /dev/null
if [[ $? -ne 0 ]]; then
echo "file $i doesnt exist in $3"
echo "Exiting..."
exit 1;
fi
done
cd $wd > /dev/null
# Calling user creation method
createUser $1 $2 $3 $4
############################# Main Ends ###############################
Arguments
1. complete path to the file listing the names of the user, eg:
/home/userlist where userlist is the filename
2. complete path to the file listing the names of the files to be
copied, eg: /root/filelistdir/filelist where filelist is the name of
the file containing filenames.
3. Complete path to the folder where the files are present, eg: /root/filelistdir/
4. Complete path where the users home path needs to be created.
I have understood most if the script now but got a doubt in this section :
if [[ $answer -eq y || $answer -eq Y ]]; then
mv $4$user $4$user$old > /dev/null
mkdir /$4/$user > /dev/null
for i in `cat $2`
do
cp $3$i $4$user > /dev/null
done
elif [[ $answer -eq n || $answer -eq N ]]; then
for i in `cat $2`
do
cp $3$i $4$user > /dev/null
done
fi
Here the script reads from the input and if the answer is yes, then it moves old files to a dir $user_old then creates new home dir and copies master files there.
But i dont understand the elseif section, here if the answer is NO, then it should just leave and start loop again for 2nd user in the userlist. but instead it copies the files again. which we dont want to do.
So i guess the loop in elseif section is not needed here and should be removed. right? if not, please clarify why?
That depends on what the question is. Were it "save old user files before copying (instead of overwrite)", then copying should occur in either case. But then still the elif were too many - put the for loop outside/after the if branch.
theres one more problem in the script, whenever we run the script it says "file for user already exists", even if the user is being created for the 1st time. I think the problem is here :
copyFiles() {
cd $4$user
old=_old
if [[ $? -eq 0 ]]; then
echo "file for $4$user already exists !"
echo "Do you want to overwrite the file (y/n):\c"
read answer
here it checks if return code is equal to 0, if yes then shows that error. but how can it get a return code as 0, if the dir is not there? i tried to resolve this error but couldnt do it. would appreciate any help here..
Pls post execution log (set -vx) with err msg.
On first sight, you may try double quotes if [[ "$?" -eq "0" ]] . Secondly, you may want to save $? to a variable and echo it for reference.
AND, on third sight, you are testing $? from the assignment old=_old which succeeded and thus $? is 0. So - go with the second proposal, use a variable.
---------- Post updated at 09:25 PM ---------- Previous update was at 09:09 PM ----------
i think the return code is 0 because we're creating the home dir in the createUser() function. here :
createUser() {
for w in `cat $1`;
do
export user=$(printf '%s\n' "$w";)
useradd -d $4$user -m $user -p $(perl -e 'print
crypt("password", "password")') > /dev/null
here we're using "useradd -m" to create a home dir for the given user. which in turn gives the return code as 0.
did i get it correct? or if am wrong, then how to modify the code to resolve the error as well as to fulfill the purpose of script?
Again, output the $? after the cd command and after the assignment.
And, I'm pretty sure, the user directory will be created in useradd . So you need to check not for presence of dir, but for non-/ emptiness.
Pls post logs as text files, not screen shot images.
So, as the directory exists, you want to check if it's empty. After successfully cd ing to /neha , try sth like ls|wc -w . If that supplies anything different from 0 , the dir is not empty and you should ask for overwrite.
Fine - but here we don't need the exit code, but the word count itself - i.e. the no. of files in dir:
CNT=$(ls|wc -w)
# echo code=$? <---- DON'T do this - see comment below!
if [[ "$CNT" -gt "0" ]]; then #CNT is greater than zero - files exist - ask for overwrite!
.
.
.
fi
DON'T execute any command before evaluating the exit code - it will contain the last command's status, in the case above echo's status, which is almost always 0, rendering $? useless for your purposes. Save exit codes into e variable immediately for later evaluation!
Can't tell why - but the entire logics of your function needs some polishing. Step back and start from scratch - where do you come from? What do you want to achieve? E.g. there's four options - copy into empty dir, overwrite with or without saving old files, or don't copy at all. Try to sketch that on a paper slip and then start over coding. Setting the shell's -vx options helps troubleshooting as it prints out what the shell does.
ok first problem is solved after implementing your solution. the script now checks if files are already present, if yes then asks to overwrite, if not then copies new files to dir. however if answered NOT TO overwrite, it doesnt create $user_old folder, instead overwrites files anyway.
This is the code :
copyFiles() {
cd $4$user
old=_old
ls|wc -w
CNT=$(ls|wc -w)
if [[ $CNT -gt 0 ]]; then
echo "file for $4$user already exists!"
echo "Do you want to overwrite the file (y/n):"
read answer
if [[ $answer -eq y || $answer -eq Y ]]; then
for i in `cat $2`
do
cp $3$i $4$user > /dev/null
done
elif [[ $answer -eq n || $answer -eq N ]]; then
mv $4$user $4$user$old > /dev/null
mkdir /$4/$user > /dev/null
for i in `cat $2`
do
cp $3$i $4$user > /dev/null
done
fi
else
for i in `cat $2`
do
cp $3$i $4$user > /dev/null
done
chmod 700 $4$user /dev/null
fi
}
First, you should delete all the > /dev/null
and especially the /dev/null behind the chmod 700 $4$user ! This will spoil the permissions on /dev/null device,
please restore with
chmod 666 /dev/null
Then, it's more consequent to have mkdir $4$user
followed by additional commands chmod 700 $4$user and cd $4$user
copyFiles() {
cd $4$user
old=_old
# ls|wc -w <--- remove, not needed
CNT=$(ls|wc -w)
if [[ "$CNT" -gt "0" ]]; then <--- double quotes never/rarely hurt
echo "file for $4$user already exists!"
echo "Do you want to overwrite the file (y/n):"
read answer
if [ "${answer^?}" == "N" ]; then <--- make $answer upper case by parameter case modification, use string comparison operator, and double quotes ...
# for i in `cat $2` <--- remove, will be done later
# do
# cp $3$i $4$user > /dev/null
# done
# elif [[ $answer -eq n || $answer -eq N ]]; then <--- remove, unneccessary
set -vx <--- show shell's activities on variables
mv $4$user $4$user$old > /dev/null <---+ pls remove /dev/null to show what's going on
mkdir /$4/$user > /dev/null <---+
# for i in `cat $2` <--- same as above
# do
# cp $3$i $4$user > /dev/null
# done
fi # answer = "N"
# else
for i in $2 <--- cat not required!
do
cp $3$i $4$user > /dev/null <--- NOW you copy! And remove redirection...
done
chmod 700 $4$user /dev/null <--- not the wisest thing to do...
# fi
}
Not sure I caught every single stumbling block, but seems a good starting point to me...
There are several traps, e.g. file owner and permissions.
The following is simpler and should be safer:
copyFiles() {
old=_old
cd $4$user
if [ $? -eq 0 ]; then
echo "$4$user already exists !"
printf "%s" "Do you want to overwrite the initial files (y/n):"
read answer
if [ "$answer" = "y" -o "$answer" = "Y" ]; then
for i in `cat $2`
do
if [ -e $4$user$i ]; then
echo "backing up to $4$user$i$old"
mv $4$user$i $4$user$i$old &&
cp -p $4$user$i$old $4$user$i
# copied back to restore attributes and to ensure it's a plain file
fi
cp $3$i $4$user
done
fi
chmod 700 $4$user
fi
}
following this script, if answer is yes, the files are being copied to user dir but if said "No" then no files are being copied or backed up. and no user_old folders are created.