From Fedora Project Wiki
(Redirected from Introduction to bash shell scripting Classroom (20090307))
Resources
Other Wiki Docs
I put together StabbyMc's_Intro_to_Shell_Scripting to organize the ideas in a more linear fashion. I also added some additional concepts that we weren't able to get to in class.
IRC Log
-!- nirik changed the topic of #fedora-classroom to: Fedora IRC Classroom - Introduction to bash shell scripting with your teacher Scott McBrien ( | 11:15 | |
StabbyMc_ ) - See Classroom for class schedule today and more info. | ||
StabbyMc_ | OK, it's 18:15 UTC, lets get started | 11:15 |
---|---|---|
oNe3 | ok | 11:15 |
StabbyMc_ | Questions are welcome | 11:15 |
wonderer|chatzil | ok | 11:15 |
@nirik | ok, take it away StabbyMc_ ! | 11:15 |
StabbyMc_ | I'd like to keep comentary to a minimum ;-) | 11:15 |
StabbyMc_ | Alright, so we're talking about an introduction to shell scripting. | 11:15 |
zer0c00l | damn squid will go down shortly for a log backup :( | 11:15 |
oNe3 | <nirik> ok | 11:15 |
StabbyMc_ | And the example I've put together is adding a user to a machine. | 11:15 |
StabbyMc_ | So when you're adding a user to a machine, what do you typically do? | 11:16 |
StabbyMc_ | What commands would you run? | 11:16 |
linuxguru | useradd , passwd | 11:16 |
StabbyMc_ | exactly. | 11:16 |
oNe3 | cd mkdir | 11:16 |
oNe3 | cat tail | 11:16 |
oNe3 | ls | 11:16 |
oNe3 | sh | 11:16 |
@nirik | oNe3: uh, those seem unrelated to adding a user. ;) | 11:16 |
StabbyMc_ | You use useradd to add the user to /etc/passwd, /etc/shadow, create and populate their home dir... | 11:17 |
StabbyMc_ | Then you need to set their inital password with passwd. | 11:17 |
oNe3 | service ... status | 11:17 |
StabbyMc_ | So two separate commands that you almost always have to run together to accompish the task of adding a user. | 11:17 |
StabbyMc_ | *THIS* concept is the beginning of a shell script. | 11:17 |
StabbyMc_ | At its most basic core, a shell script is simply a list of commands to run in order. | 11:18 |
StabbyMc_ | If you're familiar with some _other_ operating system, at a very basic stage a shell script is like a batch file. | 11:18 |
StabbyMc_ | So I've written some examples for us to take a look at. | 11:19 |
StabbyMc_ | The first is very basic. | 11:19 |
StabbyMc_ | http://fpaste.org/paste/4852 | 11:19 |
StabbyMc_ | So to make this script, I added the two commands that I need to run to add a user to a file. | 11:19 |
StabbyMc_ | Then I make the file executable, by something like chmod +x <name of file> | 11:20 |
StabbyMc_ | And lastly, to invoke the script with these two commands, on the command line I provide the full path to the file I've created. | 11:20 |
StabbyMc_ | Or if I'm in the directory that contains the file I can run ./script_file_name | 11:20 |
StabbyMc_ | -OR- | 11:20 |
StabbyMc_ | What I think is the best mechanism, on Fedora the PATH variable includes ~/bin | 11:21 |
rtnpro | StabbyMc_: ! | 11:21 |
StabbyMc_ | So I generally take the executable file and drop it in /root/bin so that I can just run it like a command on the command line. | 11:21 |
StabbyMc_ | Ok, so to recap, I put the commands I want to run in a file, make the file executable, then call it from the command line. | 11:22 |
@nirik | rtnpro: you had a question? go ahead and ask... | 11:23 |
StabbyMc_ | Before we start talking about making changes to the contents of the script, making it more sophisticated, any questions on how we execute | 11:23 |
a basic script? | ||
StabbyMc_ | yes, please post questions as you have them, no need to be recognized. | 11:23 |
oNe3 | in the begin of file with +x need string #/bin/sh/? | 11:23 |
StabbyMc_ | oNe3: an excellent question. | 11:24 |
rtnpro | StabbyMc_: will it work without the #!/usr/bin/sh | 11:24 |
StabbyMc_ | That will be one of the first enhancements to our script. | 11:24 |
oNe3 | yes | 11:24 |
StabbyMc_ | Without the #! line, a shell script will assume that you wish to use the shell program that the user has. | 11:24 |
oNe3 | this only identify script | 11:24 |
StabbyMc_ | So for many of us this is the bash shell. | 11:24 |
oNe3 | # is commentary | 11:25 |
mahesh | can i execute a file being in the same directory and by using the command $bash <filename> | 11:25 |
StabbyMc_ | So if I run the script, it will be interpreted as a bash script. | 11:25 |
rtnpro | ok | 11:25 |
StabbyMc_ | mahesh: yes you can also do that. | 11:25 |
oNe3 | perl will run witout :) | 11:25 |
oNe3 | without | 11:25 |
mahesh | StabbyMc_ ok | 11:26 |
StabbyMc_ | Alright, I think we're all thinking in the same direction, so lets take a look at a slightly more enhanced version of the same script.. | 11:26 |
StabbyMc_ | http://fpaste.org/paste/4853 | 11:26 |
StabbyMc_ | So notice in this version I added the #! at the top. | 11:26 |
oNe3 | StabbyMc_, create users is the litle problem on desctop, and many usefus servers have a virtual users stored in DB | 11:27 |
StabbyMc_ | The reason you want to do this is what happens if someone running the script uses pdksh or tcsh as their shell? The commands will be run | 11:27 |
with the wrong shell interpreter. | ||
StabbyMc_ | So the #! at the very top tells us what program to call to read and execute the commands contained in this script. | 11:27 |
StabbyMc_ | oNe3: we'll be addressing that :-) | 11:28 |
oNe3 | yes, its right | 11:28 |
franciscod | StabbyMc_: scripting isnt the same for them is it ? | 11:28 |
StabbyMc_ | The #! is also something that you see in perl scripts for the same reason. | 11:28 |
franciscod | for pdksh etc ? | 11:28 |
StabbyMc_ | You don't want your perl program instructions read and executed by bash, which uses very different syntax | 11:28 |
StabbyMc_ | franciscod: right. | 11:28 |
StabbyMc_ | now at the bottom of the script we see a line that begins with # | 11:29 |
oNe3 | where? in perl or bash? | 11:29 |
StabbyMc_ | Except for the first line in the script which is a # followed by a !, any other occurence of # will be seen as a comment. | 11:29 |
StabbyMc_ | oNe3: for #! lines, it works the same in both schell scripting and perl. Generally that's true of any interpreted (non compiled) language. | 11:30 |
Zart | it's possible to run the same script via bash/perl/tcl with some syntax tricks | 11:30 |
oNe3 | script language | 11:30 |
oNe3 | like perl and bash | 11:30 |
StabbyMc_ | So the line down at the bottom of the script is a comment, and I've added a bit to tell us how this program should be executed on the | 11:30 |
command line. | ||
StabbyMc_ | (we'll be changing this too to make it better, later) | 11:30 |
oNe3 | ) | 11:31 |
StabbyMc_ | In addition to adding the interpreter to use (#!) and the comment, I've also made one other change. | 11:31 |
StabbyMc_ | in the previous example, my script added a single user, frank. | 11:31 |
StabbyMc_ | which means in order to re-use it, I'd have to edit the file and change the username. | 11:31 |
oNe3 | StabbyMc_, please put scripts here | 11:32 |
StabbyMc_ | Which is a lot of work, and the point of scripting is to do less work! | 11:32 |
StabbyMc_ | http://fpaste.org/paste/4853 | 11:32 |
StabbyMc_ | oNe3: this is the script I'm talking about currently. | 11:32 |
StabbyMc_ | The additional change I've made is adding a variable, $1 | 11:32 |
StabbyMc_ | notice that I now useradd $1 | 11:32 |
StabbyMc_ | and set the password for $1 | 11:32 |
StabbyMc_ | $1 is known as a positional parameter | 11:33 |
StabbyMc_ | meaning it's value corresponds to the 1st argument passed to the script as an argument. | 11:33 |
franciscod | StabbyMc_: is there a $0 ? coressponding to the app name ? | 11:34 |
StabbyMc_ | positional parameters start at $0 (the script name) and will be assigned for as many items are passed to the script on the command line. | 11:34 |
franciscod | answered.. thanks.. | 11:34 |
StabbyMc_ | franciscod: we're on the same page ;-) | 11:34 |
franciscod | :) | 11:34 |
StabbyMc_ | So now, as the comment at the bottom of the page indicates, when we call the script it'll look something like | 11:34 |
StabbyMc_ | scriptfile frank | 11:34 |
StabbyMc_ | $0 will be assigned as "scriptfile" and $1 is frank | 11:35 |
oNe3 | ./frank ? | 11:35 |
StabbyMc_ | Later we'll be enhancing the script to handle multiple users. | 11:35 |
StabbyMc_ | oNe3: no, more like ./useradd-wrapper frank | 11:35 |
StabbyMc_ | so the command we're running corresponds to the file that our scripted commands are stored in. | 11:36 |
oNe3 | how to edit more than 1 users? | 11:36 |
StabbyMc_ | So we could ./useradd-wrapper frank vlad amelia | 11:36 |
oNe3 | stored in /usr/bin | 11:36 |
StabbyMc_ | where frank would be $1, vlad is $2, and amelia is $3 | 11:36 |
* franciscod gets this part properly.. | 11:37 | |
StabbyMc_ | But currently the *internals* of our script doesn't support multiple users. | 11:37 |
StabbyMc_ | we'll be updating it though. | 11:37 |
zer0c00l | yeah | 11:37 |
StabbyMc_ | So my idea for this lesson is that we start with something very basic and keep enhancing the same script to make it better. | 11:37 |
StabbyMc_ | to make it handle more than one user. | 11:37 |
StabbyMc_ | to add more customization for adding users. | 11:38 |
wonderer|chatzil | sounds good. | 11:38 |
zer0c00l | StabbyMc_: why that --stdin why not "passwd $1" | 11:38 |
StabbyMc_ | So lets say that these commands are in a file /root/bin/useradd-wrapper | 11:38 |
StabbyMc_ | zer0c001: Ah a great question. | 11:38 |
oNe3 | is learning pass for $1 username ))) | 11:39 |
StabbyMc_ | so the problem with passwd is, that by default, it's interactive. | 11:39 |
oNe3 | ) | 11:39 |
StabbyMc_ | If we just run passwd $1 it will now require us, the admin, to type in the password, then type it again to set it. | 11:39 |
oNe3 | many interactive commands in linux ))) | 11:39 |
StabbyMc_ | I'm using the --stdin option to passwd so that passwd will accept the user's password over a |, rather than ask me to type it. | 11:40 |
* franciscod looks at "man passwd" | 11:40 | |
oNe3 | | is the system conveer | 11:40 |
StabbyMc_ | so in the script as it is, I'm setting the username in $1's password to be the string, mypassword. | 11:41 |
StabbyMc_ | So if we call useradd-wrapper frank | 11:41 |
franciscod | *--stdin* This option is used to indicate that passwd should read the new password from standard input, which can be a pipe. | 11:41 |
StabbyMc_ | frank is added, and has a password of mypassword | 11:41 |
StabbyMc_ | if we useradd-wrapper vlad | 11:41 |
StabbyMc_ | vlad is created and also has a password set of mypassword | 11:41 |
StabbyMc_ | This makes you all unhappy right? That everyone gets the same password? | 11:42 |
oNe3 | typing passwords in scripts are bad | 11:42 |
StabbyMc_ | oNe3 I agree. | 11:42 |
StabbyMc_ | So that's our next enhancement. | 11:42 |
StabbyMc_ | But before we move to that, I want to make sure everyone is OK with $1 and the idea of positional variables. | 11:43 |
StabbyMc_ | Questions? | 11:43 |
* franciscod is okay with position variables.. | 11:43 | |
franciscod | StabbyMc_: any limit to number of posn variables ? | 11:43 |
oNe3 | # | 11:43 |
oNe3 | echo mypassword | passwd --stdin $1 .... password is mypassword or -stdin $1 ? | 11:43 |
* sherry151 understood too. | 11:43 | |
SSlater | What if the system already has a frank? | 11:43 |
StabbyMc_ | oNe3: the password set for the user in $1 is whatever string passed by echo. | 11:44 |
rtnpro | oNe3: I didn't get the 2nd step | 11:44 |
StabbyMc_ | so echo mypassword sets the password for the user $1 to be mypassword | 11:44 |
StabbyMc_ | If we echo "supersecret" | passwd --stdin $1 | 11:44 |
rtnpro | oNe3: ok | 11:44 |
mahesh | $0 is script file... iam not clear with this | 11:44 |
oNe3 | but mypassword | is not variable!!! | 11:44 |
StabbyMc_ | now the user we add has a password of supersecret | 11:45 |
StabbyMc_ | oNe3: Not yet. | 11:45 |
oNe3 | $mypassword maybe? | 11:45 |
StabbyMc_ | But remember, we're starting small, and fixing things as we go! | 11:45 |
Zart | short summary: scripts allow execution of number of commands and allow re-using them later for various tasks. to make them more flexible, we're | 11:45 |
using arguments to parametrize them | ||
StabbyMc_ | Zart: right on. | 11:45 |
StabbyMc_ | Lets take a look at a new enhancement. | 11:46 |
StabbyMc_ | http://fpaste.org/paste/4854 | 11:46 |
zer0c00l | i have another question passwd command will ask us two times password right? how could our script do it? | 11:46 |
StabbyMc_ | zer0c001: that's why I'm using --stdin, so that the passwd command doesn't require me to type anything, it takes input over the |. | 11:46 |
zer0c00l | ok | 11:46 |
oNe3 | http://fpaste.org/paste/4854 hm | 11:47 |
StabbyMc_ | Ok, so the new enhancement takes care of some of our issues. | 11:47 |
StabbyMc_ | 2 new things are added. | 11:47 |
oNe3 | # | 11:47 |
oNe3 | #!/bin/bash | 11:47 |
oNe3 | # | 11:47 |
oNe3 | # | 11:47 |
oNe3 | useradd $1 | 11:47 |
oNe3 | # | 11:47 |
oNe3 | # | 11:47 |
StabbyMc_ | First, we have a variable to store the password! | 11:47 |
oNe3 | password=mkpasswd
|
11:47 |
oNe3 | # | 11:47 |
heftig | i suppose mkpasswd is another script | 11:47 |
oNe3 | # | 11:47 |
oNe3 | echo $password | passwd --stdin $1 | 11:47 |
StabbyMc_ | oNe3 | 11:47 |
@nirik | oNe3: don't paste entire scripts please... use pastebin. ;) | 11:47 |
oNe3 | ok | 11:47 |
StabbyMc_ | We can't paste the contents of the script in chat, which is why I'm putting up the links to them :-) | 11:47 |
oNe3 | ok, sorry | 11:48 |
StabbyMc_ | so we're creating a new variable called password | 11:48 |
StabbyMc_ | Which we use later in our passwd command. | 11:48 |
oNe3 | but what is password=mkpasswd ?
|
11:48 |
StabbyMc_ | So that now we don't have the same password being set for everyone. | 11:48 |
StabbyMc_ | oNe3 sees the other change. | 11:48 |
StabbyMc_ | So I could have done something like | 11:49 |
oNe3 | ok | 11:49 |
StabbyMc_ | password="mypassword" | 11:49 |
StabbyMc_ | but that would still end up setting every new user's password to the same string :-( | 11:49 |
oNe3 |
|
11:49 |
linuxguru | oNe3, read this when you get time http://fedoraproject.org/wiki/Communicate/IRC/Maximizing_Support_from_IRC | 11:49 |
StabbyMc_ | AND I'd still have the password in plain text in this file. | 11:49 |
StabbyMc_ | so oNe3 is right. | 11:49 |
StabbyMc_ | mkpasswd is another command. | 11:49 |
StabbyMc_ | if you run it on your machines and it says "mkpasswd Command not found" | 11:50 |
zer0c00l | ya | 11:50 |
StabbyMc_ | That's because this program is provided by the expect RPM | 11:50 |
StabbyMc_ | so if you yum install expect | 11:50 |
StabbyMc_ | You'll get mkpasswd installed (as well as the expect programming language) | 11:50 |
oNe3 | <linuxguru> i know this, i want to speak, if you think bad for me say this and i.m be banned | 11:50 |
StabbyMc_ | mkpasswd is a program that will create random 8 character passwords | 11:51 |
StabbyMc_ | The 8 characters will include a mixture of upper and lower case, digits, and an other character. | 11:51 |
franciscod | StabbyMc_: how will we know what it generated? | 11:51 |
StabbyMc_ | franciscod: well that's a problem. | 11:51 |
StabbyMc_ | Because it really is RANDOM | 11:51 |
zer0c00l | :-) | 11:52 |
StabbyMc_ | So we'll be fixing that too, but it'll be later. | 11:52 |
linuxguru | franciscod, you can echo $password | 11:52 |
franciscod | so we've made accounts and we dont know the passwd? ;) | 11:52 |
StabbyMc_ | For right now, yes. | 11:52 |
StabbyMc_ | But in real life, that would be silly. Especially since we can't tell the new user what their password is because its a random string! | 11:52 |
StabbyMc_ | But again, we'll be fixing that. Its towards the end though. | 11:53 |
mahesh | can we view those random passwd's later | 11:53 |
StabbyMc_ | for now, lets just say "Yea we get randomized passwords, hurrah"... | 11:53 |
StabbyMc_ | mahesh: not unless we store them. | 11:53 |
StabbyMc_ | once the script ends, the value in $password will be lost. | 11:53 |
StabbyMc_ | Oddly enough, we'll be storing them later ;-) | 11:54 |
mahesh | StabbyMc_ ok | 11:54 |
StabbyMc_ | The bigger concept to take from this is not mkpasswd, but rather how we're calling it in the script. | 11:54 |
StabbyMc_ | Notice that we're setting the variable to mkpasswd
|
11:54 |
linuxguru | command substitution | 11:54 |
StabbyMc_ | This is a concept known as command substitution or quoted execution. | 11:54 |
StabbyMc_ | the charcter
|
11:55 |
StabbyMc_ | is the backquote. | 11:55 |
StabbyMc_ | it shares the key with the ~ character on US keyboards. If you were to use a single quote ', it would not work right. | 11:55 |
zer0c00l | ok
|
11:55 |
StabbyMc_ | Now for almost all the additional examples I use s to do my quoted execution. | 11:56 |
StabbyMc_ | But there is another way you may see it, or you may prefer to have quoted execution in your scripts. | 11:56 |
StabbyMc_ | http://fpaste.org/paste/4855http://fpaste.org/paste/4855 | 11:57 |
StabbyMc_ | http://fpaste.org/paste/4855 | 11:57 |
StabbyMc_ | http://fpaste.org/paste/4855 | 11:57 |
StabbyMc_ | Bah | 11:57 |
StabbyMc_ | Ok, laggy network, sorry about htat. | 11:57 |
linuxguru | no problem | 11:57 |
linuxguru | ok so i thought $(mkpasswd) will fork a new sub-shell and mkpasswd will not
|
11:58 |
* nirik thinks they are the same thing, both do a subshell and pass the output back. Just a matter of quoting differences. | 11:59 | |
heftig | uh, as far as i can determine both fork a subshell | 12:00 |
* nirik nods. | 12:00 | |
linuxguru | okay | 12:00 |
* nirik suspects StabbyMc_ is renewing his network connection. Should be back in a sec here. | 12:00 | |
delhage | did scott lose his connection now? | 12:00 |
StabbyMc_ | so we can also take the output of a command and store it in a variable by the method here | 12:00 |
StabbyMc_ | Using $(command) | 12:00 |
StabbyMc_ | Which according to delhage is easier if you're not using a US keyboard. | 12:00 |
StabbyMc_ | So right now, we have a basic script that adds a user (passed on the command line) and sets their password to a random string. | 12:00 |
StabbyMc_ | questions on quoted execution or setting variables in a script? | 12:00 |
StabbyMc_ | Ok, so one of the questions asked earlier was what if user $1 already exists. | 12:01 |
StabbyMc_ | Right now we'd change their password to a random string and see an error out of useradd that the user already exists. | 12:01 |
StabbyMc_ | So lets enhance the script further to make it a little more tolerant of errors. | 12:01 |
StabbyMc_ | http://fpaste.org/paste/4856 | 12:01 |
StabbyMc_ | Yeah, I'm back... | 12:01 |
StabbyMc_ | linuxguru, they both fork a new shell for the quoted command. | 12:01 |
StabbyMc_ | if you don't want a subshell created, take a look at the source command. | 12:01 |
StabbyMc_ | also known as the . command | 12:01 |
linuxguru | StabbyMc_, thanks | 12:01 |
StabbyMc_ | So this script http://fpaste.org/paste/4856 | 12:02 |
StabbyMc_ | introduces the if statement | 12:02 |
StabbyMc_ | Lets check a condition on the machine before proceeding. | 12:02 |
StabbyMc_ | Now an if is a shell command, just like echo or others. | 12:02 |
StabbyMc_ | it takes an argument of a command to run. | 12:02 |
StabbyMc_ | And it will check the return of that command to see if the command is successful or failed. | 12:03 |
StabbyMc_ | So lets fill in this condition. | 12:03 |
mahesh | what does fi do?? | 12:03 |
StabbyMc_ | http://fpaste.org/paste/4857 | 12:03 |
StabbyMc_ | mahesh: you may have worked with other programming languages where code is put in blocks? | 12:03 |
StabbyMc_ | Usually with some kind of bracket character, well in shell a fi is the command that ends an if command block | 12:04 |
franciscod | it closes the block.. | 12:04 |
mahesh | StabbyMc_ ok | 12:04 |
StabbyMc_ | You'll see this kind of thing with several other shell control constructs. | 12:04 |
StabbyMc_ | In a minute or so we'll talk about for loops. | 12:04 |
StabbyMc_ | They'll have some keywords that define their code blocks too. | 12:05 |
mahesh | StabbyMc_ ok | 12:05 |
StabbyMc_ | Sometimes, like with if, it's the word spelled backwards. | 12:05 |
StabbyMc_ | Or with a case statement, you'd end it with an esac (case spelled backwards) | 12:05 |
StabbyMc_ | With loops it is usually do and done that define the loop contents. | 12:05 |
StabbyMc_ | So with script http://fpaste.org/paste/4857 | 12:06 |
mahesh | StabbyMc_ clear now | 12:06 |
StabbyMc_ | we're running useradd $1 as an argument to if. | 12:06 |
StabbyMc_ | which means if the useradd is successful, we will then set the user's password. | 12:06 |
StabbyMc_ | But if the useradd fails (maybe because the user already exists) we skip the code in the then-fi code block. | 12:06 |
StabbyMc_ | We'll be doing some more with if statements in a bit, and there are some neat things you can check beside trying to run a command. | 12:07 |
StabbyMc_ | So this is how we can check to make sure we don't mangle existing users on the system with our script. | 12:08 |
StabbyMc_ | I'll be making it a little better soon. | 12:08 |
StabbyMc_ | But one of the early other problems that was raised is working on multiple users. | 12:08 |
itnomad | if useradd fails, will we see the error in the output? | 12:08 |
heftig | itnomad: yes | 12:08 |
itnomad | thanks | 12:08 |
StabbyMc_ | itnomad: yes, but I'll address that too. | 12:08 |
StabbyMc_ | http://fpaste.org/paste/4859 | 12:09 |
StabbyMc_ | So this is the syntax of adding a for loop. | 12:09 |
StabbyMc_ | In shell, for is an iterative loop that will execute the contents of the do-done code block until the list of items it's been passed has | 12:09 |
been exhausted. | ||
StabbyMc_ | for each iteration, the placeholder variable contents are replaced with the current item we are iterating on. | 12:10 |
StabbyMc_ | So filling in these pieces... | 12:10 |
StabbyMc_ | http://fpaste.org/paste/4860 | 12:11 |
StabbyMc_ | http://fpaste.org/paste/4860 | 12:11 |
StabbyMc_ | So now our script can accept up to 5 usernames on the command line | 12:11 |
StabbyMc_ | but if we only provide 2 users, it'll produce some errors. | 12:11 |
StabbyMc_ | So instead of using $1 - $5 | 12:12 |
heftig | would it try to add some users with an empty name? | 12:12 |
StabbyMc_ | lets replace that with a copy of EVERYTHING passed to the script on the command line. | 12:12 |
StabbyMc_ | heftig: if you just run useradd with no arguments, it'll error. | 12:12 |
heftig | StabbyMc_: right | 12:12 |
delhage | ! | 12:13 |
StabbyMc_ | So just like $1 was set up automatically when the script runs. | 12:13 |
StabbyMc_ | There is another variable $* that get's set up. | 12:13 |
StabbyMc_ | delhage, question away. | 12:13 |
StabbyMc_ | $* is a variable that contains a copy of ALL arguements passed on the command line. | 12:13 |
StabbyMc_ | So if we call useradd-wrapper frank vlad joe | 12:14 |
delhage | I just want to point out that if $4 and $5 aren't set they will not be included in the for loop | 12:14 |
StabbyMc_ | $* contains "frank vlad joe" | 12:14 |
delhage | so no error | 12:14 |
StabbyMc_ | thanks for that clarification delhage :-) | 12:14 |
heftig | woohoo | 12:14 |
StabbyMc_ | if the script is called useradd-wrapper frank joe vlad amelia foobar | 12:14 |
StabbyMc_ | then $* contains "frank joe vlad amelia foobar" | 12:14 |
StabbyMc_ | A copy of all the arguments passed to the script. | 12:15 |
StabbyMc_ | So better, and more flexible would be: http://fpaste.org/paste/4861 | 12:15 |
StabbyMc_ | So for each argument stored in $*, we're going to iterate over the contents of the for loop's do-done code. | 12:16 |
StabbyMc_ | And each time we do an iteration, the current item we're working on from $* is going to be stored in the placeholder variable $user | 12:16 |
* nirik notes we are at 19:15 UTC now. ;) Feel free to go over, but do provide some break time before the next class. ;) | 12:16 | |
StabbyMc_ | nirik, thanks, I should be able to wrap up in another 5-10 mins :-) | 12:16 |
StabbyMc_ | I think right now we have a pretty good script. | 12:17 |
StabbyMc_ | It works with a variety of things passed as parameters. | 12:17 |
StabbyMc_ | But we need to make it more error tolerant. | 12:17 |
vinod | also we can use $@ in place of $* | 12:17 |
StabbyMc_ | what happens when you call it and pass no users? | 12:17 |
mahesh | StabbyMc_ ok | 12:17 |
mahesh | errors | 12:18 |
StabbyMc_ | http://fpaste.org/paste/5352 | 12:18 |
StabbyMc_ | So I've added a new if statemetn into the mix. | 12:18 |
StabbyMc_ | And I've added a new branch to the if statement. | 12:18 |
StabbyMc_ | An else. | 12:18 |
franciscod | [ ] -> test .. right ? | 12:18 |
StabbyMc_ | the command we're running in the if is a test | 12:19 |
StabbyMc_ | franciscod: right! | 12:19 |
StabbyMc_ | so there is a command called test. | 12:19 |
StabbyMc_ | or it's often abreviated with this [ condition ] syntax | 12:19 |
StabbyMc_ | bash includes a variety of things that you can verify in a test command. | 12:19 |
StabbyMc_ | I'm using -n | 12:19 |
StabbyMc_ | -n checks to see if it's argument is a non-zero lenght string. | 12:20 |
* nirik notes there is a [ binary that is really the test command. ;) | 12:20 | |
zer0c00l | yeah | 12:20 |
StabbyMc_ | So if you don't pass any arguments, $* is empty, and is therefore a zero lenght string. | 12:20 |
herlo | $ which [ | 12:20 |
StabbyMc_ | which would fail the if check. | 12:20 |
herlo | /usr/bin/[ | 12:20 |
StabbyMc_ | and would launch us into the else branch. | 12:21 |
StabbyMc_ | So only if arguments are passed, ie $* has content, will we try and iterate though the arguments using a for loop. | 12:21 |
delhage | [root@mccloud ~]# type [ | 12:21 |
delhage | [ is a shell builtin | 12:21 |
StabbyMc_ | If the script is called with no arguments, we fail the if test and go into the else | 12:21 |
StabbyMc_ | which echos out an error message | 12:21 |
@nirik | delhage: it's that too. :) | 12:21 |
* franciscod directs to http://www.freeos.com/guides/lsst/ch03sec02.html | 12:22 | |
StabbyMc_ | Adn sets an exit value. | 12:22 |
zer0c00l | what is a exit value? why 7 there? | 12:22 |
zer0c00l | *an exit | 12:22 |
StabbyMc_ | Ok last change we have time for, I'll post the rest of the unit on the wiki to go along with the log. | 12:22 |
StabbyMc_ | http://fpaste.org/paste/5353 | 12:22 |
StabbyMc_ | I also added an else statement to our sucessful useradd check. | 12:23 |
StabbyMc_ | So if useradd is unsuccessful, it errors about that person, but will continue to try and add additional users on the commandline. | 12:23 |
StabbyMc_ | zer0c001: the seven is a non-zero value. | 12:24 |
StabbyMc_ | When commands exit successfully, they return a 0. | 12:24 |
heftig | wouldn't that output two errors? one from useradd to stderr and one from the script to stdout | 12:24 |
StabbyMc_ | On unsuccessful exit, they return non-zero | 12:24 |
StabbyMc_ | heftig: yes it would. | 12:24 |
StabbyMc_ | In the next changes I make, I redirect errors and output from things like useradd and passwd to /dev/null | 12:24 |
StabbyMc_ | That way we only see output from the scripts that WE put in, rather than random command crud. | 12:25 |
StabbyMc_ | Ok, but I think that's all we have time for... I'll update the wiki, and maybe we'll finish the last bits in another class. | 12:25 |
@nirik | thanks for the class StabbyMc_ ! | 12:25 |
neverho0d | StabbyMc_: we should add some commands for password storage, so we will be know what password users get after the scripts finished | 12:25 |
franciscod | StabbyMc_: thanks :D | 12:26 |
mahesh | StabbyMc_ thankyou | 12:26 |
-!- nirik changed the topic of #fedora-classroom to: Fedora IRC Classroom - Next class at 19:30UTC - See Classroom for | 12:26 | |
class schedule today and more info. | ||
SSlater | Thanks StabbyMc_ | 12:26 |
zer0c00l | thank u very much for the wonder full class StabbyMc_ | 12:26 |
baconfork | where on the wiki will the rest of it be? | 12:26 |
StabbyMc_ | neverho0d: I've got that too, and mailing the information to the user as well ;-)_ | 12:26 |
neverho0d | StabbyMc_: ok. thank you very much! | 12:26 |
itnomad | Thanks StabbyMc_ it would be cool if you could suggest some exercises. | 12:26 |
StabbyMc_ | baconfork, I'll add it to the transcript page, or at least a link to it from the transcript page when inode0 gets it up. | 12:26 |
linuxguru | StabbyMc_, nice. hope to see you in the next bash class for advanced users | 12:27 |
* wonderer|chatzil also thnaks for the class. | 12:27 | |
StabbyMc_ | If you guys want another more advanced class, suggest it on the classroom wiki page :-) | 12:27 |
heftig | StabbyMc_: ty | 12:27 |
baconfork | StabbyMc: Thanks for the class | 12:27 |
StabbyMc_ | You're all welcome, sorry we ran out of time :-) | 12:27 |
Generated by irclog2html.py 2.7 by Marius Gedminas - find it at mg.pov.lt!