{"id":182,"date":"2018-10-22T00:00:00","date_gmt":"2018-10-21T16:00:00","guid":{"rendered":"https:\/\/yeslq.com\/201810182.html"},"modified":"2019-05-07T10:43:40","modified_gmt":"2019-05-07T02:43:40","slug":"the-linux-command-line-errors-and","status":"publish","type":"post","link":"https:\/\/yeslq.com\/?p=182","title":{"rendered":"The Linux Command Line&#8212;Errors And Signals And Traps (Oh My!) &#8211; Part 1"},"content":{"rendered":"<h1 style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif; font-weight: normal;\">\n<i style=\"font-size: x-small;\"><a href=\"http:\/\/linuxcommand.org\/tlcl.php\" style=\"color: #002740;\">The Linux Command Line&nbsp;<\/a><\/i><span style=\"font-size: xx-small;\">by William Shotts<\/span><\/h1>\n<div>\n<span style=\"font-size: xx-small;\"><br \/><\/span><\/div>\n<div>\n<span style=\"font-size: xx-small;\"><\/p>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nIn this lesson, we&#8217;re going to look at handling errors during the execution of your scripts.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nThe difference between a good program and a poor one is often measured in terms of the program&#8217;s&nbsp;<i>robustness<\/i>. That is, the program&#8217;s ability to handle situations in which something goes wrong.<\/div>\n<h2 style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif; font-weight: normal;\">\nExit Status<\/h2>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nAs you recall from previous lessons, every well-written program returns an exit status 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.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nIt is very important to check 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:<\/div>\n<div class=\"codeexample\" style=\"background-color: #e0e0e0; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n<pre style=\"font-family: courier, lucidatypewriter, monospace;\"># Example of a really bad idea\n\ncd $some_directory\nrm *<\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nWhy is this such a bad way of doing it? It&#8217;s not, if nothing goes wrong. The two lines change the working directory to the name contained in&nbsp;$some_directoryand delete the files in that directory. That&#8217;s the intended behavior. But what happens if the directory named in&nbsp;$some_directory&nbsp;doesn&#8217;t exist? In that case, the&nbsp;cd&nbsp;command will fail and the script executes the&nbsp;rm&nbsp;command on the current working directory. Not the intended behavior!<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nBy the way, my hapless system administrator&#8217;s script suffered this very failure and it destroyed a large portion of an important production system. Don&#8217;t let this happen to you!<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nThe problem with the script was that it did not check the exit status of the&nbsp;cd&nbsp;command before proceeding with the&nbsp;rm&nbsp;command.<\/div>\n<h2 style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif; font-weight: normal;\">\nChecking The Exit Status<\/h2>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nThere are several ways you can get and respond to the exit status of a program. First, you can examine the contents of the&nbsp;$?&nbsp;environment variable.&nbsp;$?&nbsp;will contain the exit status of the last command executed. You can see this work with the following:<\/div>\n<div class=\"display\" style=\"background-color: black; color: lime; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n<pre style=\"font-family: courier, lucidatypewriter, monospace;\">[me] $ true; echo $?\n0\n[me] $ false; echo $?\n1<\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nThe&nbsp;true&nbsp;and&nbsp;false&nbsp;commands are programs that do nothing except return an exit status of zero and one, respectively. Using them, we can see how the&nbsp;$?environment variable contains the exit status of the previous program.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nSo to check the exit status, we could write the script this way:<\/div>\n<div class=\"codeexample\" style=\"background-color: #e0e0e0; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n<pre style=\"font-family: courier, lucidatypewriter, monospace;\"># Check the exit status\n\ncd $some_directory\nif [ \"$?\" = \"0\" ]; then\n rm *\nelse\n echo \"Cannot change directory!\" 1&gt;&amp;2\n exit 1\nfi\n<\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nIn this version, we examine the exit status of the&nbsp;cd&nbsp;command and if it&#8217;s not zero, we print an error message on standard error and terminate the script with an exit status of 1.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nWhile this is a working solution to the problem, there are more clever methods that will save us some typing. The next approach we can try is to use the&nbsp;ifstatement directly, since it evaluates the exit status of commands it is given.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nUsing&nbsp;if, we could write it this way:<\/div>\n<div class=\"codeexample\" style=\"background-color: #e0e0e0; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n<pre style=\"font-family: courier, lucidatypewriter, monospace;\"># A better way\n\nif cd $some_directory; then\n rm *\nelse\n echo \"Could not change directory! Aborting.\" 1&gt;&amp;2\n exit 1\nfi\n<\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nHere we check to see if the&nbsp;cd&nbsp;command is successful. Only then does&nbsp;rm&nbsp;get executed; otherwise an error message is output and the program exits with a code of 1, indicating that an error has occurred.<\/div>\n<h2 style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif; font-weight: normal;\">\nAn Error Exit Function<\/h2>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nSince we will be checking for errors often in our programs, it makes sense to write a function that will display error messages. This will save more typing and promote laziness.<\/div>\n<div class=\"codeexample\" style=\"background-color: #e0e0e0; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n<pre style=\"font-family: courier, lucidatypewriter, monospace;\"># An error exit function\n\nerror_exit()\n{\n echo \"$1\" 1&gt;&amp;2\n exit 1\n}\n\n# Using error_exit\n\nif cd $some_directory; then\n rm *\nelse\n error_exit \"Cannot change directory!  Aborting.\"\nfi\n<\/pre>\n<\/div>\n<h2 style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif; font-weight: normal;\">\nAND And OR Lists<\/h2>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nFinally, we can further simplify our script by using the AND and OR control operators. To explain how they work, I will quote from the&nbsp;<a href=\"http:\/\/linuxcommand.org\/man_pages\/bash1.html\" style=\"color: #002740;\">bash<\/a>&nbsp;man page:<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\n&#8220;The control operators &amp;&amp; and || denote AND lists and OR lists, respectively. An AND list has the form<\/div>\n<div class=\"codeexample\" style=\"background-color: #e0e0e0; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\ncommand1 &amp;&amp; command2<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\ncommand2&nbsp;is executed if,&nbsp;<i>and only if<\/i>,&nbsp;command1&nbsp;returns an exit status of zero.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nAn OR list has the form<\/div>\n<div class=\"codeexample\" style=\"background-color: #e0e0e0; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\ncommand1 || command2<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\ncommand2&nbsp;is executed if, and only if,&nbsp;command1&nbsp;returns a non-zero exit status. The exit status of AND and OR lists is the exit status of the last command executed in the list.&#8221;<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nAgain, we can use the&nbsp;true&nbsp;and&nbsp;false&nbsp;commands to see this work:<\/div>\n<div class=\"display\" style=\"background-color: black; color: lime; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n<pre style=\"font-family: courier, lucidatypewriter, monospace;\">[me] $ true || echo \"echo executed\"\n[me] $ false || echo \"echo executed\"\necho executed\n[me] $ true &amp;&amp; echo \"echo executed\"\necho executed\n[me] $ false &amp;&amp; echo \"echo executed\"\n[me] $<\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nUsing this technique, we can write an even simpler version:<\/div>\n<div class=\"codeexample\" style=\"background-color: #e0e0e0; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n<pre style=\"font-family: courier, lucidatypewriter, monospace;\"># Simplest of all\n\ncd $some_directory || error_exit \"Cannot change directory! Aborting\"\nrm *\n<\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nIf an exit is not required in case of error, then you can even do this:<\/div>\n<div class=\"codeexample\" style=\"background-color: #e0e0e0; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n<pre style=\"font-family: courier, lucidatypewriter, monospace;\"># Another way to do it if exiting is not desired\n\ncd $some_directory &amp;&amp; rm *\n<\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nI want to point out that even with the defense against errors we have introduced in our example for the use of&nbsp;cd, this code is still vulnerable to a common programming error, namely, what happens if the name of the variable containing the name of the directory is misspelled? In that case, the shell will interpret the variable as empty and the&nbsp;cd&nbsp;succeed, but it will change directories to the user&#8217;s home directory, so beware!<\/div>\n<h2 style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif; font-weight: normal;\">\nImproving The Error Exit Function<\/h2>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nThere are a number of improvements that we can make to the&nbsp;error_exit&nbsp;function. I like to include the name of the program in the error message to make clear where the error is coming from. This becomes more important as your programs get more complex and you start having scripts launching other scripts, etc. Also, note the inclusion of the&nbsp;LINENO&nbsp;environment variable which will help you identify the exact line within your script where the error occurred.<\/div>\n<div class=\"codeexample\" style=\"background-color: #e0e0e0; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n<pre style=\"font-family: courier, lucidatypewriter, monospace;\">#!\/bin\/bash\n\n# A slicker error handling routine\n\n# I put a variable in my scripts named PROGNAME which\n# holds the name of the program being run.  You can get this\n# value from the first item on the command line ($0).\n\nPROGNAME=$(basename $0)\n\nerror_exit()\n{\n\n# ----------------------------------------------------------------\n# Function for exit due to fatal program error\n#  Accepts 1 argument:\n#   string containing descriptive error message\n# ----------------------------------------------------------------\n\n\n echo \"${PROGNAME}: ${1:-\"Unknown Error\"}\" 1&gt;&amp;2\n exit 1\n}\n\n# Example call of the error_exit function.  Note the inclusion\n# of the LINENO environment variable.  It contains the current\n# line number.\n\necho \"Example of error with line number and message\"\nerror_exit \"$LINENO: An error has occurred.\"\n<\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nThe use of the curly braces within the&nbsp;error_exit&nbsp;function is an example of&nbsp;<i>parameter expansion<\/i>. You can surround a variable name with curly braces (as with&nbsp;${PROGNAME}) if you need to be sure it is separated from surrounding text. Some people just put them around every variable out of habit. That usage is simply a style thing. The second use,&nbsp;${1:-&#8220;Unknown Error&#8221;}&nbsp;means that if parameter 1 ($1) is undefined, substitute the string &#8220;Unknown Error&#8221; in its place. Using parameter expansion, it is possible to perform a number of useful string manipulations. You can read more about parameter expansion in the&nbsp;<a href=\"http:\/\/linuxcommand.org\/lc3_man_pages\/bash1.html\" style=\"color: #002740;\">bash<\/a>&nbsp;man page under the topic &#8220;EXPANSIONS&#8221;.<\/div>\n<div class=\"pagenav\" style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif; padding: 1em;\">\n<\/div>\n<p><\/span><\/div>\n","protected":false},"excerpt":{"rendered":"<p>The Linux Command Line&nbsp;by William Shotts In this l &#8230; <a title=\"The Linux Command Line&#8212;Errors And Signals And Traps (Oh My!) &#8211; Part 1\" class=\"read-more\" href=\"https:\/\/yeslq.com\/?p=182\" aria-label=\"\u9605\u8bfb The Linux Command Line&#8212;Errors And Signals And Traps (Oh My!) &#8211; Part 1\">\u9605\u8bfb\u66f4\u591a<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[50,51,52,53],"class_list":["post-182","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-error","tag-linux","tag-shell","tag-the-linux-command-line"],"_links":{"self":[{"href":"https:\/\/yeslq.com\/index.php?rest_route=\/wp\/v2\/posts\/182","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/yeslq.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/yeslq.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/yeslq.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/yeslq.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=182"}],"version-history":[{"count":1,"href":"https:\/\/yeslq.com\/index.php?rest_route=\/wp\/v2\/posts\/182\/revisions"}],"predecessor-version":[{"id":322,"href":"https:\/\/yeslq.com\/index.php?rest_route=\/wp\/v2\/posts\/182\/revisions\/322"}],"wp:attachment":[{"href":"https:\/\/yeslq.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=182"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/yeslq.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=182"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/yeslq.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=182"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}