Introduction to bash shell scripting (20090307 classroom)

From FedoraProject

Jump to: navigation, search


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.


-!- 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 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_ 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_ 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_ 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_ 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 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 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_ 11:57
StabbyMc_ 11:57
StabbyMc_ 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_ 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 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_ 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 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_ 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_ 12:11
StabbyMc_ 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: 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_ 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 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_ 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 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 2.7 by Marius Gedminas - find it at!