{"id":33,"date":"2018-10-22T20:00:00","date_gmt":"2018-10-22T12:00:00","guid":{"rendered":""},"modified":"2018-11-11T16:10:57","modified_gmt":"2018-11-11T08:10:57","slug":"the-linux-command-line-errors-and-signals-and-traps-oh-my-part-2","status":"publish","type":"post","link":"https:\/\/yeslq.com\/?p=33","title":{"rendered":"The Linux Command Line&#8212;Errors And Signals And Traps (Oh My!) &#8211; Part 2"},"content":{"rendered":"<h1 style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif; font-weight: normal;\"><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><span style=\"font-size: xx-small;\"><br \/><\/span><\/div>\n<div><span style=\"font-size: xx-small;\"><\/p>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">Errors are not the only way that a script can terminate unexpectedly. You also have to be concerned with signals. Consider the following program:<\/div>\n<div style=\"background-color: #e0e0e0; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n<pre style=\"font-family: courier, lucidatypewriter, monospace;\"><tt style=\"font-family: courier, lucidatypewriter, monospace;\">#!\/bin\/bash<br \/><br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">echo<\/tt> \"this script will endlessly loop until you stop it\"<br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">while<\/tt> true; <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">do<\/tt><br \/> <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">:<\/tt> # Do nothing<br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">done<\/tt><br \/><\/tt><\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">After you launch this script it will appear to hang. Actually, like most programs that appear to hang, it is really stuck inside a loop. In this case, it is waiting for the&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">true<\/tt>&nbsp;command to return a non-zero exit status, which it never does. Once started, the script will continue until bash receives a signal that will stop it. You can send such a signal by typing Ctrl-c which is the signal called SIGINT (short for SIGnal INTerrupt).<\/div>\n<h2 style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif; font-weight: normal;\">Cleaning Up After Yourself<\/h2>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">Okay, so a signal can come along and make your script terminate. Why does it matter? Well, in many cases it doesn&#8217;t matter and you can ignore signals, but in some cases it will matter.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">Let&#8217;s take a look at another script:<\/div>\n<div style=\"background-color: #e0e0e0; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n<pre style=\"font-family: courier, lucidatypewriter, monospace;\"><tt style=\"font-family: courier, lucidatypewriter, monospace;\">#!\/bin\/bash<br \/><br \/># Program to print a text file with headers and footers<br \/><br \/>TEMP_FILE=\/tmp\/printfile.txt<br \/><br \/>pr $1 &gt; $TEMP_FILE<br \/><br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">echo<\/tt> -n \"Print file? [y\/n]: \"<br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">read<\/tt><br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">if<\/tt> <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">[<\/tt> \"$REPLY\" = \"y\" <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">];<\/tt> <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">then<\/tt><br \/> lpr $TEMP_FILE<br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">fi<\/tt><br \/><\/tt><\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">This script processes a text file specified on the command line with the&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\"><a href=\"http:\/\/linuxcommand.org\/man_pages\/pr1.html\" style=\"color: #002740;\">pr<\/a><\/tt>&nbsp;command and stores the result in a temporary file. Next, it asks the user if they want to print the file. If the user types &#8220;y&#8221;, then the temporary file is passed to the&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\"><a href=\"http:\/\/linuxcommand.org\/man_pages\/lpr1.html\" style=\"color: #002740;\">lpr<\/a><\/tt>&nbsp;program for printing (you may substitute&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">less<\/tt>&nbsp;for&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">lpr<\/tt>&nbsp;if you don&#8217;t actually have a printer attached to your system.)<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">Now, I admit this script has a lot of design problems. While it needs a file name passed on the command line, it doesn&#8217;t check that it got one, and it doesn&#8217;t check that the file actually exists. But the problem I want to focus on here is the fact that when the script terminates, it leaves behind the temporary file.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">Good practice would dictate that we delete the temporary file&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">$TEMP_FILE<\/tt>&nbsp;when the script terminates. This is easily accomplished by adding the following to the end of the script:<\/div>\n<div style=\"background-color: #e0e0e0; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n<pre style=\"font-family: courier, lucidatypewriter, monospace;\"><tt style=\"font-family: courier, lucidatypewriter, monospace;\">rm $TEMP_FILE<br \/><\/tt><\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">This would seem to solve the problem, but what happens if the user types ctrl-c when the &#8220;Print file? [y\/n]:&#8221; prompt appears? The script will terminate at the&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">read<\/tt>&nbsp;command and the&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">rm<\/tt>&nbsp;command is never executed. Clearly, we need a way to respond to signals such as SIGINT when the Ctrl-c key is typed.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">Fortunately, bash provides a method to perform commands if and when signals are received.<\/div>\n<h2 style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif; font-weight: normal;\">trap<\/h2>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">The&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">trap<\/tt>&nbsp;command allows you to execute a command when a signal is received by your script. It works like this:<\/div>\n<div style=\"background-color: #e0e0e0; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n<pre style=\"font-family: courier, lucidatypewriter, monospace;\"><tt style=\"font-family: courier, lucidatypewriter, monospace;\"><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">trap<\/tt> arg signals<br \/><\/tt><\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">&#8220;signals&#8221; is a list of signals to intercept and &#8220;arg&#8221; is a command to execute when one of the signals is received. For our printing script, we might handle the signal problem this way:<\/div>\n<div style=\"background-color: #e0e0e0; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n<pre style=\"font-family: courier, lucidatypewriter, monospace;\"><tt style=\"font-family: courier, lucidatypewriter, monospace;\">#!\/bin\/bash<br \/><br \/># Program to print a text file with headers and footers<br \/><br \/>TEMP_FILE=\/tmp\/printfile.txt<br \/><br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">trap<\/tt> \"rm $TEMP_FILE; exit\" SIGHUP SIGINT SIGTERM<br \/><br \/>pr $1 &gt; $TEMP_FILE<br \/><br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">echo<\/tt> -n \"Print file? [y\/n]: \"<br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">read<\/tt><br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">if<\/tt> <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">[<\/tt> \"$REPLY\" = \"y\" <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">];<\/tt> <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">then<\/tt><br \/> lpr $TEMP_FILE<br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">fi<\/tt><br \/>rm $TEMP_FILE<br \/><\/tt><\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">Here we have added a&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">trap<\/tt>&nbsp;command that will execute &#8220;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">rm $TEMP_FILE<\/tt>&#8221; if any of the listed signals is received. The three signals listed are the most common ones that you will encounter, but there are many more that can be specified. For a complete list, type &#8220;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">trap -l<\/tt>&#8220;. In addition to listing the signals by name, you may alternately specify them by number.<\/div>\n<div style=\"background-color: #e0e0e0; font-family: verdana, arial, helvetica, sans-serif; padding: 1em;\">\n<h2 style=\"font-weight: normal;\">Signal 9 From Outer Space<\/h2>\n<p>There is one signal that you cannot trap: SIGKILL or signal 9. The kernel immediately terminates any process sent this signal and no signal handling is performed. Since it will always terminate a program that is stuck, hung, or otherwise screwed up, it is tempting to think that it&#8217;s the easy way out when you have to get something to stop and go away. Often you will see references to the following command which sends the SIGKILL signal:<br \/><tt style=\"font-family: courier, lucidatypewriter, monospace;\">kill -9<\/tt>However, despite its apparent ease, you must remember that when you send this signal, no processing is done by the application. Often this is OK, but with many programs it&#8217;s not. In particular, many complex programs (and some not-so-complex) create&nbsp;<i>lock files<\/i>&nbsp;to prevent multiple copies of the program from running at the same time. When a program that uses a lock file is sent a SIGKILL, it doesn&#8217;t get the chance to remove the lock file when it terminates. The presence of the lock file will prevent the program from restarting until the lock file is manually removed.<br \/>Be warned. Use SIGKILL as a last resort.<\/div>\n<h2 style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif; font-weight: normal;\">A clean_up Function<\/h2>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">While the trap command has solved the problem, we can see that it has some limitations. Most importantly, it will only accept a single string containing the command to be performed when the signal is received. You could get clever and use &#8220;;&#8221; and put multiple commands in the string to get more complex behavior, but frankly, it&#8217;s ugly. A better way would be to create a function that is called when you want to perform any actions at the end of your script. In my scripts, I call this function&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">clean_up<\/tt>.<\/div>\n<div style=\"background-color: #e0e0e0; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n<pre style=\"font-family: courier, lucidatypewriter, monospace;\"><tt style=\"font-family: courier, lucidatypewriter, monospace;\">#!\/bin\/bash<br \/><br \/># Program to print a text file with headers and footers<br \/><br \/>TEMP_FILE=\/tmp\/printfile.txt<br \/><br \/>clean_up() {<br \/><br \/> # Perform program exit housekeeping<br \/> rm $TEMP_FILE<br \/> <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">exit<\/tt><br \/>}<br \/><br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">trap<\/tt> clean_up SIGHUP SIGINT SIGTERM<br \/><br \/>pr $1 &gt; $TEMP_FILE<br \/><br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">echo<\/tt> -n \"Print file? [y\/n]: \"<br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">read<\/tt><br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">if<\/tt> <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">[<\/tt> \"$REPLY\" = \"y\" <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">];<\/tt> <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">then<\/tt><br \/> lpr $TEMP_FILE<br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">fi<\/tt><br \/>clean_up<br \/><\/tt><\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">The use of a clean up function is a good idea for your error handling routines too. After all, when your program terminates (for whatever reason), you should clean up after yourself. Here is finished version of our program with improved error and signal handling:<\/div>\n<div style=\"background-color: #e0e0e0; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n<pre style=\"font-family: courier, lucidatypewriter, monospace;\"><tt style=\"font-family: courier, lucidatypewriter, monospace;\">#!\/bin\/bash<br \/><br \/># Program to print a text file with headers and footers<br \/><br \/># Usage: printfile file<br \/><br \/># Create a temporary file name that gives preference<br \/># to the user's local tmp directory and has a name<br \/># that is resistant to \"temp race attacks\"<br \/><br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">if<\/tt> <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">[<\/tt> -d \"~\/tmp\" <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">];<\/tt> <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">then<\/tt><br \/> TEMP_DIR=~\/tmp<br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">else<\/tt><br \/> TEMP_DIR=\/tmp<br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">fi<\/tt><br \/>TEMP_FILE=$TEMP_DIR\/printfile.$$.$RANDOM<br \/>PROGNAME=$(basename $0)<br \/><br \/>usage() {<br \/><br \/> # Display usage message on standard error<br \/> <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">echo<\/tt> \"Usage: $PROGNAME file\" 1&gt;&amp;2<br \/>}<br \/><br \/>clean_up() {<br \/><br \/> # Perform program exit housekeeping<br \/> # Optionally accepts an exit status<br \/> rm -f $TEMP_FILE<br \/> <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">exit<\/tt> $1<br \/>}<br \/><br \/>error_exit() {<br \/><br \/> # Display error message and exit<br \/> <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">echo<\/tt> \"${PROGNAME}: ${1:-\"Unknown Error\"}\" 1&gt;&amp;2<br \/> clean_up 1<br \/>}<br \/><br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">trap<\/tt> clean_up SIGHUP SIGINT SIGTERM<br \/><br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">if<\/tt> <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">[<\/tt> $# != \"1\" <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">];<\/tt> <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">then<\/tt><br \/> usage<br \/> error_exit \"one file to print must be specified\"<br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">fi<\/tt><br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">if<\/tt> <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">[<\/tt> ! -f \"$1\" <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">];<\/tt> <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">then<\/tt><br \/> error_exit \"file $1 cannot be read\"<br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">fi<\/tt><br \/><br \/>pr $1 &gt; $TEMP_FILE || error_exit \"cannot format file\"<br \/><br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">echo<\/tt> -n \"Print file? [y\/n]: \"<br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">read<\/tt><br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">if<\/tt> <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">[<\/tt> \"$REPLY\" = \"y\" <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">];<\/tt> <tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">then<\/tt><br \/> lpr $TEMP_FILE || error_exit \"cannot print file\"<br \/><tt style=\"font-family: courier, lucidatypewriter, monospace; font-weight: bold;\">fi<\/tt><br \/>clean_up<br \/><\/tt><\/pre>\n<\/div>\n<h2 style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif; font-weight: normal;\">Creating Safe Temporary Files<\/h2>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">In the program above, there a number of steps taken to help secure the temporary file used by this script. It is a Unix tradition to use a directory called&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">\/tmp<\/tt>to place temporary files used by programs. Everyone may write files into this directory. This naturally leads to some security concerns. If possible, avoid writing files in the&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">\/tmp<\/tt>&nbsp;directory. The preferred technique is to write them in a local directory such as&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">~\/tmp<\/tt>&nbsp;(a tmp subdirectory in the user&#8217;s home directory.) If you must write files in&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">\/tmp<\/tt>, you must take steps to make sure the file names are not predictable. Predictable file names allow an attacker to create symbolic links to other files that the attacker wants you to overwrite.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">A good file name will help you figure out what wrote the file, but will not be entirely predictable. In the script above, the following line of code created the temporary file&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">$TEMP_FILE<\/tt>:<\/div>\n<div style=\"background-color: #e0e0e0; font-family: verdana, arial, helvetica, sans-serif; padding: 0.5em;\">\n<pre style=\"font-family: courier, lucidatypewriter, monospace;\"><tt style=\"font-family: courier, lucidatypewriter, monospace;\">TEMP_FILE=$TEMP_DIR\/printfile.$$.$RANDOM<br \/><\/tt><\/pre>\n<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">The&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">$TEMP_DIR<\/tt>&nbsp;variable contains either&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">\/tmp<\/tt>&nbsp;or&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">~\/tmp<\/tt>&nbsp;depending on the availability of the directory. It is common practice to embed the name of the program into the file name. We have done that with the string &#8220;printfile&#8221;. Next, we use the&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">$$<\/tt>&nbsp;shell variable to embed the process id (pid) of the program. This further helps identify what process is responsible for the file. Surprisingly, the process id alone is not unpredictable enough to make the file safe, so we add the&nbsp;<tt style=\"font-family: courier, lucidatypewriter, monospace;\">$RANDOM<\/tt>&nbsp;shell variable to append a random number to the file name. With this technique, we create a file name that is both easily identifiable and unpredictable.<\/div>\n<h2 style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif; font-weight: normal;\">There You Have It<\/h2>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif;\">This concludes the LinuxCommand.org tutorials. I sincerely hope you found them both useful and enjoyable. If you did, continue your command line adventure by downloading&nbsp;<a href=\"http:\/\/linuxcommand.org\/tlcl.php\" style=\"color: #002740;\">my book<\/a>.<\/div>\n<div style=\"background-color: white; font-family: verdana, arial, helvetica, sans-serif; padding: 1em;\"><\/div>\n<p><\/span><\/div>\n<div><span style=\"font-size: xx-small;\"><br \/><\/span><\/div>\n","protected":false},"excerpt":{"rendered":"<p>The Linux Command Line&nbsp;by William Shotts Errors ar &#8230; <a title=\"The Linux Command Line&#8212;Errors And Signals And Traps (Oh My!) &#8211; Part 2\" class=\"read-more\" href=\"https:\/\/yeslq.com\/?p=33\" aria-label=\"\u9605\u8bfb The Linux Command Line&#8212;Errors And Signals And Traps (Oh My!) &#8211; Part 2\">\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":[5,3,4,6],"tags":[],"class_list":["post-33","post","type-post","status-publish","format-standard","hentry","category-error","category-linux","category-shell","category-the-linux-command-line"],"_links":{"self":[{"href":"https:\/\/yeslq.com\/index.php?rest_route=\/wp\/v2\/posts\/33","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=33"}],"version-history":[{"count":1,"href":"https:\/\/yeslq.com\/index.php?rest_route=\/wp\/v2\/posts\/33\/revisions"}],"predecessor-version":[{"id":94,"href":"https:\/\/yeslq.com\/index.php?rest_route=\/wp\/v2\/posts\/33\/revisions\/94"}],"wp:attachment":[{"href":"https:\/\/yeslq.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=33"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/yeslq.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=33"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/yeslq.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=33"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}