username=$1
freq=$2
checkuser()
{
if who grep "$1"
then
sleep 60
fi
}
if [ -n "$1" ]
then
echo "Enter username"
read username
checkuser
echo -e "$1 is logged on \a"
echo -e "$1 logged in at `date`">>LOG
checkuser
else
echo "User is not logged on"
fi
I need to integrate a second argument into my code which allows for the user to specify after what time should the script check to see who is logged in. I have it set to 60 seconds currently and this needs to be the default frequency. I tried to use another function but to no avail. I thought of something like this...
if [ "$2" -ne 0 ]
then
freq=$2
else
freq=60
Thanks William for that was very helpful!! I changed the code a bit and came up with this. I now need to add a 3rd argument "X" which when selected just sends a message to the LOGFILE and not to the screen. I made an attempt but not doing as intended.
username=$1
freq=${2:-10}
X=$3
checkuser()
{
whoami|grep "$1";
}
while checkuser "$username"
do
echo -e "$1 is logged on \a"
echo "$1 logged in at `date`">>LOGFILE
sleep $freq
exit 0
done
echo "User is not logged in"
if [ "$3" -ne 1 ]
then
echo "$1 logged in at `date`"LOGFILE
fi
username=$1
freq=${2:-60} # Set a default frequency
checkuser(){ who | grep -q "$1"; }
while ! checkuser "$username"; do
echo "User is not logged on"
sleep $freq
done
echo "$1 is logged on"
Also note that you can simplify the setting of username:
username=${1:-$( echo "Enter username: "; read u; echo $u; )}
echo 'Enter id'
read id
res=`who | grep "$id" | wc -l`
if [ $res -eq 0 ]
then
echo 'user is not logged in'
else
echo 'user is logged in'
fi
A simple shell script that takes the username as input and determines whether the user is currently logged in.
if [[ $# -eq 0 ]]; then
echo "Usage: " $0 "username"
exit 1
fi
result="$(who | grep $1 | wc -l)"
if [[ $result -gt 0 ]]; then
echo "$1 is currently logged in"
else
echo "$1 is not logged in"
fi
exit 0
Related
I'm trying to make a while loop.
This loop should either echo "try again or type exit to quit" when typing gibberish or finger a user if typed the user name.
echo Please enter a user name to find.
read username
done_fn()
{
finger $username
exit 0
}
continue_fn()
{
echo 'try again or type exit to quit'
read exitvar
}
grep $username /etc/passwd >/dev/null
while [ $? -eq 0 ]
do
done_fn
done
exitvar=quit
until [ $exitvar = exit ]
do
continue_fn
done
while [ -u $exitvar ]
do
done_fn
done
This is everything I have got so far. Whenever I I type in a username after 'try again or type exit to quit' it will just echo it again. I would like it to finger the user instead of echoing it again. I have looked in so many places and can't find the answer.
Thank you in advance.
You can try this:
typeset u="John Doe"
while ! grep -q "^$u:" /etc/passwd
do
echo -n "username? "
read u
if [[ $u = "q" ]]
then
exit
fi
done
finger $u
echo Please enter a user name to find.
read username
donev2_fn()
{
finger $exitvar
exit 0
}
done_fn()
{
finger $username
exit 0
}
continue_fn()
{
echo 'try again or type exit to quit'
read exitvar
grep $exitvar /etc/passwd >/dev/null
if [ $? -eq 0 ]
then
donev2_fn
fi
}
grep $username /etc/passwd >/dev/null
while [ $? -eq 0 ]
do
done_fn
done
exitvar=quit
until [ $exitvar = exit ]
do
continue_fn
done
I figured it out. I had to put an extra function in it. Thank you for all the help.
I have a bash script that asks the user for their details.
I'm setting a limit to how long we wait for the input. I've found this and it appears to what I want.
timelimit=5
echo -e " You have $timelimit seconds\n Enter your name quickly: \c"
name=""
read -t $timelimit name
#read -t $timelimit name <&1
# for bash versions bellow 3.x
if [ ! -z "$name" ]
then
echo -e "\n Your name is $name"
else
echo -e "\n TIME OUT\n You failed to enter your name"
fi
It shows "You have 5 seconds..." any way to update the output so it shows 4,3,2,1 etc as it counts down ?
Thanks
I have tried most of these answers and none of them worked perfectly for me.
Been playing with this for a local developer deployment script.
This solves a few of the issues noted, like including printed output, etc.
Also wrapped as a function for portability. I'm keen to see any improvements.
Here is my solution:
#!/bin/bash
# set -euo pipefail
READTIMEOUT=5
function read_yn {
MESSAGE=$1
TIMEOUTREPLY=$2
NORMALREPLY="Y"
if [ -z "${TIMEOUTREPLY}" ]; then
TIMEOUTREPLY="Y"
fi
TIMEOUTREPLY_UC=$( echo $TIMEOUTREPLY | awk '{print toupper($0)}' )
TIMEOUTREPLY_LC=$( echo $TIMEOUTREPLY | awk '{print tolower($0)}' )
if [ "${TIMEOUTREPLY_UC}" == "Y" ]; then
NORMALREPLY="N"
fi
NORMALREPLY_UC=$( echo $NORMALREPLY | awk '{print toupper($0)}' )
NORMALREPLY_LC=$( echo $NORMALREPLY | awk '{print tolower($0)}' )
for (( i=$READTIMEOUT; i>=0; i--)); do
printf "\r${MESSAGE} [${NORMALREPLY_UC}${NORMALREPLY_LC}/${TIMEOUTREPLY_UC}${TIMEOUTREPLY_LC}] ('${TIMEOUTREPLY_UC}' in ${i}s) "
read -s -n 1 -t 1 waitreadyn
if [ $? -eq 0 ]
then
break
fi
done
yn=""
if [ -z $waitreadyn ]; then
echo -e "\nNo input entered: Defaulting to '${TIMEOUTREPLY_UC}'"
yn="${TIMEOUTREPLY_UC}"
else
echo -e "\n${waitreadyn}"
yn="${waitreadyn}"
fi
}
read_yn "TESTING" "y"
GIST: https://gist.github.com/djravine/7a66478c37974940e8c39764d59d35fa
LIVE DEMO: https://repl.it/#DJRavine/read-input-with-visible-countdownsh
This should work and shouldn't overwrite input, bit more long winded than the other solutions.
#!/bin/bash
abend()
{
stty sane
exit
#Resets stty and then exits script
}
DoAction(){
stty -echo
#Turn off echo
tput sc
#Save cursor position
echo -ne "\033[0K\r"
# Remove previous line
tput cuu1
#Go to previous line
tput el
#clear to end of line
echo "You have $(($time-$count)) seconds"
#Echo timer
echo -n "$Keys"
#Echo currently typed text
stty echo
#turn echo on
tput rc
#return cursor
}
main()
{
trap abend SIGINT # Trap ctrl-c to return terminal to normal
stty -icanon time 0 min 0 -echo
#turn of echo and set read time to nothing
keypress=''
time=5
echo "You have $time seconds"
while Keys=$Keys$keypress; do
sleep 0.05
read keypress && break
((clock = clock + 1 ))
if [[ clock -eq 20 ]];then
((count++))
clock=0
DoAction $Keys
fi
[[ $count -eq $time ]] && echo "you have run out of time" && abend
done
stty sane
echo Your username was $Keys
echo "Thanks for using this script."
exit 0
}
main
This seems to work:
$ cat test.sh
total=5 # total wait time in seconds
count=0 # counter
while [ ${count} -lt ${total} ] ; do
tlimit=$(( $total - $count ))
echo -e "\rYou have ${tlimit} seconds to enter your name: \c"
read -t 1 name
test ! -z "$name" && { break ; }
count=$((count+1))
done
if [ ! -z "$name" ] ; then
echo -e "\nyour name is $name"
else
echo -e "\ntime out"
fi
#!/bin/bash
timelimit=6
name=""
for (( i = 1 ; i <= $timelimit; i++ )); do
echo -ne "\rYou have $(expr $timelimit - $i) seconds. Enter your name quickly: \c"
[ ! -z "$name" ] && { break ; }
read -t 1 name
done
if [ -z "$name" ]; then
echo -e "\n TIME OUT\n You failed to enter your name"
else
echo -e "\n Your name is $name"
fi
this should work
This works fine and fast for me:
#!/bin/bash
#Sets starttimestamp
starttime=$(date +%s)
#Sets timeout
timeout=5
#sets successflag default to false
success=false
#Save Cursorposition
echo -n -e "\033[s"
#While time not up
while [ $(($starttime+$timeout)) -gt $(date +%s) ] ; do
#Return to saved Cursorpositon
echo -n -e "\033[u"
#Display time left
echo "$(((starttime+timeout)-$(date +%s))) seconds left"
#Ask for 1 char then go on in loop make it look like an ongoing input by adding the user variable to the prompt
if read -p foo="Username: $user" -n 1 -t 1 c ; then
#If user hits return in time c will be empty then break out of loop and set success true
if [[ $c == "" ]] ; then
success=true
break
fi
# Append latest character to user variable
user=${user}${c}
unset c
fi
done
if $success ; then
echo "Yiha!"
else
echo "Too late!"
fi
I have been trying to implement a code that makes a predefined user created, be put into a specific groups (first 5 in MyMembers, next 5 in MyGroup, and last 5 to MyMinions), but I always got lost in coding it.
So far this is my code in creating predefined user.
#!/bin/bash
#This script adds a user with a hidden password to your #system.
ans=yes
while [[ "$ans" = yes ]] ;
do
if [ $(id -u) -eq 0 ];
then
read -p "Enter username: " username
read -s -p "Enter password: " password
egrep "^$username" /etc/passwd >/dev/null
if [ $? -eq 0 ];
then
echo "$username already exists!"
exit 1
else
pass=$(perl -e 'print crypt ($ARGV[0], "password")' $password)
useradd -m -p $pass $username
[ $? -eq 0 ] && echo -e "\nUser has been added to your system!" || echo "\nFailed to add the user!"
fi
else
echo "Only root may add a user to the system"
exit 2
fi
echo -e "\nDo you still want to add more users?. \nType yes to continue adding. \nType yes or any key to exit"
read ans
done
exit
while true
do
if($update)
then
who | awk {'print$1'} > first_user_list #store original user list
update=false
fi
who | awk {'print$1'} > updated_user_list
(diff first_user_list updated_user_list) | cut -c 3- > in_out_list
inOutVar='cat in_out_list' #<----here's my problem
length_first=$(wc -l < updated_user_list)
length_update=$(wc -l < first_user_list)
if [[ "$length_first" -lt "$length_update" ]]; then
echo -e "$inOutVar" " has logged out"
update=true
elif [ "$length_first" -gt "$length_update" ]; then
echo -e "$inOutVar" " has logged in"
update=true
else
echo No user has logged in/out in the last 3 seconds
fi
sleep 3
done
How would i go by printing out the users names who has logged out then " has logged out"
eg.
"johnsmith has logged out"
Pretty new to unix, any help or suggestions would be great, thanks in advance :)x
Your issue is that you used quotes instead of backticks. Since you are setting the variable equal to a command you need to use `` or $():
#!/bin/sh
while true; do
if($update)
then
who | awk {'print$1'} > first_user_list #store original user list
update=false
fi
who | awk {'print$1'} > updated_user_list
(diff first_user_list updated_user_list) | cut -c 3- > in_out_list
inOutVar=`cat in_out_list` ## use `` or $(), not ''
length_first=$(wc -l < updated_user_list)
length_update=$(wc -l < first_user_list)
if [[ "$length_first" -lt "$length_update" ]]; then
echo -e "$inOutVar" " has logged out"
update=true
elif [ "$length_first" -gt "$length_update" ]; then
echo -e "$inOutVar" " has logged in"
update=true
else
echo No user has logged in/out in the last 3 seconds
fi
sleep 3
That works on my system.
In order to simplicate the process of creating a new user in my company's NIS server, I wrote the following scripts:
#!/bin/bash
# This script will simplicate NIS user management.
# You will not be able to change password or delete users peeradmin and root through this script.
# Written by Itai Ganot 2014.
# Variables
USER=$1
GREP="/bin/grep"
PASSWDFILE="/etc/passwd"
YPPASSWD="/usr/bin/yppasswd"
USERDEL="/usr/sbin/userdel"
USERADD="/usr/sbin/useradd"
PASSWD="/usr/bin/passwd"
YPCAT="/usr/bin/ypcat passwd.byname"
# Functions
function usage {
echo -e "Usage: $0 <username to manage>"
}
function updatenis {
echo -e "\e[36m #===# Uptdating NIS database... \e[0m"
cd /var/yp && make
}
# Script
if [ -z "$USER" ]; then
usage
exit 1
fi
if [ "$(id -u)" != "0" ]; then
echo -e "Run as root!"
exit 1
fi
"$GREP" -q "$USER" "$PASSWDFILE"
if [ "$?" = "0" ]; then
echo -e "\e[36m #===# User already exists \e[0m"
echo -e "\e[36m #===# How would you like to continue? \e[0m"
USERID=$(id -u $USER)
select CHOICE in 'Change user password' 'Remove user' 'View user' 'Exit'; do
case $CHOICE in
"Change user password")
if [[ "$USER" = "peeradmin" || "$USER" = "root" ]]; then # Defense against changing root or peeradmin password
echo -e "\e[36m #===# User $USER should never be edited! \e[0m"
exit 1
fi
echo -e "\e[36m #===# Provide root password for NIS server... \e[0m"
"$YPPASSWD" "$USER"
break
;;
"Remove user")
if [[ "$USER" = "peeradmin" || "$USER" = "root" ]]; then # Defense against deletion of user root or peeradmin.
echo -e "\e[36m #===# User $USER should never be edited! \e[0m"
exit 1
fi
read -r -p "Remove home directory and mail? [y/n] " ANSWER1
if [[ "$ANSWER1" = [Yy] ]]; then
"$USERDEL" -r "$USER"
updatenis
echo -e "\e[36m #===# User $USER has been deleted along with the user's home folder and mail \e[0m"
break
else
"$USERDEL" "$USER"
echo -e "\e[36m #===# User $USER has been deleted \e[0m"
updatenis
break
fi
;;
"View user")
echo -e "\e[36m #===# Displaying user $USER \e[0m"
$YPCAT | $GREP "$USER"
break
;;
"Exit")
echo -e "\e[36m #===# Exiting, No changes done. \e[0m"
exit 0
;;
esac
done
else
read -r -p "User doesn't exist, would you like to add it? [y/n] " ANSWER2
if [[ "$ANSWER2" = [Yy] ]]; then
echo -e "\e[36m #===# Collecting required information... \e[0m"
sleep 2
LASTUID=$(tail -n 1 $PASSWDFILE | awk -F: '{print $3}')
NEXTUID=$(( LASTUID + 1 ))
$USERADD -g users $USER -u $NEXTUID
echo -e "\e[36m #===# Set password for the new user \e[0m"
$PASSWD $USER
updatenis
read -r -p "Would you like to test the creation of the user? [y/n] " ANSWER3
if [[ "$ANSWER3" = [Yy] ]]; then
$YPCAT | $GREP "$USER"
if [ "$?" = "0" ]; then
echo -e "\e[36m #===# User $USER created successfully! \e[0m"
fi
fi
elif [[ "$ANSWER2" = [Nn] ]]; then
echo -e "\e[36m #===# Exiting, no changes done. \e[0m"
exit 0
fi
fi
I want to make the script public so I'll be able to share it with some communities, however I'm having a hard time to get some specific thing done.
I want to define a new variable called: PROTECTEDUSERS and assign one or more usernames to it.
Example:
PROTECTEDUSERS="root peeradmin"
Then, In the relevant line:
if [[ "$USER" = "peeradmin" || "$USER" = "root" ]];
I want the line to include the newly created variable.
I've tried this:
if [[ "*$USER*" =~ "$PROTECTEDUSERS" ]]; then...
But it doesn't work, is that even a possible thing to do? I believe it is just don't know how to do it, please assist.
Thanks in advance
if [[ "$PROTECTEDUSERS" =~ $USER ]]; then
Update to not match substings like "admin":
if [[ "$PROTECTEDUSERS" =~ (^| )$USER($| ) ]]; then
You are using glob in reverse direction, use this condition with == in bash:
if [[ "$PROTECTEDUSERS" == *"$USER"* ]]; then...
glob pattern is only supported on RHS of comparison.