Problem: I need to create a file where users and passwords are stored. But my script only saves the password of user1.
Example: I explain myself better with an example. When the two users are created with random password, my script assigns the same password on both users.
user1:Eehei5oo8ohz:/home/user1:/bin/bash
user2:Eehei5oo8ohz:/home/user2:/bin/bash
When the result of my script should be something like this:
user1:Eehei5oo8ohz:/home/user1:/bin/bash
user2:Kln2149sdpja:/home/user2:/bin/bash
My script: This is the script I have used:
#!/bin/bash
##Checking if you are root.##
if [ `id -u` -ne 0 ]
then
echo "you dont are a root user."
exit 1
fi
x=`pwgen 12 1`
for i in {1..2}
do
echo "user$i:#:/home/user$i:/bin/bash" >> users.txt
done
for j in $x
do
sed -i "s/#/$j/" users.txt
done
newusers users.txt
users=`cat users.txt`
login=`echo $i | cut -d: -f1` #username
pass=`cat pass.txt | tr " " _`
password1=`echo $i | cut -d: -f2` #password
for in $users
do
echo "$login:$password1" | chpasswd -m
done
rm users.txt
rm pass.txt
I hope I have explained correctly and appreciate all the help.
You could simplify your script and adapt it as follows (I'm referring to the first part only):
#!/bin/bash
# checking if you are root.##
if [ `id -u` -ne 0 ]
then
echo "you are not the root user!"
exit 1
fi
for i in {1..2}
do
x=`pwgen 12 1`
echo "user$i:$x:/home/user$i:/bin/bash" >> users.txt
done
This will create a file users.txt like the one bellow:
user1:ohng3uxohYi9:/home/user1:/bin/bash
user2:Gah5kiehaemi:/home/user2:/bin/bash
I see no point in creating a file with users and then replacing the # sign with a generated password since you can do that from the start!
You can simplify this script by getting rid of sed editing, eg change:
for i in {1..2}
do
echo "user$i:#:/home/user$i:/bin/bash" >> users.txt
done
for j in $x
do
sed -i "s/#/$j/" users.txt
done
to
pass=`cat pass.txt`
i=1
for pw in $pass
do
echo "user$i:$pw:/home/user$i:/bin/bash" >> users.txt
((i++))
done
This way you can get user numbers and passwords in one go and you are guaranteed to get as many usernames as passwords.
Related
I am on debian 9.
I have a problem to check the password of a linux user in my scripts. I realized that the different linux tools for creating and modifying a user password gave results of different pattern in /etc/shadow
To create a user
pwLinux="abcdef1234"
userLinux="toto02"
pwCrypt=$(perl -e 'print crypt($ARGV[0], "zzz")' $pwLinux)
useradd -m -G adm,dip,plugdev,www-data,sudo -p $pwCrypt $userLinux
I have in /etc/shadow
toto02:zzDxrNjXuUs3U:17469:0:99999:7:::
In another script I want check the password input by the user with
USERNAME="toto02"
PASSWD="abcdef1234"
ORIGPASS=`grep -w "$USERNAME" /etc/shadow | cut -d: -f2`
ORIGPASS=`echo $ORIGPASS | cut -d"$" -f2`
GENPASS=$(perl -e 'print crypt($ARGV[0], "zzz")' $PASSWD)
if [ "$GENPASS" == "$ORIGPASS" ]; then
echo "Valid Password"
exit 0
else
echo "Invalid Password"
exit 1
fi
it's ok
The trouble starts here: if I want to change passwords in a script I use
# username "toto02", newPwd "aabbcc"
echo "${username}:${newPwd}" | chpasswd
I can not use passwd because everything has to be done without interactivity.
I have in /etc/shadow
toto02:$6$rLklwx9K$Brv4lvNjR.S7f8i.Lmt8.iv8pgcbKhwDgINzhT1XwCBbD7XkB98lCtwUK3/4hdylkganoLuh/eIc38PtMArgZ/:17469:0:99999:7:::
If i want to check this password i must use a different script.
First problem how to have the same pattern of password in both cases?
i use:
#!/bin/bash
USERNAME="toto02"
PASSWD="aabbcc"
ORIGPASS=`grep -w "$USERNAME" /etc/shadow | cut -d: -f2`
export ALGO=`echo $ORIGPASS | cut -d"$" -f2`
export SALT=`echo $ORIGPASS | cut -d"$" -f3`
echo "algo: -$ALGO-"
echo "salt: -$SALT-"
echo "pwd entré: -$PASSWD-"
echo "shadow: -$ORIGPASS-"
GENPASS="$(perl -e 'print crypt("$ENV{PSWD}","\$$ENV{ALGO}\$$ENV{SALT}\$")')"
echo "pwd généré: -$GENPASS-"
if [ "$GENPASS" == "$ORIGPASS" ]; then
echo "Valid Password"
exit 0
else
echo "Invalid Password"
exit 1
fi
Which give:
algo: -6-
salt: -rLklwx9K-
pwd entré: -aabbcc-
shadow: -$6$rLklwx9K$Brv4lvNjR.S7f8i.Lmt8.iv8pgcbKhwDgINzhT1XwCBbD7XkB98lCtwUK3/4hdylkganoLuh/eIc38PtMArgZ/-
pwd généré: -$6$rLklwx9K$AIX1bUMAK9bwdd2g3ST5VtXTvHlHXHxnh4Xj.fLdxjaEkAAvHeeN5islid0wtmZN5u1zWQBup./IP8IH9i6W7/-
Invalid Password
The generated chain is different! why?
How to cure it ?
Thank you
Replace PSWD with PASSWD and replace PASSWD="aabbcc" with export PASSWD="aabbcc".
YES is good now
it's been hours that I'm on and I could not see anything!
#!/bin/bash
USERNAME=$1 # "toto02"
export PASSWD=$2 # "aabbcc"
ORIGPASS=`grep -w "$USERNAME" /etc/shadow | cut -d: -f2`
export ALGO=`echo $ORIGPASS | cut -d"$" -f2`
export SALT=`echo $ORIGPASS | cut -d"$" -f3`
echo "algo: -$ALGO-"
echo "salt: -$SALT-"
echo "pw entré: -$PASSWD-"
echo "shadow: -$ORIGPASS-"
GENPASS="$(perl -e 'print crypt("$ENV{PASSWD}","\$$ENV{ALGO}\$$ENV{SALT}\$")')"
echo "pass génére: -$GENPASS-"
if [ "$GENPASS" == "$ORIGPASS" ]; then
echo "Valid Password"
exit 0
else
echo "Invalid Password"
exit 1
fi
algo: -6-
salt: -rYc.lGtG-
pw entré: -aabbcc-
shadow: -$6$rYc.lGtG$wMHAM.nXHk1J5sDRmcHeBLW1sRQA/xQcjJSZxkls4BratyWf.KoQST14pPjNWDiUKwfegC96Lhjgjbj4YbZoc.-
pass génére: -$6$rYc.lGtG$wMHAM.nXHk1J5sDRmcHeBLW1sRQA/xQcjJSZxkls4BratyWf.KoQST14pPjNWDiUKwfegC96Lhjgjbj4YbZoc.-
Valid Password
Thank you very much, but is there a way to have the same type of password with useradd and chpasswd
I am trying to output which accounts have been successfully created from a text file and which haven't. I would also like to output the number of successfully created accounts. I currently the get the following error: grep: 3: No such file or directory. The script and text file and saved in the same folder. I have use the following commands in my script.
file=users.txt
verify =grep "verify" $file |cut -f2 -d:`
cat /etc/passwd | grep $verify
echo -e "\nYou have Currently"
cat /etc/passwd | grep $verify |wc -l;
echo "users added from your Text File"
Edit:
#!/bin/bash
ROOT_UID=0 #The root user has a UID of 0
if [ "$UID" -ne "$ROOT_UID" ]; then
echo "**** You must be the root user to run this script!****"
exit
fi
clear
echo
echo "######################################################"
echo "##### Batch script to automate creation of users #####"
echo -e "######################################################\n"
while true;
do
file=notvalid
while [ $file == "notvalid" ]
do
#echo "repeat $repeat"
#echo -e "\n"
echo -n "Please enter import filename:"
read filename
echo -e "\r"
exists=0
if [ -e $filename ]; then
file=valid
while IFS=":" read firstname lastname userid password group
do
egrep -i "^$userid:" /etc/passwd &>/dev/null
if [ $? -eq 0 ]; then
exists=$((exists+1))
#echo -e "${firstname} ${lastname} already exists on the system"
#grep ${userid} /etc/passwd
aname=$( getent passwd "$userid" | cut -d: -f3)
echo "Account Exists: $aname"
euserid=$( getent passwd "$userid" | cut -d: -f1)
echo "User ID: $userid"
homedir=$( getent passwd "$userid" | cut -d: -f6)
echo "Home Directory: $homedir"
usershell=$( getent passwd "$userid" | cut -d: -f7)
echo "User Shell: $usershell"
g=$( id -Gn "$userid")
echo "Groups: $g"
echo -e "\r"
else
egrep -i "^$group:" /etc/group &>/dev/null
if [ $? -eq 1 ]; then
/usr/sbin/addgroup ${group} &>/dev/null
fi
useradd -d /home/"${userid}" -m -s /bin/bash -c \
"${firstname}${lastname}" -g "${group}" "${userid}"
echo "Creating Account: ${firstname} ${lastname}"
nuserid=$( getent passwd "$userid" | cut -d: -f1)
echo "Creating User ID: ${nuserid}"
{ echo ${password}; echo ${password}; } | sudo passwd ${userid} > /dev/null 2>&1
echo "Creating Password: ${password}"
echo "Creating Home Directory: /home/${userid}"
echo "Creating User Shell: /bin/bash"
echo -e "Assigning Group: ${group}\n"
fi
done < $filename
else
echo -e "##### CANNOT FIND OR LOCATE FILE #####"
fi
verify=`grep "verify" /home/pi/$filename | cut -f3 -d:`
echo "$verify"
count=0
for id in $verify
do grep -wo ^$id /etc/passwd && count=$((count+1))
done
echo $count users added from your text file
echo these are not added:
for id in $verify
do grep -wq ^$id /etc/passwd || echo $id
done
while true
do
echo -n "Create additional accounts [y/n]: "
read opt
if [[ $opt == "n" || $opt == "y" ]];then
break
else
echo "Invalid Input"
fi
done
if [ $opt = "n" ]; then
clear
break
else
clear
fi
done
You were almost there.
The main issue with your approach is that you try to search for multiple accounts at once with grep. The variable verify has multiple userids so you need to process it one by one.
file=users.txt
verify=`grep "verify" $file | cut -f2 -d:`
count=0
for id in $verify
do grep -wo ^$id /etc/passwd && count=$((count+1))
done
echo $count users added from your text file
echo these are not added:
for id in $verify
do grep -wq ^$id /etc/passwd || echo $id
done
The for loop will take each element in your verify variable into id and search with grep (-w matches only whole words, not fragments, ^ matches the beginning of line and -o outputs only the matching word not the whole line).
We count the number of matches in the count variable. Alternative approach to run the for loop twice and pipe the second one to wc -l as you did.
&& operator means it will increase count if the previous command found a match (the return code of grep was 0).
The next loop will not print matching ids (-q), and will echo id if grep did not found a match (the return code was not 0). This is achieved with the || operator.
One last note on iteration of a list: if the members can contain spaces (unlike userids), you should use ${verify[#]} (this is a bash-ism) instead of $verify .
And forget this: cat /etc/passwd | grep pattern, use grep pattern /etc/passwd instead.
I want to pass my n number csv data into command "esusers useradd username -r role -p password". How can i perform this in linux machine. i Have done this window but unable to do in linux machine can anyone help me out of this. My input will contain header also.
csv file user.csv:
user1,role1,pass1
user2,role2,pass2
user3,role3,pass3
The bash script (scripts.sh) to iterate over the csv file:
#!/bin/bash
# Check parameters
if [ "$#" -ne 1 ]; then
>&2 echo "Illegal number of parameters"
exit 1
fi
# Check file
if [ ! -f "${1}" ]; then
>&2 echo "File ${1} not found"
exit 1
fi
FILE="${1}"
while read line; do
USER=`echo ${line} | cut -d"," -f1`
ROLE=`echo ${line} | cut -d"," -f2`
PASS=`echo ${line} | cut -d"," -f3`
echo "adding user ${USER} (role: ${ROLE}) with password: ${PASS}"
esusers useradd "${USER}" -r "${ROLE}" -p "${PASS}"
done < ${FILE}
Then, add execution mode to the script with chmod +x script.sh
and run the script with the csv file as parameter ./script.sh user.csv
$ ./script.sh user.csv
adding user user1 (role: role1) with password: pass1
adding user user2 (role: role2) with password: pass2
adding user user3 (role: role3) with password: pass3
I have a handy script here that can return accounts that will expire in 7 Days or have expired. I wanted to allow this to run on multiple hosts with out putting the script on each individual host, I added the for loop and the ssh $SERVER >> EOF part but it will just run the commands off they system that is running the script.
I believe the error is with ssh $SERVER >> EOF but I am unsure as the syntax looks correct.
#!/bin/bash
for SERVER in `cat /lists/testlist`
do
echo $SERVER
ssh $SERVER >> EOF
sudo cat /etc/shadow | cut -d: -f1,8 | sed /:$/d > /tmp/expirelist.txt
totalaccounts=`sudo cat /tmp/expirelist.txt | wc -l`
for((i=1; i<=$totalaccounts; i++ ))
do
tuserval=`sudo head -n $i /tmp/expirelist.txt | tail -n 1`
username=`sudo echo $tuserval | cut -f1 -d:`
userexp=`sudo echo $tuserval | cut -f2 -d:`
userexpireinseconds=$(( $userexp * 86400 ))
todaystime=`date +"%s"`
if [[ $userexpireinseconds -ge $todaystime ]] ;
then
timeto7days=$(( $todaystime + 604800 ))
if [[ $userexpireinseconds -le $timeto7days ]];
then
echo $username "is going to expire in 7 Days"
fi
else
echo $username "account has expired"
fi
done
sudo rm /tmp/expirelist.txt
EOF
done
Here documents are started by << EOF (or, better, << 'EOF' to prevent the body of the here document being expanded by the (local) shell) and the end marker must be in column 1.
What you're doing is running ssh and appending standard output to a file EOF (>> is an output redirection; << is an input redirection). It is then (locally) running sudo, etc. It probably fails to execute the local file EOF (not executable, one hopes), and likely doesn't find any other command for that either.
I think what you're after is this (where I've now replaced the back-ticks in the script with $(...) notation, and marginally optimized the server list generation for use with Bash):
#!/bin/bash
for SERVER in $(</lists/testlist)
do
echo $SERVER
ssh $SERVER << 'EOF'
sudo cat /etc/shadow | cut -d: -f1,8 | sed '/:$/d' > /tmp/expirelist.txt
totalaccounts=$(sudo cat /tmp/expirelist.txt | wc -l)
for ((i=1; i<=$totalaccounts; i++))
do
tuserval=$(sudo head -n $i /tmp/expirelist.txt | tail -n 1)
username=$(sudo echo $tuserval | cut -f1 -d:)
userexp=$(sudo echo $tuserval | cut -f2 -d:)
userexpireinseconds=$(( $userexp * 86400 ))
todaystime=$(date +"%s")
if [[ $userexpireinseconds -ge $todaystime ]]
then
timeto7days=$(( $todaystime + 604800 ))
if [[ $userexpireinseconds -le $timeto7days ]]
then
echo $username "is going to expire in 7 Days"
fi
else
echo $username "account has expired"
fi
done
sudo rm /tmp/expirelist.txt
EOF
done
Very close, but the differences really matter! Note, in particular, that the end marker EOF is in column 1 and not indented at all.
I am a newbie to linux scripting and I am getting an unexpected error. I have made a script which takes into account two options 1 and 2. I am having issues with option 2 I want to extract the usernames from a text file and add all of the users except the EOF to the home directory like this:
Try this for parsing your input file:
if [ -e $Path ]
then
while read user
do
[[ $user = \#* ]] && continue
Username=`echo $user | cut -f2 -d:`
if [ "$Username" != "EOF" ]
then
echo $Username
fi
done < $Path
fi