Help with simple program. (beginner)

Hey all,

Writing a program that searches for a username and if they are online creates a 'beep' and sends the username and date to a log file.

the error i am getting is:

paul.obrien16@aisling:~/os$ bash checklogin
: command not found
Enter username
paul.obrien16
': not a valid identifier `username
checklogin: line 36: syntax error: unexpected end of file
paul.obrien16@aisling:~/os$

Here is my code for refrence:

#!/bin/bash

# get username
echo "Enter username"
read username
#finds the user in the list of people currently logged in
if [ $ cat /etc/passwd | cut -d: -f1= "$username" ]
then
# loop while user is logged in
while [ $(who | grep $username) != 0 ]
do
sleep 60
done

echo "$username logged in"
#generate beep
echo -e \a
#output to a log file calles date.txt
echo "user is $(username) Today's date is $(date)" > /tmp/date.txt
#exit function
exit 1
else
#display message
echo "$username aint logged in!"
#output to a log file called date.txt
echo "user is $(username) Today's date is $(date)" > /tmp/date.txt
#exit the function
exit 1
#end the script
fi

exit 0

A good start but there's a few things to figure out here:

if [ $ cat /etc/passwd | cut -d: -f1= "$username" ]

You don't put programs inside [ ] like that, you can just put them there raw.

That is also a useless use of cat, whenever you have cat stuff | program it's better to do program < stuff .

There's a trick you can do with grep to check for a user in the password file:

if grep -q "^${username}:" /etc/passwd
then
...

The ^ makes it look at the beginning of the line, so it looks for ${username}: at the beginning of any line in /etc/passwd. The -q tells it not to print anything, just return true or false as usual.

while [ $(who | grep $username) != 0 ]

This is a useless use of backticks (since the $(stuff) syntax is a special form of backticks). You don't check a return value in that fashion, either -- what that statement would actually end up doing is checking the string output of who | grep $username.

How you check a return value is like:

# there really are 'true' and 'false' programs, so go ahead and
# try these statements
if true
then
       echo "true returns true"
fi

if ! false
then
        echo "false returns false"
fi

So how about:

while who | grep -q "${username}"
do
...
exit 1

1 means error, by returning 1 you're telling whatever ran it that your program failed. Use 'exit 0' to show that your program ran successfully.

Validate your input not blank, is in /etc/passwd, first, before proceeding, if bad then display, exit -- done, no deep nesting, all parts of the function point close together. A cat is not necessary to get files to stdin, < does that cheaper. One user name might be a substring of another, so the grep of who should be more qualified. date can produce the entire message using a "+%Y-%m-%d %H:%M:%S $username" sort of argument, and have a nicer format. $(xxx) is not for diplaying variables, that is ${xxx}, $(xxx) turns a command or script stdout into a string on the command line, just the opposite of echo, which turns a string on the command line into a stream on stdout. The error message does not describe the error, unnown user name.