{"id":481398,"date":"2022-08-04T19:00:01","date_gmt":"2022-08-04T16:00:01","guid":{"rendered":"https:\/\/en.buradabiliyorum.com\/how-to-use-linux-signals-in-bash-scripts\/"},"modified":"2022-08-04T19:00:01","modified_gmt":"2022-08-04T16:00:01","slug":"how-to-use-linux-signals-in-bash-scripts","status":"publish","type":"post","link":"https:\/\/buradabiliyorum.com\/en\/how-to-use-linux-signals-in-bash-scripts\/","title":{"rendered":"#How to Use Linux Signals in Bash Scripts"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_84 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a24ba98c60c8\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #dd3333;color:#dd3333\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #dd3333;color:#dd3333\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a24ba98c60c8\" checked aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-use-linux-signals-in-bash-scripts\/#%E2%80%9CHow_to_Use_Linux_Signals_in_Bash_Scripts%E2%80%9D\" >&#8220;How to Use Linux Signals in Bash Scripts&#8221;<\/a><ul class='ez-toc-list-level-2' ><li class='ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-use-linux-signals-in-bash-scripts\/#Signals_and_Processes\" >Signals and Processes<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-use-linux-signals-in-bash-scripts\/#Meet_the_Signals\" >Meet the Signals<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-use-linux-signals-in-bash-scripts\/#Signals_on_the_Command_Line\" >Signals on the Command Line<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-use-linux-signals-in-bash-scripts\/#Trapping_Signals_in_Scripts\" >Trapping Signals in Scripts<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-use-linux-signals-in-bash-scripts\/#Handling_Signals_in_Scripts\" >Handling Signals in Scripts<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-use-linux-signals-in-bash-scripts\/#Read_the_Signals\" >Read the Signals<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n<h1><span class=\"ez-toc-section\" id=\"%E2%80%9CHow_to_Use_Linux_Signals_in_Bash_Scripts%E2%80%9D\"><\/span>&#8220;How to Use Linux Signals in Bash Scripts&#8221;<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<div>\n<figure style=\"width: 1200px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"type:primaryImage size-full wp-image-791996\" data-pagespeed-no-defer=\"\" src=\"https:\/\/www.howtogeek.com\/wp-content\/uploads\/2022\/03\/shutterstock_321627716.png?width=1198&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"Linux laptop showing a bash prompt\" width=\"1200\" height=\"675\"\/><figcaption class=\"wp-caption-text\"><span class=\"type:primaryImage imagecredit\"><a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/www.shutterstock.com\/image-vector\/linux-interface-screen-notebook-world-map-321627716\">fatmawati achmad zaenuri\/Shutterstock.com<\/a><\/span><\/figcaption><\/figure>\n<p>The Linux kernel sends signals to processes about events they need to react to. Well-behaved <a href=\"https:\/\/buradabiliyorum.com\/en\/category\/download-scripts-themes-apps\/\" data-internallinksmanager029f6b8e52c=\"9\" title=\"Download Scripts &amp; Themes &amp; Apps\" target=\"_blank\" rel=\"noopener\">script<\/a>s handle signals elegantly and robustly and can clean up behind themselves even if you hit Ctrl+C. Here\u2019s how.<\/p>\n<h2 id=\"signals-and-processes\"><span class=\"ez-toc-section\" id=\"Signals_and_Processes\"><\/span>Signals and Processes<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Signals are short, fast, one-way messages sent to processes such as scripts, programs, and daemons. They let the process know about something that has happened. The user may have hit Ctrl+C, or the application may have tried to write to memory it doesn\u2019t have access to.<\/p>\n<p>If the author of the process has anticipated that a certain signal might be sent to it, they can write a routine into the program or script to handle that signal. Such a routine is called a <em>signal handler<\/em>. It catches or traps the signal, and performs some action in response to it.<\/p>\n<p>Linux uses a lot of signals, as we shall see, but from a scripting point of view, there\u2019s only a small subset of signals that you\u2019re likely to be interested in. In particular, in non-trivial scripts, signals that tell the script to shut down should be trapped (where possible) and a graceful shutdown performed.<\/p>\n<p>For example, scripts that create temporary files or open firewall ports can be given the chance to delete the temporary files or to close the ports before they shut down. If the script just dies the instant it receives the signal, your computer can be left in an unpredictable state.<\/p>\n<p>Here\u2019s how you can handle signals in your own scripts.<\/p>\n<h2 id=\"linux-and-signals\"><span class=\"ez-toc-section\" id=\"Meet_the_Signals\"><\/span>Meet the Signals<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Some Linux commands have cryptic names. Not so the command that traps signals. It\u2019s called <code>trap<\/code>. We can also use <code>trap<\/code> with the <code>-l<\/code> (list) option to show us the entire list of\u00a0<a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/github.com\/torvalds\/linux\/blob\/master\/include\/linux\/signal.h\">signals that Linux uses<\/a>.<\/p>\n<pre>trap -l<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-814955\" data-pagespeed-lazy-src=\"https:\/\/www.howtogeek.com\/wp-content\/uploads\/2022\/06\/1-11.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"Listing the signals in Ubuntu with trap -l\" width=\"644\" height=\"310\" src=\"\/pagespeed_static\/1.JiBnMqyl6S.gif\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Although our numbered list finishes at 64, there are actually 62 signals. Signals 32 and 33 are missing. They\u2019re\u00a0<a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/en.wikipedia.org\/wiki\/Light-weight_process\">not implemented in Linux<\/a>. They\u2019ve been replaced by functionality in the <code>gcc<\/code> compiler for handling real-time threads. Everything from signal 34, <code>SIGRTMIN<\/code>, to signal 64, <code>SIGRTMAX<\/code>, are real-time signals.<\/p>\n<p>You\u2019ll see different lists on different Unix-like operating systems. On <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/www.openindiana.org\/\">OpenIndiana<\/a> for example, signals 32 and 33 are present, along with a bunch of extra signals taking the total count to 73.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-814957\" data-pagespeed-lazy-src=\"https:\/\/www.howtogeek.com\/wp-content\/uploads\/2022\/06\/10-9.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"Listing the signals in OpenIndiana with trap -l\" width=\"644\" height=\"368\" src=\"\/pagespeed_static\/1.JiBnMqyl6S.gif\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Signals can be referenced by name, number, or by their shortened name. Their shortened name is simply their name with the leading \u201cSIG\u201d removed.<\/p>\n<p>Signals are raised for many different reasons. If you can decipher them, their purpose is contained in their name. The impact of a signal falls into one of a few categories:<\/p>\n<ul>\n<li><strong>Terminate:<\/strong>\u00a0The process is terminated.<\/li>\n<li><strong>Ignore:<\/strong>\u00a0The signal does not affect the process. This is an information-only signal.<\/li>\n<li><strong>Core:<\/strong>\u00a0A dump-core file is created. This is usually done because the process has transgressed in some way, such as a memory violation.<\/li>\n<li><strong>Stop:<\/strong>\u00a0The process is stopped. That is, it is\u00a0<em>paused<\/em>, not terminated.<\/li>\n<li><strong>Continue:<\/strong>\u00a0Tells a stopped process to continue execution.<\/li>\n<\/ul>\n<p>These are the signals you\u2019ll encounter most frequently.<\/p>\n<ul>\n<li><strong>SIGHUP<\/strong>: Signal 1. The connection to a remote host\u2014such as an SSH server\u2014has unexpectedly dropped or the user has logged out. A script receiving this signal might terminate gracefully, or may choose to attempt to reconnect to the remote host.<\/li>\n<li><strong>SIGINT<\/strong>: Signal 2. The user has pressed the Ctrl+C combination to force a process to close, or the <code>kill<\/code> command has been used with signal 2. Technically, this is an interrupt signal, not a termination signal, but an interrupted script without a signal handler will usually terminate.<\/li>\n<li><strong>SIGQUIT<\/strong>: Signal 3. The user has pressed the Ctrl+D combination to force a process to quit, or the <code>kill<\/code> command has been used with signal 3.<\/li>\n<li><strong>SIGFPE<\/strong>: Signal 8. The process tried to perform an illegal (impossible) mathematical operation, such as division by zero.<\/li>\n<li><strong>SIGKILL<\/strong>: Signal 9. This is the signal equivalent of a guillotine. You can\u2019t catch it or ignore it, and it happens instantly. The process is terminated im<a href=\"https:\/\/buradabiliyorum.com\/en\/category\/social-mediaa\/\" data-internallinksmanager029f6b8e52c=\"1\" title=\"Social Media\" target=\"_blank\" rel=\"noopener\">media<\/a>tely.<\/li>\n<li><strong>SIGTERM<\/strong>: Signal 15. This is the more considerate version of <code>SIGKILL<\/code>. <code>SIGTERM<\/code>\u00a0also tells a process to terminate, but it can be trapped and the process can run its clean-up processes before closing down. This allows a graceful shutdown. This is the default signal raised by the <code>kill<\/code> command.<\/li>\n<\/ul>\n<h2 id=\"signals-on-the-command-line\"><span class=\"ez-toc-section\" id=\"Signals_on_the_Command_Line\"><\/span>Signals on the Command Line<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>One way to trap a signal is to use <code>trap<\/code> with the number or name of the signal, and a response that you want to happen if the signal is received. We can demonstrate this in a terminal window.<\/p>\n<p>This command traps the <code>SIGINT<\/code> signal. The response is to print a line of text to the terminal window. We\u2019re using the <code>-e<\/code> (enable escapes) option with <code>echo<\/code> so we can use the \u201c<code>\\n<\/code>\u201d format specifier.<\/p>\n<pre>trap 'echo -e \"+c Detected.\"' SIGINT<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-814959\" data-pagespeed-lazy-src=\"https:\/\/www.howtogeek.com\/wp-content\/uploads\/2022\/06\/2-11.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"Trapping Ctrl+C on the command line\" width=\"644\" height=\"250\" src=\"\/pagespeed_static\/1.JiBnMqyl6S.gif\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Our line of text is printed each time we hit the Ctrl+C combination.<\/p>\n<p>To see if a trap is set on a signal, use the <code>-p<\/code> (print trap) option.<\/p>\n<pre>trap -p SIGINT<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-814960\" data-pagespeed-lazy-src=\"https:\/\/www.howtogeek.com\/wp-content\/uploads\/2022\/06\/3-11.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"Checking whether a trap is set on a signal\" width=\"644\" height=\"95\" src=\"\/pagespeed_static\/1.JiBnMqyl6S.gif\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Using <code>trap<\/code> with no options does the same thing.<\/p>\n<p>To reset the signal to its untrapped, normal state, use a hyphen \u201c<code>-<\/code>\u201d and the name of the trapped signal.<\/p>\n<pre>trap - SIGINT<\/pre>\n<pre>trap -p SIGINT<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-814973\" data-pagespeed-lazy-src=\"https:\/\/www.howtogeek.com\/wp-content\/uploads\/2022\/06\/11-7.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"Removing a trap from a signal\" width=\"644\" height=\"95\" src=\"\/pagespeed_static\/1.JiBnMqyl6S.gif\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>No output from the <code>trap -p<\/code> command indicates there is no trap set on that signal.<\/p>\n<h2 id=\"trapping-signals-in-scripts\"><span class=\"ez-toc-section\" id=\"Trapping_Signals_in_Scripts\"><\/span>Trapping Signals in Scripts<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>We can use the same <a href=\"https:\/\/buradabiliyorum.com\/en\/category\/general\/\" data-internallinksmanager029f6b8e52c=\"3\" title=\"General\" target=\"_blank\" rel=\"noopener\">general<\/a> format <code>trap<\/code> command inside a script. This script traps three different signals, <code>SIGINT<\/code>, <code>SIGQUIT<\/code>, and <code>SIGTERM<\/code>.<\/p>\n<pre>#!\/bin\/bash&#13;\n&#13;\ntrap \"echo I was SIGINT terminated; exit\" SIGINT&#13;\ntrap \"echo I was SIGQUIT terminated; exit\" SIGQUIT&#13;\ntrap \"echo I was SIGTERM terminated; exit\" SIGTERM&#13;\n&#13;\necho $$&#13;\ncounter=0&#13;\n&#13;\nwhile true&#13;\ndo &#13;\n\u00a0 echo \"Loop number:\" $((++counter))&#13;\n\u00a0 sleep 1&#13;\ndone<\/pre>\n<p>The three <code>trap<\/code> statements are at the top of the script. Note that we\u2019ve included the <code>exit<\/code> command inside the response to each of the signals. This means the script reacts to the signal and then exits.<\/p>\n<p>Copy the text into your editor and save it in a file called \u201csimple-loop.sh\u201d, and make it executable using the <code>chmod<\/code> command. You\u2019ll need to do that to all of the scripts in this article if you want to follow along on your own computer. Just use the name of the appropriate script in each case.<\/p>\n<pre>chmod +x simple-loop.sh<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-814962\" data-pagespeed-lazy-src=\"https:\/\/www.howtogeek.com\/wp-content\/uploads\/2022\/06\/4-9.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"Making a script executable with chmod\" width=\"644\" height=\"55\" src=\"\/pagespeed_static\/1.JiBnMqyl6S.gif\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>The rest of the script is very simple. We need to know the process ID of the script, so we have the script echo that to us. The <code>$$<\/code> variable holds the process ID of the script.<\/p>\n<p>We create a variable called <code>counter<\/code>\u00a0and set it to zero.<\/p>\n<p>The <code>while<\/code> loop will run forever unless it is forcibly stopped. It increments the <code>counter<\/code> variable, echoes it to the screen, and sleeps for a second.<\/p>\n<p>Let\u2019s run the script and send different signals to it.<\/p>\n<pre>.\/simple-loop.sh<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-814963\" data-pagespeed-lazy-src=\"https:\/\/www.howtogeek.com\/wp-content\/uploads\/2022\/06\/5-10.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"A script identifying it has been terminated with Ctrl+C\" width=\"644\" height=\"190\" src=\"\/pagespeed_static\/1.JiBnMqyl6S.gif\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>When we hit \u201cCtrl+C\u201d our message is printed to the terminal window and the script is terminated.<\/p>\n<p>Let\u2019s run it again and send the <code>SIGQUIT<\/code> signal using the <code>kill<\/code> command. We\u2019ll need to do that from another terminal window. You\u2019ll need to use the process ID that was reported by your own script.<\/p>\n<pre>.\/simple-loop.sh<\/pre>\n<pre>kill -SIGQUIT 4575<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-814964\" data-pagespeed-lazy-src=\"https:\/\/www.howtogeek.com\/wp-content\/uploads\/2022\/06\/6-10.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"A script identifying it has been terminated with SIGQUIT\" width=\"644\" height=\"330\" src=\"\/pagespeed_static\/1.JiBnMqyl6S.gif\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>As expected the script reports the signal arriving then terminates. And finally, to prove the point, we\u2019ll do it again with the <code>SIGTERM<\/code> signal.<\/p>\n<pre>.\/simple-loop.sh<\/pre>\n<pre>kill -SIGTERM 4584<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-814965\" data-pagespeed-lazy-src=\"https:\/\/www.howtogeek.com\/wp-content\/uploads\/2022\/06\/7-9.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"A script identifying it has been terminated with SIGTERM\" width=\"644\" height=\"330\" src=\"\/pagespeed_static\/1.JiBnMqyl6S.gif\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>We\u2019ve verified we can trap multiple signals in a script, and react to each one independently. The step that promotes all of this from interesting to useful is adding signal handlers.<\/p>\n<h2 id=\"handling-signals-in-scripts\"><span class=\"ez-toc-section\" id=\"Handling_Signals_in_Scripts\"><\/span>Handling Signals in Scripts<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>We can replace the response string with the name of a function in your script. The <code>trap<\/code> command then calls that function when the signal is detected.<\/p>\n<p>Copy this text into an editor and save it as a file called \u201cgrace.sh\u201d, and make it executable with <code>chmod<\/code>.<\/p>\n<pre>#!\/bin\/bash&#13;\n&#13;\ntrap graceful_shutdown SIGINT SIGQUIT SIGTERM&#13;\n&#13;\ngraceful_shutdown()&#13;\n{&#13;\n\u00a0 echo -e \"\\nRemoving temporary file:\" $temp_file&#13;\n\u00a0 rm -rf \"$temp_file\"&#13;\n\u00a0 exit&#13;\n}&#13;\n&#13;\ntemp_file=$(mktemp -p \/tmp tmp.XXXXXXXXXX)&#13;\necho \"Created temp file:\" $temp_file&#13;\n&#13;\ncounter=0&#13;\n&#13;\nwhile true&#13;\ndo &#13;\n\u00a0 echo \"Loop number:\" $((++counter))&#13;\n\u00a0 sleep 1&#13;\ndone<\/pre>\n<p>The script sets a trap for three different signals\u2014 <code>SIGHUP<\/code>, <code>SIGINT<\/code>, and <code>SIGTERM<\/code>\u2014using a single <code>trap<\/code> statement. The response is the name of the <code>graceful_shutdown()<\/code> function. The function is called whenever one of the three trapped signals is received.<\/p>\n<p>The script creates a temporary file in the \u201c\/tmp\u201d directory, using <code>mktemp<\/code>. The filename template is \u201ctmp.XXXXXXXXXX\u201d, so the name of the file will be \u201ctmp.\u201d followed by ten random alphanumeric characters. The name of the file is echoed on the screen.<\/p>\n<p>The rest of the script is the same as the previous one, with a <code>counter<\/code> variable and an infinite <code>while<\/code> loop.<\/p>\n<pre>.\/grace.sh<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-814966\" data-pagespeed-lazy-src=\"https:\/\/www.howtogeek.com\/wp-content\/uploads\/2022\/06\/8-10.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"A script performing a graceful shutdown by deleting a temporary file\" width=\"644\" height=\"250\" src=\"\/pagespeed_static\/1.JiBnMqyl6S.gif\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>When the file is sent a signal that causes it to close, the <code>graceful_shutdown()<\/code> function is called. This deletes our single temporary file. In a real-world situation, it could perform whatever clean-up your script requires.<\/p>\n<p>Also, we bundled all of our trapped signals together and handled them with a single function. You can trap signals individually and send them to their own dedicated handler functions.<\/p>\n<p>Copy this text and save it in a file called \u201c<a href=\"https:\/\/buradabiliyorum.com\/en\/category\/trip-and-travel\/\" data-internallinksmanager029f6b8e52c=\"10\" title=\"Trip &amp; Travel\" target=\"_blank\" rel=\"noopener\">trip<\/a>le.sh\u201d, and make it executable using the <code>chmod <\/code> command.<\/p>\n<pre>#!\/bin\/bash&#13;\n&#13;\ntrap sigint_handler SIGINT&#13;\ntrap sigusr1_handler SIGUSR1&#13;\ntrap exit_handler EXIT&#13;\n&#13;\nfunction sigint_handler() {&#13;\n\u00a0 ((++sigint_count))&#13;\n&#13;\n\u00a0 echo -e \"\\nSIGINT received $sigint_count time(s).\"&#13;\n&#13;\n\u00a0 if [[ \"$sigint_count\" -eq 3 ]]; then&#13;\n\u00a0 \u00a0 echo \"Starting close-down.\"&#13;\n\u00a0 \u00a0 loop_flag=1&#13;\n\u00a0 fi&#13;\n}&#13;\n&#13;\nfunction sigusr1_handler() {&#13;\n\u00a0 echo \"SIGUSR1 sent and received $((++sigusr1_count)) time(s).\"&#13;\n}&#13;\n&#13;\nfunction exit_handler() { &#13;\n\u00a0 echo \"Exit handler: Script is closing down...\"&#13;\n}&#13;\n&#13;\necho $$&#13;\nsigusr1_count=0&#13;\nsigint_count=0&#13;\nloop_flag=0&#13;\n&#13;\nwhile [[ $loop_flag -eq 0 ]]; do&#13;\n\u00a0 kill -SIGUSR1 $$&#13;\n\u00a0 sleep 1&#13;\ndone<\/pre>\n<p>We define three traps at the top of the script.<\/p>\n<ul>\n<li>One traps <code>SIGINT<\/code>\u00a0and has a handler called <code>sigint_handler()<\/code>.<\/li>\n<li>The second traps a signal called <code>SIGUSR1<\/code> and uses a handler called <code>sigusr1_handler()<\/code> .<\/li>\n<li>Trap number three traps the <code>EXIT<\/code> signal. This signal is raised by the script itself when it closes. Setting a signal handler for <code>EXIT<\/code> means you can set a function that\u2019ll always be called when the script terminates (unless it is killed with signal <code>SIGKILL<\/code>). Our handler is called <code>exit_handler()<\/code> .<\/li>\n<\/ul>\n<p><code>SIGUSR1<\/code> and <code>SIGUSR2<\/code> are signals provided so that you can send custom signals to your scripts. How you interpret and react to them is entirely up to you.<\/p>\n<p>Leaving the signal handlers aside for now, the body of the script should be familiar to you. It echoes the process ID to the terminal window and creates some variables. Variable <code>sigusr1_count<\/code> records the number of times <code>SIGUSR1<\/code> was handled, and <code>sigint_count<\/code> records the number of times <code>SIGINT<\/code> was handled. The <code>loop_flag<\/code> variable is set to zero.<\/p>\n<p>The <code>while<\/code> loop is not an infinite loop. It will stop looping if the <code>loop_flag<\/code> variable is set to any non-zero value. Each spin of the <code>while<\/code> loop uses <code>kill<\/code> to send the <code>SIGUSR1<\/code> signal to this script, by sending it to the process ID of the script. Scripts can send signals to themselves!<\/p>\n<p>The <code>sigusr1_handler()<\/code> function increments the <code>sigusr1_count<\/code> variable and sends a message to the terminal window.<\/p>\n<p>Each time the <code>SIGINT<\/code> signal is received, the <code>siguint_handler()<\/code> function increments the <code>sigint_count<\/code> variable and echoes its value to the terminal window.<\/p>\n<p>If the <code>sigint_count<\/code> variable equals three, the <code>loop_flag<\/code> variable is set to one and a message is sent to the terminal window letting the user know the shutdown process has started.<\/p>\n<p>Because <code>loop_flag<\/code> is no longer equal to zero, the <code>while<\/code> loop terminates and the script is finished. But that action automatically raises the <code>EXIT<\/code> signal and the <code>exit_handler()<\/code> function is called.<\/p>\n<pre>.\/triple.sh<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-814967\" data-pagespeed-lazy-src=\"https:\/\/www.howtogeek.com\/wp-content\/uploads\/2022\/06\/9-9.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"A script using SIGUSR1, requireing three Ctrl+C combinations to close, and catching the EXIT signal at shutdown\" width=\"644\" height=\"340\" src=\"\/pagespeed_static\/1.JiBnMqyl6S.gif\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>After three Ctrl+C presses, the script terminates and automatically invokes the <code>exit_handler()<\/code> function.<\/p>\n<h2 id=\"wrap-up\"><span class=\"ez-toc-section\" id=\"Read_the_Signals\"><\/span>Read the Signals<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>By trapping signals and dealing with them in straightforward handler functions, you can make your Bash scripts tidy up behind themselves even if they\u2019re unexpectedly terminated. That gives you a cleaner filesystem. It also prevents instability the next time you run the script, and\u2014depending on what the purpose of your script is\u2014it could even prevent security holes.<\/p>\n<p><strong>RELATED:<\/strong> <strong><em>How to Audit Your Linux System&#8217;s Security with Lynis<\/em><\/strong><\/p>\n<\/div>\n<p><script>\n setTimeout(function(){\n  !function(f,b,e,v,n,t,s)\n  {if(f.fbq)return;n=f.fbq=function(){n.callMethod?\n  n.callMethod.apply(n,arguments):n.queue.push(arguments)};\n  if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';\n  n.queue=[];t=b.createElement(e);t.async=!0;\n  t.src=v;s=b.getElementsByTagName(e)[0];\n  s.parentNode.insertBefore(t,s) } (window, document,'script',\n  'https:\/\/connect.facebook.net\/en_US\/fbevents.js');\n   fbq('init', '335401813750447');\n   fbq('track', 'PageView');\n  },3000);\n<\/script><\/p>\n<blockquote><p><strong><span style=\"color: #ff6600;\">If you liked the article, do not forget to share it with your friends. Follow us on\u00a0<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/news.google.com\/publications\/CAAqBwgKMLG0nwswvr63Aw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Google News<\/a><\/span>\u00a0too, click on the star and choose us from your favorites.<\/span><\/strong><\/p><\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\">For forums sites go to <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/forum.buradabiliyorum.com\/\" target=\"_blank\" rel=\"noopener\">Forum.BuradaBiliyorum.Com<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\"><strong>If you want to read more like this article, you can visit our <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/en.buradabiliyorum.com\/technology\/\" target=\"_blank\" rel=\"noopener\">Technology category.<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<p><span style=\"color: black;\"><a style=\"color: #ff9900;\" href=\"https:\/\/www.howtogeek.com\/814925\/linux-signals-bash\/\" target=\"_blank\" rel=\"noopener\">Source<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;How to Use Linux Signals in Bash Scripts&#8221; fatmawati achmad zaenuri\/Shutterstock.com The Linux kernel sends signals to processes about events they need to react to. Well-behaved scripts handle signals elegantly and robustly and can clean up behind themselves even if you hit Ctrl+C. Here\u2019s how. Signals and Processes Signals are short, fast, one-way messages sent&#8230;<\/p>\n","protected":false},"author":1,"featured_media":481399,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/www.howtogeek.com\/wp-content\/uploads\/2022\/03\/shutterstock_321627716.png?height=200p&trim=2,2,2,2","fifu_image_alt":"","footnotes":""},"categories":[18],"tags":[],"class_list":["post-481398","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology"],"_links":{"self":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/481398","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/comments?post=481398"}],"version-history":[{"count":0,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/481398\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media\/481399"}],"wp:attachment":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media?parent=481398"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/categories?post=481398"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/tags?post=481398"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}