Take user name as input: if user is logged in, display running processes belonging to the user
Solution 1
You can use the who -u
command to list the users who are logged in.
Then you could use grep
to look for a specific user in the output,
and exit with success if found, or exit with failure otherwise.
#!/bin/bash
read -p 'Enter username to check: ' user
if who -u | grep -q "^$user "; then
top -u "$user"
else
echo "User $user is not logged in"
fi
(Thanks to @dessert for shortening the who -u | ...
part!)
Solution 2
To me it looks like you have misunderstood the task a little. I guess the script is something a sysadmin would use to check on users, so "Who are you?", and checking that the user running the script has entered their own username (which is what your script tries to do) is not what you are supposed to do!
I think janos' answer and dessert's answer do exactly what you want, and I don't have a better answer. But here are some tips to debug your script...
test
aka [
You used [
which is a shell builtin. You can see some information about it by running help [
, but as that info tells you, it is a version of the test
command, and more information can be found under help test
. When I run your script (which I named script
) I get these errors:
script: line 6: if[zanna == zanna]: command not found
script: line 7: syntax error near unexpected token `then'
script: line 7: `then'
you needed three spaces to separate the if
and [
commands from their arguments. Also, as Sergiy pointed out in a comment, until Bash version 4.4, the ==
operator did not exist in test
or [
. Ubuntu 16.04 is using Bash 4.3. I have Bash 4.4 in 17.10. You can correct the syntax error like this:
if [ "$user" = "$name" ]
You could also have avoided assigning an extra variable by making that test
if [ "$user" = "$(whoami)" ]
but brevity does not always yield clarity, especially in shell scripts, and besides, this isn't what you really want to do, because the user running the script has to be logged in to run a script, so even the syntactically correct version of your script would only be checking that the user typed their username correctly, which isn't what the task asks for.
read
read
is a Bash builtin command. You can get information on it by running help read
.
When you use the read
command, you probably want to use the -r
option to prevent any backslashes in the input from acting as escapes.
Also, rather than echo
ing the user prompt, you can use read
's -p
option and write the prompt after -p
for a more concise script.
echo "Who are we checking on? "
read -r user
does the same as
read -rp "Who are we checking on? " user
You also don't strictly need to name the variable, since read
puts the input into a variable REPLY
automatically. You can test this:
read -rp "Who are we checking on? "
echo "$REPLY"
Of course, you often want to name the variable. I think user
was a good choice for this one.
if
if
is also a shell builtin, so you can find out about it by running help if
. You'll see that it checks the command after it and executes the then
branch if the exit status of that command was zero (ie it was successful). janos' answer uses if
without test
or [
by simply collecting the exit status of grep
:
who -u | grep -q "^$user "
searches the output of who -u
to see if any line starts with the value of the $user
variable. ^
is start of line, and the -q
option suppresses output. grep
's exit status is zero if it finds a match, so if $user
is found, the then
branch of the if
structure will be executed, but if grep
fails to find anything, the else
branch of the if
structure will be executed (if it exists).
dessert's answer uses only the shell's logic to define actions for success and failure of a command - even if
is not necessary here :)
test
again
Since checking exit status suffices, I don't think you need the [
or test
command at all. If you really want to use it, you could use something like
[ -n "$(w -h | grep "^$user ")" ]
The whole command substitution must be quoted or [
will complain of too many arguments if there are multiple words in the output (since $user
will be one word, we could also use grep -o
to output only the match). -n
is true if the string is not empty.
An alternative to who -u
is w -h
. I'm not sure which is more portable or reliable. I've noticed that who
gives slightly different output in different terminal emulators, although not different enough to stop this script from working.
Quoting
Most of the time, you want to quote variables in scripts to prevent further expansions. The utilities you use to create users on Ubuntu will not allow you to create a username with spaces or any other characters that could cause the shell to perform an expansion, so I don't think it's strictly essential to quote the variable in this script. Still, it's possible for such usernames to exist, and it a good habit to quote variables that don't need to be unquoted.
For completeness, here is my version without [
(it's essentially the same as janos'):
#!/bin/bash
read -rp "Who are we checking on? "
if w -h | grep -q "^$REPLY "; then
echo "here's what "$REPLY" is doing:"
top -u "$REPLY"
else
echo "looks like "$REPLY" is not logged in."
fi
Solution 3
What you're asking for can actually be done with a oneliner:
read -p"Who are you? " u&&((who -u|grep -q "^$u "&&top -u"$u")||echo "$u is not logged in")
But as you requested a script, here's the much nicer script version:
#!/bin/bash
read -p "Who are you? " user && (( # prompt for username, save as $user
who -u | grep -q "^$user " && # test if user is logged in
top -u "$user" ) || # run top with that username
echo "$user is not logged in" ) # error message
Explanations
-
read -p "Who are you? " user
– prompt for the username and save it as variableuser
-
&&
– if that's successful, … -
(…)
– start a subshell and do…
in it – if you don't want to start a subshell you can use{ …;}
instead, the space as well as the semicolon are mandatory -
who -u | grep -q "^$user "
– callwho
andgrep
for the username at the beginning of the line (^
) with a preceding space (so thatdes
doesn't matchdessert
) -
top -u "$user"
– run top with the username -
||
– if that's not successful, i.e. if the user is not logged in -
echo "$u is not logged in"
– print error message
NB: This can very well also be done with an if
expression as shown in the other answers. I stuck to logical operators and brackets here because that's another way of doing it and I wanted to show how.
Related videos on Youtube
rumana khanom
Updated on September 18, 2022Comments
-
rumana khanom over 1 year
I want to write a script that takes the name of a user as command line input. If that user is logged in then it will display the processes the user is running. If he/she is not logged in, then the script should mention this.
My attempt is not working:
#!/bin/bash echo "Who are you?" read user echo $user name=$(whoami) if[$user == $name] then top -u $user else echo "not logged in" fi
-
goo over 6 yearsRun your script with
bash -x
, "who the user is" is already provided in the$USER
environment variable. -
dessert over 6 yearsYou are checking whether the user is the same as the one who runs the script, not whether he is logged in. How about
top -u $user || echo "$user is not logged in"
? This would save you the wholeif
expression… -
dessert over 6 yearsBy the way: Always quote variables with input you got from a user!
-
-
janos over 6 years@Zanna I meant to delete that line from the original script, and keep only the
read -p
I added. Thanks for spotting it! -
Sergiy Kolodyazhnyy over 6 yearsCouple things:
test
doesn't have==
operator, that's only in[[
or arithmetic compound command((...))
, and arithmetic expansion$((...))
. Be careful withgrep "^$user"
as this doesn't account for usernames likejdoe
andjdoe1
, so that may lead to flags. Good answer, I like it. -
Zanna over 6 years@SergiyKolodyazhnyy I've found out why it worked for me - the
==
operator was added totest
in Bash 4.4 (which I have on 17.10)! -
Sergiy Kolodyazhnyy over 6 yearsGood find ! This also means one more incompatibility between
/bin/sh
and/bin/bash
. I'm gonna have to go add that on Ubuntu wiki -
dessert over 6 yearsPretty much anything is valid in a username! What characters should I use or not use in usernames on Linux? and endpoint.com/blog/2008/08/13/…
-
Sergiy Kolodyazhnyy over 6 years@dessert Yep, and that's one of the reasons it could break commands if shell decides to ... oh, maybe do filename expansion on username ... See askubuntu.com/a/983961/295286
-
Zanna over 6 yearsoh, alright then, edited slightly :P