{"id":187,"date":"2018-10-19T00:00:00","date_gmt":"2018-10-18T16:00:00","guid":{"rendered":"https:\/\/yeslq.com\/201810187.html"},"modified":"2019-05-07T10:43:34","modified_gmt":"2019-05-07T02:43:34","slug":"the-linux-command-line-stay-out-of","status":"publish","type":"post","link":"https:\/\/yeslq.com\/?p=187","title":{"rendered":"The Linux Command Line&#8212;Stay Out Of Trouble"},"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;\">\nNow that our scripts are getting a little more complicated, I want to point out some common mistakes that you might run into. To do this, create the following script called&nbsp;trouble.bash. Be sure to enter it exactly as written.<\/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\nnumber=1\n\nif [ $number = \"1\" ]; then\n    echo \"Number equals 1\"\nelse\n    echo \"Number does not equal 1\"\nfi\n       \n<\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nWhen you run this script, it should output the line &#8220;Number equals 1&#8221; because, well,&nbsp;number&nbsp;equals 1. If you don&#8217;t get the expected output, check your typing; you made a mistake.<\/div>\n<h2 style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif; font-weight: normal;\">\nEmpty Variables<\/h2>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nEdit the script to change line 3 from:<\/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;\">number=1\n       \n<\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nto:<\/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;\">number=\n       \n<\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nand run the script again. This time you should get the following:<\/div>\n<div class=\"display\" style=\"background-color: black; color: lime; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n[me@linuxbox me]$&nbsp;.\/trouble.bash<br \/>\/trouble.bash: [: =: unary operator expected.<br \/>Number does not equal 1<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nAs you can see,&nbsp;bash&nbsp;displayed an error message when we ran the script. You probably think that by removing the &#8220;1&#8221; on line 3 it created a syntax error on line 3, but it didn&#8217;t. Let&#8217;s look at the error message again:<\/div>\n<div class=\"display\" style=\"background-color: black; color: lime; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n.\/trouble.bash: [: =: unary operator expected<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nWe can see that&nbsp;.\/trouble.bash&nbsp;is reporting the error and the error has to do with &#8220;[&#8220;. Remember that &#8220;[&#8221; is an abbreviation for the&nbsp;test&nbsp;shell builtin. From this we can determine that the error is occurring on line 5 not line 3.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nFirst, let me say there is nothing wrong with line 3.&nbsp;number=&nbsp;is perfectly good syntax. You will sometimes want to set a variable&#8217;s value to nothing. You can confirm the validity of this by trying it on the command line:<\/div>\n<div class=\"display\" style=\"background-color: black; color: lime; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n[me@linuxbox me]$&nbsp;number=<br \/>[me@linuxbox me]$<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nSee, no error message. So what&#8217;s wrong with line 5? It worked before.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nTo understand this error, we have to see what the shell sees. Remember that the shell spends a lot of its life expanding text. In line 5, the shell expands the value of&nbsp;number&nbsp;where it sees&nbsp;$number. In our first try (when&nbsp;number=1), the shell substituted 1 for&nbsp;$number&nbsp;like so:<\/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;\">if [ 1 = \"1\" ]; then\n       \n<\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nHowever, when we set number to nothing (number=), the shell saw this after the expansion:<\/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;\">if [ = \"1\" ]; then\n       \n<\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nwhich is an error. It also explains the rest of the error message we received. The &#8220;=&#8221; is a binary operator; that is, it expects two items to operate upon &#8211; one on each side. What the shell is trying to tell us is that there is only one item and there should be a unary operator (like &#8220;!&#8221;) that only operates on a single item.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nTo fix this problem, change line 5 to read:<\/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;\">if [ \"$number\" = \"1\" ]; then\n       \n<\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nNow when the shell performs the expansion it will see:<\/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;\">if [ \"\" = \"1\" ]; then\n       \n<\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nwhich correctly expresses our intent.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nThis brings up an important thing to remember when you are writing your scripts. Consider what happens if a variable is set to equal nothing.<\/div>\n<h2 style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif; font-weight: normal;\">\nMissing Quotes<\/h2>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nEdit line 6 to remove the trailing quote from the end of the line:<\/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;\">   echo \"Number equals 1\n       \n<\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nand run the script again. You should get this:<\/div>\n<div class=\"display\" style=\"background-color: black; color: lime; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n[me@linuxbox me]$&nbsp;.\/trouble.bash<br \/>.\/trouble.bash: line 8: unexpected EOF while looking for matching &#8220;<br \/>.\/trouble.bash: line 10 syntax error: unexpected end of file<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nHere we have another case of a mistake in one line causing a problem later in the script. What happens is the shell keeps looking for the closing quotation mark to tell it where the end of the string is, but runs into the end of the file before it finds it.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nThese errors can be a real pain to find in a long script. This is one reason you should test your scripts frequently when you are writing them so there is less new code to test. I also find that text editors with syntax highlighting make these kinds of bugs easier to find.<\/div>\n<h2 style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif; font-weight: normal;\">\nIsolating Problems<\/h2>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nFinding bugs in your programs can sometimes be very difficult and frustrating. Here are a couple of techniques that you will find useful:<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\n<b>Isolate blocks of code by &#8220;commenting them out.&#8221;<\/b>&nbsp;This trick involves putting comment characters at the beginning of lines of code to stop the shell from reading them. Frequently, you will do this to a block of code to see if a particular problem goes away. By doing this, you can isolate which part of a program is causing (or not causing) a problem.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nFor example, when we were looking for our missing quotation we could have done 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;\">#!\/bin\/bash\n\nnumber=1\n\nif [ $number = \"1\" ]; then\n    echo \"Number equals 1\n#else\n#   echo \"Number does not equal 1\"\nfi\n       \n<\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nBy commenting out the&nbsp;else&nbsp;clause and running the script, we could show that the problem was not in the&nbsp;else&nbsp;clause even though the error message suggested that it was.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\n<b>Use echo commands to verify your assumptions.<\/b>&nbsp;As you gain experience tracking down bugs, you will discover that bugs are often not where you first expect to find them. A common problem will be that you will make a false assumption about the performance of your program. You will see a problem develop at a certain point in your program and assume that the problem is there. This is often incorrect, as we have seen. To combat this, you should place&nbsp;echocommands in your code while you are debugging, to produce messages that confirm the program is doing what is expected. There are two kinds of messages that you should insert.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nThe first type simply announces that you have reached a certain point in the program. We saw this in our earlier discussion on stubbing. It is useful to know that program flow is happening the way we expect.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nThe second type displays the value of a variable (or variables) used in a calculation or test. You will often find that a portion of your program will fail because something that you assumed was correct earlier in your program is, in fact, incorrect and is causing your program to fail later on.<\/div>\n<h2 style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif; font-weight: normal;\">\nWatching Your Script Run<\/h2>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nIt is possible to have&nbsp;bash&nbsp;show you what it is doing when you run your script. To do this, add a &#8220;-x&#8221; to the first line of your script, like 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;\">#!\/bin\/bash -x\n       \n<\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nNow, when you run your script, bash will display each line (with expansions performed) as it executes it. This technique is called&nbsp;<i>tracing<\/i>. Here is what it looks like:<\/div>\n<div class=\"display\" style=\"background-color: black; color: lime; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n[me@linuxbox me]$&nbsp;.\/trouble.bash<br \/>+ number=1<br \/>+ &#8216;[&#8216; 1 = 1 &#8216;]&#8217;<br \/>+ echo &#8216;Number equals 1&#8217;<br \/>Number equals 1<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">\nAlternately, you can use the&nbsp;set&nbsp;command within your script to turn tracing on and off. Use&nbsp;set -x&nbsp;to turn tracing on and&nbsp;set +x&nbsp;to turn tracing off. For example.:<\/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\nnumber=1\n\nset -x\nif [ $number = \"1\" ]; then\n    echo \"Number equals 1\"\nelse\n    echo \"Number does not equal 1\"\nfi\nset +x\n       <\/pre>\n<\/div>\n<p><\/span><\/div>\n","protected":false},"excerpt":{"rendered":"<p>The Linux Command Line&nbsp;by William Shotts Now that  &#8230; <a title=\"The Linux Command Line&#8212;Stay Out Of Trouble\" class=\"read-more\" href=\"https:\/\/yeslq.com\/?p=187\" aria-label=\"\u9605\u8bfb The Linux Command Line&#8212;Stay Out Of Trouble\">\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":[51,52,53],"class_list":["post-187","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-linux","tag-shell","tag-the-linux-command-line"],"_links":{"self":[{"href":"https:\/\/yeslq.com\/index.php?rest_route=\/wp\/v2\/posts\/187","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=187"}],"version-history":[{"count":1,"href":"https:\/\/yeslq.com\/index.php?rest_route=\/wp\/v2\/posts\/187\/revisions"}],"predecessor-version":[{"id":317,"href":"https:\/\/yeslq.com\/index.php?rest_route=\/wp\/v2\/posts\/187\/revisions\/317"}],"wp:attachment":[{"href":"https:\/\/yeslq.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=187"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/yeslq.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=187"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/yeslq.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=187"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}