Linux - NewbieThis 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
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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.
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!
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
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!
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.
"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.
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!
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.
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 ...
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.
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".
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
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.
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!
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.