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.
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
bash -x
, "who the user is" is already provided in the$USER
environment variable. – waltinator Dec 15 '17 at 21:57top -u $user || echo "$user is not logged in"
? This would save you the wholeif
expression… – dessert Dec 15 '17 at 21:58