LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices

Reply
 
Search this Thread
Old 07-18-2009, 01:12 PM   #1
PAvandal
LQ Newbie
 
Registered: Jul 2009
Posts: 3

Rep: Reputation: 0
Question for loops, if statements


Hello everyone. This seems to be a great forum, I notice a lot of useful answers and help.

I am in the midst of taking a summer course dedicated to linux administration, and have hit a wall. We began studying scripting, and I thought I had a hold of it.. until the "for loops" and "if statements" came rolling in. Since we don't have a book to refer to, I decided to hit the web for help!

We have 3 scripts to write for homework. I can get the individual information for each, but I am stuck on how to link all of these commands together via ifs and for loops. I was ok in class with my professor guiding us, but I feel that his examples were extremely easier than what he assigned for homework.

so onto the problems.. er, scripts!

SCRIPT #1...

1. Write a script that take a list of users on the system and determine if the user is currently logged in, if the user is logged in display the time and date the user logged in, and list the files (just files, not directories) in the users home directory. If the user is not logged in simply print a message indicating that the user is not logged in.

Okay. I have been using

Code:
#!/bin/bash
users=`cat /etc/passwd | grep -v nologin | cut -d: -f1 | grep -v halt | grep -v shutdown | grep -v news | grep -v sync`
to find the list of regular users.

to find what users are logged in, I am using

Code:
who | grep -v pts
to get the list of users that are currently logged in and the times they logged in.

to find the files in the users home directory, I would use something like

Code:
home=`cat /etc/passwd | grep -v nologin | cut -d: -f6`
to find the home directory, and then something like

Code:
ls -l $home
to find the files in the directory.

Now... how in the heck do I put all that together?! I am seriously lost.

SCRIPT 2...


2. Write a script that will take 1 command line argument. The argument will be a username. The script will determine if the user exists on the system and will print an error if it does not. If the user does exist it will determine if the user is currently logged in, if the user is not logged in it will determine the last time the user logged in and display the file in the users home directory that was most recently modified.


This one has me utterly lost. ANY, I mean, ANY, help would be appreciated!

Thank you everyone. Now that I have access to linux knowledge, I believe I will be stopping by here a lot!
 
Old 07-18-2009, 01:45 PM   #2
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
Hi and welcome to LQ!

Well, for script 1 use a for loop over the users stored in the variable "users". The syntax is quite easy:
Code:
for user in $users
do
  echo $user
done
Think that at each cycle you have just one user to manage and the loop variable "user" will be the one to use properly inside the cycle. Regarding the who command you can try the -u option to restrict the list to the actually logged users.

One thing to take in mind is that the shell does "expansions" before actually executing a command. In the example above, before the for loop is executed the shell expand the variable "users" to its actual value, resulting in something like:
Code:
for user in alex john arnold ted
do
  echo $user
done
To see the result of expansions and eventually debug your program, you can run it using
Code:
bash -x script.sh
so that the shell will print the expanded commands and help you in understanding how it works. Regarding shell expansion take alook here: http://tldp.org/LDP/Bash-Beginners-G...ect_03_04.html

Regarding script 2, I can't give the solution, since you have to figure it out by yourself in the learning process. Take in mind that arguments (usually called "positional parameters") are referred inside the script as $1, $2, $3... and so on. Even better if you use brackets, ${1}, ${2} and so on. In bash the brackets let you use more than 9 arguments, because $10 is an error, while ${10} is interpreted correctly.

Anyway, at the beginning of the script you can simply do:
Code:
#!/bin/bash
user=$1
so that you have a variable "user" to which you refer in the rest of the script as you do in script 1. Just a matter of variables names, since you can continue to use $1 in the whole script as well.

Finally, if you need some good text, you can bookmark the Advanced Bash Scripting Guide, a complete reference guide to all the bash basics and tricks. There is also a PDF available, you can download it but don't try to print it... they are hundreds of pages!

Last edited by colucix; 07-18-2009 at 01:51 PM.
 
Old 07-18-2009, 02:01 PM   #3
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Arch/XFCE
Posts: 17,802

Rep: Reputation: 728Reputation: 728Reputation: 728Reputation: 728Reputation: 728Reputation: 728Reputation: 728
Welcome to LQ---and thank you for acknowledging that this is homework.

If they don't give you a book, where are you getting ANY information?----lecture notes? Head over to http://tldp.org and get the Bash Guide for Beginners by Machtelt Garrels. You might also want to get the Advanced Bash Scripting Guide. The latter is not a tutorial, but has a bazillion examples and is useful for searching.

If:
This is easy. The basic syntax is:
Code:
if <some test>
then
    do something
else
    do something different
fi

#EXAMPLE:
if [ $variable -gt 1 ]
then
    echo "it's bigger!!"
else
    echo "it's not bigger...."
fi
(The "else" is optional--ie you can do something if the test succeeds, and do nothing if it fails)

Loops:
There are two basic kinds---I'll describe each with an example. In this case, I'm putting them all on one line---you can cut and paste these to see how they work.


Code:
for i in $(seq 1 10); do echo $i; done


i=2; while [ $i -lt 7 ]; do echo $i; i=$(($i+1));done

#And of course the endless loop:
while true; do echo "we're running"; done
Note in this example that the ";" is functionally that same as a newline character.
 
Old 07-18-2009, 02:27 PM   #4
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,557
Blog Entries: 28

Rep: Reputation: 1178Reputation: 1178Reputation: 1178Reputation: 1178Reputation: 1178Reputation: 1178Reputation: 1178Reputation: 1178Reputation: 1178
Hello PAvandal

Welcome to the forum.

"Advanced Bash Scripting Guide" is good, especially for examples, but is not so easy to find you way around. It's one of the three I use for reference.

The others are Gnu's Bash Reference Manual (it has a great Table of Contents) and The Open Group's definition of the (POSIX) Shell Command Language (no Table of Contents but all on one page so easy to search. Very terse but tightly defined; useful when looking for a precise definition).

Best

Charles
 
Old 07-18-2009, 03:31 PM   #5
PAvandal
LQ Newbie
 
Registered: Jul 2009
Posts: 3

Original Poster
Rep: Reputation: 0
Thank you everyone for your help and resources.

I think that the issue that I'm having is that I don't understand, in human terms, how to "test" things. in the if statements, what kind of commands or syntax are to be used to run my list of users against the list in the who command? I understand that this is function of the "if" statement.

Through everyone's help, I understand that each "user" will go through the loop on their own. I need a command that can check to see if each user that is in the $users variable are in the "who" command listing. My instructor told us that we could use the "test" command, but it seems to be a lot more complicated than something I can just put in my script.

pixellany - all of the information is from lecture. One of the problems is that it's a 4 hour class, and we cover a lot of material each class without any time to test what we have learned and see where we are failing. I'm very interested in all of this, but it's a rather daunting way to learn!
 
Old 07-18-2009, 03:50 PM   #6
mmatt
Member
 
Registered: Nov 2005
Location: UK
Distribution: archlinux
Posts: 90

Rep: Reputation: 19
As with most programming problems there is more than one way to do this. You could use a nested for loop and an if statement to check the current user against the list from who - this would be quite inefficient. Or you could search for the user in the list with, for example, grep and use the return code or string length of the result as a value to test against. If you need a code example just ask, but have a go first.

p.s. use grep -w to match whole words

Last edited by mmatt; 07-18-2009 at 04:01 PM.
 
Old 07-18-2009, 04:29 PM   #7
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,557
Blog Entries: 28

Rep: Reputation: 1178Reputation: 1178Reputation: 1178Reputation: 1178Reputation: 1178Reputation: 1178Reputation: 1178Reputation: 1178Reputation: 1178
Quote:
Originally Posted by PAvandal View Post
Thank you everyone for your help and resources.

I think that the issue that I'm having is that I don't understand, in human terms, how to "test" things. in the if statements, what kind of commands or syntax are to be used to run my list of users against the list in the who command? I understand that this is function of the "if" statement.

Through everyone's help, I understand that each "user" will go through the loop on their own. I need a command that can check to see if each user that is in the $users variable are in the "who" command listing. My instructor told us that we could use the "test" command, but it seems to be a lot more complicated than something I can just put in my script.

pixellany - all of the information is from lecture. One of the problems is that it's a 4 hour class, and we cover a lot of material each class without any time to test what we have learned and see where we are failing. I'm very interested in all of this, but it's a rather daunting way to learn!
You are already looping over all the users in the passwd file and you have a list of logged on users from the who command so for each iteration of the passwd users you could loop over the list of logged on users testing (ha!) for a match. If you find a match or not then you do as required. That will require a flag variable, set to not found (found=0) before entering the logged on users loop and set to found (found=1) in the loop when you do find a match. After the logged on users loop, test the found flag ...
 
Old 07-18-2009, 05:11 PM   #8
mmatt
Member
 
Registered: Nov 2005
Location: UK
Distribution: archlinux
Posts: 90

Rep: Reputation: 19
I'll retract my statement about nested for loops being inefficient, using time they were ~5x quicker than the call to grep...
 
Old 07-18-2009, 05:18 PM   #9
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
Basically there are two forms of if/then tests: 1) test if an expression is true; 2) test if the exit status of a command is 0 (success). The syntax of the first form is:
Code:
if [ expression ]
then
  command
  command
  ...
fi
An expression can be a string comparison, an arithmetic comparison or a file test (see man test to see all the possibilities, but take in mind that you don't need to use the test command, since the square brackets already perform a test).

The syntax of the second form is:
Code:
if command
then
  command
  command
  ...
fi
Here the command after "if" is actually executed (whatever it be) and its exit status is evaluated: if the command had success then the if/then body is executed, if the command failed then the if/then body is ignored.

In your case, you have to think which command tells you if a particular user is logged in, then just put it after "if". For example:
Code:
if who | grep $user > /dev/null
then
  echo user $user is logged in
else
  echo user $user is not logged in
fi
Is up to you to know what a pipe means and why I used redirection to /dev/null.

For more examples about the if/then usage, you can see the Bash Guide for Beginners or any of the guides linked above.
 
Old 07-18-2009, 06:39 PM   #10
mmatt
Member
 
Registered: Nov 2005
Location: UK
Distribution: archlinux
Posts: 90

Rep: Reputation: 19
A much more thorough explanation colucix . I'll just reiterate that grep -w $user would be better to avoid matching, for example, "daniel" when the $user variable is "dan".
 
Old 07-19-2009, 03:21 AM   #11
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Servers: Debian Squeeze and Wheezy. Desktop: Slackware64 14.0. Netbook: Slackware 13.37
Posts: 8,557
Blog Entries: 28

Rep: Reputation: 1178Reputation: 1178Reputation: 1178Reputation: 1178Reputation: 1178Reputation: 1178Reputation: 1178Reputation: 1178Reputation: 1178
Quote:
Originally Posted by mmatt View Post
I'll retract my statement about nested for loops being inefficient, using time they were ~5x quicker than the call to grep...
Shell parameter expansion is usually a lot quicker for string manipulation than piping through (sometimes multiple) sed, awk etc. "Usually" because shell parameter expansion is gruesomely slow with big (say > 1 kB) strings. All of which is only significant when performance is an issue
 
Old 07-19-2009, 06:05 AM   #12
mmatt
Member
 
Registered: Nov 2005
Location: UK
Distribution: archlinux
Posts: 90

Rep: Reputation: 19
catkin you're right of course - no point spending extra minutes coding to save milliseconds at runtime...
 
Old 07-19-2009, 08:03 PM   #13
chrism01
Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Centos 6.5, Centos 5.10
Posts: 16,311

Rep: Reputation: 2040Reputation: 2040Reputation: 2040Reputation: 2040Reputation: 2040Reputation: 2040Reputation: 2040Reputation: 2040Reputation: 2040Reputation: 2040Reputation: 2040
In general, I'd strongly advise the OP to bookmark and read(!) the Beginners & Advanced Bash guides referred to previously.
They are well written and have loads of examples.
You just need to read & write shell scripts, there's no substitute for experimentation here.
I will point out that using the line

set -xv

as the 2nd line of a script shows you exactly what its doing - think debug mode.
 
Old 07-20-2009, 10:31 PM   #14
PAvandal
LQ Newbie
 
Registered: Jul 2009
Posts: 3

Original Poster
Rep: Reputation: 0
Well, somehow, it clicked!

My very, very limited knowledge of linux, combined with the bash beginners guide (thanks colucix!), helped me come up with a script that may not be the most efficient, but it works!

Code:
#!/bin/bash
users=`cat /etc/passwd | grep -v nologin | grep -v halt | grep -v shutdown | grep -v news | grep -v sync | grep -v vboxadd | cut -d: -f1`
logged=`last | grep -w still | grep -v pts | cut -d" " -f1`
homedir=`cat /etc/passwd | grep -w $logged | grep -v nologin | cut -d: -f6`
last=`last | grep -w still | grep -v pts | cut -c40-55`
list=`ls -l $homedir`
notlog=`last | grep -v still | grep -v pts | cut -d" " -f1 | sort | uniq | grep -v $logged`
echo $logged is logged in, and logged in at $last
for files in $list
do
        if [ -f $files ]      
        then echo $files is a file in their home directory.
        fi
done
echo $notlog are not logged in.
I'm so surprised and happy that I figured this out. Thanks everyone for your help, sincerely. I'm pretty confident that I can handle script#2 now.

I'm sure I'll be back for more help in the future!
 
  


Reply

Tags
bash, scripting


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
if else statements 0.o Programming 7 09-27-2005 03:59 PM
C Loops and switch statements ripwheels8 Programming 4 11-13-2004 05:47 PM
if statements and case statements not working in bourne shell script mparkhurs Programming 3 06-12-2004 03:41 AM
PHP: egrep For Loops and If Statements jhrbek Programming 14 12-31-2003 01:26 PM
if then statements vapor Programming 4 07-16-2003 07:44 AM


All times are GMT -5. The time now is 02:02 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration