Linux Shell Scripting
The course is part of this learning path
In this course, you'll learn about the different types of input and output and how to redirect and control those types of input and output. We'll then walk through an exercise that focuses on creating users on a Linux system - this exercise builds upon the exercise that we did in the Password Generation and Shell Script Arguments course.
This course is part of the Linux Shell Scripting learning path. To follow along with this course, you can download all the necessary resources here.
- Learn about the different types of input and output and how to redirect and control those types of input and output
- Gain practical experience of how to create users on Linux
- Anyone who wants to learn Linux shell scripting
- Linux system administrators, developers, or programmers
To get the most out of this course, you should have a basic understanding of the Linux command line.
Welcome to this exercise walkthrough. Now the script you're going to write today is very, closely based on the previous script you wrote. As a matter of fact, we don't have to do any new coding if we don't want to, you can simply update that existing script to conform to the new requirements that you have now. And speaking of those new requirements the help desk, in our scenario, has been using your script. And they notice that there are some extra output that they don't need, that they don't care to see. It really doesn't make any sense to them. So they want you to make that output disappear. And of course, you know that output comes from the password command PASSWD, and that you're going to have to use IO redirection to redirect that output to the null device. And so you start to think about, what else you can do to this script with IO redirection and you come up with that you could actually conform to standard convention, standard Linux programming conventions, by redirecting error messages to standard error and so on. So with that in mind, let's look at just the couple of changes that we're going to make with this script. So we're going to change the name of the script, from add new local user to add newer local user. Now in the real world, I wouldn't necessarily change the name. I would just make these couple of updates to that script, and place of course test it first and then put it into production. However, just for the sake of, distinguishing what exercise and what script you're working on if you need help and so on, I'm just gonna use a new name here so that we just get a unique script, for each exercise that we're working on. So again, in the real world, you can keep the same name if you'd like. Now really all the other requirements are still in play. Like you wanna make sure that the script is run with super user privileges, but the only difference there is, that when you display some help or an error message, when they don't, then what you wanna do is send that output to standard error instead of standard output like we've been doing. And that's gonna be the same thing for all the error statuses that we're gonna display in our script. So that's really the main thing that we're gonna be changing here. So here I am on my local system with my terminal open, and I'm going to navigate to the class folder. From here I'm going to navigate to the Vagrant project that we're using, for this set of scripts, and that's local users. And then I'm going to bring this virtual machine up and then connect to it. Now I'm going to move into the shared folder of forward slash vagrant. And then here I'm actually going to copy the previous script we used, and just copy it to this new name that we're gonna work on today. Of course you can write this entire script from scratch again if you would like just to give yourself some extra practice. But here for the walkthrough, I'm just going to, show the couple of changes that you need to make from the previous script, in order to, conform to these new requirements that we've come up with here. So what I'm gonna do is just start at the very top of the script and work my way down, looking for any changes that I need to make. So here I see an exit status of one, and an echo statement previously before it. So that's really our error message when we're exiting with a one. So what we need to do is send this output from the echo command, to standard error, right now by default, it's going to be displayed to standard output. And so we can do this with a greater than symbol, and ampersand, and two. Now realize here that the greater than symbol, assumes standard output. So it's also the same as this. If we wanna be explicit and specify a file descriptor one for standard output. I'm not gonna do that, I'm just gonna delete that, and then use this syntax, the greater than, ampersand, too. And of course, as you know, an ampersand right after a redirection operator, implies that you're using a file descriptor, instead of a file name. So again, file descriptor two is associated with standard error. So that makes the standard output here, the echo would generate, be displayed on standard error, gonna keep working my way down here. Here I come to another exit statement here, and I'm just gonna do the same thing. We're just gonna send all this output to standard error. I'm gonna redraw my screen with a cursor at the top, and then just keep on working down here. So assigning variables it's not gonna call us any output. The shift command won't either. The output of this command is stored in a variable, so it's not getting displayed anywhere. Okay, this is the command that could possibly, generate output. Now let me go down in the script a little bit here. You can see that we're actually checking, for its exit status down here. So we don't necessarily need to see the output generated by this command. So actually what I'm gonna do here is ignore all the output. I don't need to see the standard output, or the standard error from this command. So to redirect both standard output and standard error, we'll use ampersand, greater than sign. And then we're gonna send that to the dev, null device. And that's just gonna throw away anything that it gets. So all the output generated by this command will not be displayed to the user, running the script. Again, we come to another exit statement, and that means this echo command right above it, is going to be an error message. So we're going to send this to standard error. Okay, so this password command, we know generates some output. So what we wanna do is, send that output to dev, null, so the user doesn't see this output. So again we're gonna use ampersand greater than, and send that to the dev, null device. We're doing a check for an exit status, of the password command, and then we're gonna display an error if we get an error. So that means this is an error message. It needs to be displayed on standard error. Now we have a another password command. Again, the help desk users don't wanna see these messages. So we're just gonna send all that output to dev, null. Since we haven't generated any output in our script here, there's no need for a blank line, to separate the information that we're gonna display for the user, between the output of the previous commands. So I'm just going to get rid of this echo statement. And then the rest of our script here, generates the output that we want the user to see. So let's go ahead and save our changes and then, we'll check the permissions on the script. Now, when you copy a script, it gets the same permissions as the script it was copied from. But, we'll go ahead and check the permissions here, just to be thorough. Okay, it's 755, so that looks good. You can see the X's there, and all three sets of permission. So anyone can execute this script. Now obviously, if they don't run it with pseudo privileges, they're going to get an error message. But again, the executable bid is there. If you created this script from scratch, then you're going to need to 755, your script. So now that we have our changes in place, or a new script written, let's go ahead and test it. So we're going to, let's add a new user here, and we'll just call this username Turing. And the comment will be Alan Turing and hit enter. So now you can see that the only thing is displayed is the username, the password, and the host that this user was created on. None of that extra output from the password commands were displayed on the screen. And this is exactly what we're looking for. So I'm gonna go ahead and create our other users here. We have, woz. Again, the display is just the information that is needed, by the people running the command. We'll create another user here, call this Moore, or Gordon Moore. Okay, we've created three accounts. Now let's go ahead and see if those accounts were added to the Etsy password file. We can do that by just telling the Etsy password file or actually I'm gonna do, a dash three for the last three lines of the Etsy password file. Okay, there you can see our users, Turing, Woz and Moore. Now I'm just going to switch to an account to be thorough here, to make sure that, it still forces the password expiration and prompts us for a new password on login. As a matter of fact, before I do this, I need to go back up here and actually copy the password. Okay. It's asking for our current password, and then a new password. Okay, that looks like it worked. And we're all done with this user. So we'll just hit exit here, and return to our normal Vagrant user. So the core functionality of our script is still in place. It creates users, it expires their passwords and so on. So now what we wanna do is actually test our new functionality. So one way to do that is to make our script generated error. And we can do that by not running it with, super user privileges. Okay, we get a message on our screen. Of course you can't tell if that message is standard input or standard output, but we'll get to that in just a second. Okay, it prints a message to our screen. Now let's check the exit status of the command. Sure enough. It's an exit status of one, which is exactly what we want. Now let's do the same thing again, but this time let's redirect the standard output and standard error to different places. And then check those to see what is going where. Now because by default standard output and standard error are both displayed to our screen, we can't necessarily tell what standard output or standard error just by looking. So what we're going to do is redirect standard output, to a file called std.out. We could have named that anything, I'm just gonna use the kind of standard abbreviation here. Again, standard error is gonna go to a file. I'm just going to name std.err. Again, you can name it, any file name you want. So all the output, either goes to standard out or standard error. So let's examine the standard out file, and there's nothing in that file. And if we look at standard error, then our error message is in that file. So we know that the echo statement is displaying its output to standard error. And that's exactly what we want. So let's go ahead and remove these files. Let's test for another error condition that our script checks for. We'll actually run the script here, but we won't supply any arguments. So we'll hit enter and sure enough we get an exit status here of one, and now let's run the same kind of test. We'll just send the standard output to standard out and the standard error, to a standard error file. We'll look to see if it generated in the standard output. It did not. So all the error messages went to standard error, and that's exactly what we want our script to do. I'm gonna go ahead and clean up here. All right, now that brings us to the end of this exercise. So we've made our changes. Our error messages are now being displayed to standard error instead of standard out. And all that output that was generated from those other commands, are now hidden from the user. Since I'm done for the day, I'm gonna exit out of the virtual machine and then go ahead and halt it.
Jason is the founder of the Linux Training Academy as well as the author of "Linux for Beginners" and "Command Line Kung Fu." He has over 20 years of professional Linux experience, having worked for industry leaders such as Hewlett-Packard, Xerox, UPS, FireEye, and Amazon.com. Nothing gives him more satisfaction than knowing he has helped thousands of IT professionals level up their careers through his many books and courses.