Bash Shell Script Error Handling
Contents |
and Signals and Traps (Oh My!) - Part 1 by William Shotts, Jr. In this lesson, we're going to look at handling errors during the execution of your scripts. The difference between a good program and a poor one is
Bash Script If Error
often measured in terms of the program's robustness. That is, the program's ability to handle bash shell script exit on error situations in which something goes wrong. Exit status As you recall from previous lessons, every well-written program returns an exit status ftp shell script with error handling when it finishes. If a program finishes successfully, the exit status will be zero. If the exit status is anything other than zero, then the program failed in some way. It is very important to check
Linux Shell Script Error Handling
the exit status of programs you call in your scripts. It is also important that your scripts return a meaningful exit status when they finish. I once had a Unix system administrator who wrote a script for a production system containing the following 2 lines of code: # Example of a really bad idea cd $some_directory rm * Why is this such a bad way of doing it? It's not, if nothing goes
Unix Shell Script Error Handling
wrong. The two lines change the working directory to the name contained in $some_directory and delete the files in that directory. That's the intended behavior. But what happens if the directory named in $some_directory doesn't exist? In that case, the cd command will fail and the script executes the rm command on the current working directory. Not the intended behavior! By the way, my hapless system administrator's script suffered this very failure and it destroyed a large portion of an important production system. Don't let this happen to you! The problem with the script was that it did not check the exit status of the cd command before proceeding with the rm command. Checking the exit status There are several ways you can get and respond to the exit status of a program. First, you can examine the contents of the $? environment variable. $? will contain the exit status of the last command executed. You can see this work with the following: [me] $ true; echo $? 0 [me] $ false; echo $? 1 The true and false commands are programs that do nothing except return an exit status of zero and one, respectively. Using them, we can see how the $? environment variable contains the exit status of the previous program. So
Bash Prompts About Writing Robust Bash Shell Scripts Many people hack together shell scripts quickly to do simple tasks, but these soon take on a life of their own. Unfortunately shell scripts are full of subtle effects which result in scripts failing bash throw error in unusual ways. It's possible to write scripts which minimise these problems. In this
Bash Catch Errors
article, I explain several techniques for writing robust bash scripts. Use set -u How often have you written a script that broke shell script exit code because a variable wasn't set? I know I have, many times. chroot=$1 ... rm -rf $chroot/usr/share/doc If you ran the script above and accidentally forgot to give a parameter, you would have just deleted all http://linuxcommand.org/wss0150.php of your system documentation rather than making a smaller chroot. So what can you do about it? Fortunately bash provides you with set -u, which will exit your script if you try to use an uninitialised variable. You can also use the slightly more readable set -o nounset. david% bash /tmp/shrink-chroot.sh $chroot= david% bash -u /tmp/shrink-chroot.sh /tmp/shrink-chroot.sh: line 3: $1: unbound variable david% Use set -e Every script you write should include set -e at the http://www.davidpashley.com/articles/writing-robust-shell-scripts/ top. This tells bash that it should exit the script if any statement returns a non-true return value. The benefit of using -e is that it prevents errors snowballing into serious issues when they could have been caught earlier. Again, for readability you may want to use set -o errexit. Using -e gives you error checking for free. If you forget to check something, bash will do it or you. Unfortunately it means you can't check $? as bash will never get to the checking code if it isn't zero. There are other constructs you could use: command if [ "$?"-ne 0]; then echo "command failed"; exit 1; fi could be replaced with command || { echo "command failed"; exit 1; } or if ! command; then echo "command failed"; exit 1; fi What if you have a command that returns non-zero or you are not interested in its return value? You can use command || true, or if you have a longer section of code, you can turn off the error checking, but I recommend you use this sparingly. set +e command1 command2 set -e On a slightly related note, by default bash takes the error status of the last item in a pipeline, which may not be what you want. For example, false | true wi
here for a quick overview of the site Help Center Detailed answers to any questions you might have Meta Discuss the workings and policies of this site About Us Learn more about Stack Overflow http://unix.stackexchange.com/questions/21151/error-handling-in-shell-script the company Business Learn more about hiring developers or posting ads with us Unix & Linux Questions Tags Users Badges Unanswered Ask Question _ Unix & Linux Stack Exchange is a question and answer site for users of http://www.linuxjournal.com/magazine/work-shell-handling-errors-and-making-scripts-bulletproof Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute: Sign up Here's how it works: Anybody can ask a question Anybody can answer The best answers are voted up and rise to shell script the top Error handling in shell script up vote 3 down vote favorite I wrote a shell script run_script.sh, which includes a step which creates an empty file run_script.lck. Everytime the shell script was called by the cronjob, it will check for the existence of run_script.lck. If the lock is presence, it indicates that run_script.sh is already running and hasn't finished yet. The run_script.lck file will be deleted in the end of the program. shell script error The trouble is to remove the lock file when the shell script crashed and before it exits. I wrote a line like this: trap "rm -f run_script.lck" EXIT But it will remove the lock file in an undesired condition like this: I execute run_script.sh in shell A, and it is running, the lock file was created. Then I execute it again in shell B, and it said that the script is already running and the script will be aborted. However, because the trap received an EXIT signal including the signal from shell B, which is exiting an aborted script, then it removes the lock file. And the script in shell A is still running, but the lock was deleted and anyone can call another run_script.sh again while there is already one script running. Any idea how to solve this? shell shell-script trap share|improve this question edited Sep 21 '11 at 7:19 jasonwryan 34.7k983132 asked Sep 21 '11 at 1:48 lamwaiman1988 34741124 migrated from stackoverflow.com Sep 21 '11 at 6:38 This question came from our site for professional and enthusiast programmers. add a comment| 3 Answers 3 active oldest votes up vote 4 down vote accepted To illustrate Ignacio's answer (use following protocol: first check if lockfile exists and then install the trap), you can solve the problem like this: $ cat test
the ability to anticipate and respond to error situations gracefully and without anything breaking. Dave explores some of the basic shell script error-handling options. I realize I've been playing a bit fast and loose with my shell scripts over the last few months, because I haven't talked about how to ensure that error conditions don't break things. If you read the Letters section in Linux Journal, you know I haven't covered this topic because, well, you have covered it for me! This topic ranges from the simple to the sophisticated, so let's start with a basic test: the return status after an application or utility is invoked. The Magical $? Sequence Different shells have different return status indicators (the C shell, for example, uses $status), but the most basic is Bash/the Bourne shell, which is what we've focused on since I started writing Work the Shell, and it uses $?. Here's a quick example: #!/bin/sh mkdir / echo "return status is $?" mkdir /tmp/foobar echo "return status is $?" rmdir /tmp/foobar echo "return status is $?" rmdir /tmp echo "return status is $?" exit 0 Run this, and you can see the difference between commands that succeed and those that fail: mkdir: /: Is a directory return status is 1 return status is 0 return status is 0 rmdir: /tmp: Not a directory return status is 1 You can see that when invoking mkdir or rmdir with an error condition, they output an error and—the important part—the $? return status is nonzero. In fact, check out the man page for a typical command like mkdir, and you'll see: “DIAGNOSTICS: The mkdir utility exits 0 on success, and >0 if an error occurs.” In a perfect world, the >0 return code would actually tell you what happened, but although that's true with the functions accessible via software, it's not true for the shell. On t