Lock file and interrupt signals in POSIX shell script running indefinitely












0












$begingroup$


This script is running indefinitely as the Linux background process.



I have put an enormous effort to make this POSIX shell script containing an infinite loop shut down tidily along with the operating system (TERM signal) and by me sending it a HUP signal.



Ok, we don't call it exception-handling, but I didn't find any other suitable tag for it. Also did not find an appropriate tag for the script's termination.



We have reviewed two big pieces of the puzzle already, so I cut it out.





readonly script_one_instance_lockfile="${HOME}/.PROGRAM/$(basename "${0}").lock"

# this is long and not relevant to this question, it does as its name says
# you can find a review on it here: https://codereview.stackexchange.com/q/204828/104270
print_error_and_exit() { ... }

is_number()
{
[ "${1}" -eq "${1}" ] 2> /dev/null
}

# purpose is clear, i.e. to clean up some temp, lock files
# which were created during script execution and should not be left in place
cleanup_on_exit()
{
[ -f "${script_one_instance_lockfile}" ] && rm "${script_one_instance_lockfile}"
}

# this function is merely for future expansions of the script
# it might very well be different from cleanup_on_exit
cleanup_on_signal()
{
cleanup_on_exit
}

# here we define a generic function to handle signals
# treat them as errors with appropriate messages
# example calls:
# kill -15 this_script_name # POSIX; all shells compatible
# kill -TERM this_script_name # Bash and alike; newer shells
signal_handler_generic()
# expected arguments:
# $1 = signal code
{
# check if exactly one argument has been passed
[ "${#}" -eq 1 ] || print_error_and_exit "signal_handler_generic()" "Exactly one argument has not been passed!\n\tPassed: ${*}"

# check if the argument is a number
is_number "${1}" || print_error_and_exit "signal_handler_generic()" "The argument is not a number!\n\Signal code expected.\n\tPassed: ${1}"

number_argument=${1}
signal_code=${number_argument}
case "${number_argument}" in
1 ) signal_human_friendly='HUP' ;;
2 ) signal_human_friendly='INT' ;;
3 ) signal_human_friendly='QUIT' ;;
6 ) signal_human_friendly='ABRT' ;;
15) signal_human_friendly='TERM' ;;
* ) signal_human_friendly='' ;;
esac

if [ "${signal_human_friendly}" = "" ]
then
print_error_and_exit "signal_handler_generic()" "Given number code (${signal_code}) does not correspond to supported signal codes."
else
# tidy up any temp or lock files created along the way
cleanup_on_signal
# print human friendly and number signal code that has been caught
print_error_and_exit "\ntrap()" "Caught ${signal_human_friendly} termination signal ${signal_code}.\n\tClean-up finished. Exiting. Bye!"
fi
}

# use the above function for signal handling;
# note that the SIG* constants are undefined in POSIX,
# and numbers are to be used for the signals instead
trap 'signal_handler_generic 1' 1
trap 'signal_handler_generic 2' 2
trap 'signal_handler_generic 3' 3
trap 'signal_handler_generic 6' 6
trap 'signal_handler_generic 15' 15

# this is long and not relevant to this question, it does as its name says
# you can find a review on it here: https://codereview.stackexchange.com/q/213156/104270
is_java_program_running() { ... }

####################
### MAIN PROGRAM ###
####################

if [ -f "${script_one_instance_lockfile}" ]
then
# if one instance of this script is already running, quit to shell
print_error_and_exit "\nmain()" "One instance of this script should already be running.\n\tLock file: ${script_one_instance_lockfile}\n\tMore than one instance is not allowed. Exiting."
else
# create a .lock file for one instance handling
touch "${script_one_instance_lockfile}"
fi

# keep the PROGRAM alive forever, check in 5 seconds interval
while true
do
sleep 5s

if ! is_java_program_running "${PROGRAM_java_process_identifier}"
then
my_date_time=$(date +%Y-%m-%d_%H:%M:%S)
printf '%s %sn' "${my_date_time}" "(re-)starting PROGRAM"
( /full/path/to/program > /dev/null 2>&1 & )
fi
done

# ordinary scripts don't have infinite loops
# this code shall be unreachable, but it is good to have it here since I will be
# copying / reusing the script and I would definitely forget on this
cleanup_on_exit








share









$endgroup$

















    0












    $begingroup$


    This script is running indefinitely as the Linux background process.



    I have put an enormous effort to make this POSIX shell script containing an infinite loop shut down tidily along with the operating system (TERM signal) and by me sending it a HUP signal.



    Ok, we don't call it exception-handling, but I didn't find any other suitable tag for it. Also did not find an appropriate tag for the script's termination.



    We have reviewed two big pieces of the puzzle already, so I cut it out.





    readonly script_one_instance_lockfile="${HOME}/.PROGRAM/$(basename "${0}").lock"

    # this is long and not relevant to this question, it does as its name says
    # you can find a review on it here: https://codereview.stackexchange.com/q/204828/104270
    print_error_and_exit() { ... }

    is_number()
    {
    [ "${1}" -eq "${1}" ] 2> /dev/null
    }

    # purpose is clear, i.e. to clean up some temp, lock files
    # which were created during script execution and should not be left in place
    cleanup_on_exit()
    {
    [ -f "${script_one_instance_lockfile}" ] && rm "${script_one_instance_lockfile}"
    }

    # this function is merely for future expansions of the script
    # it might very well be different from cleanup_on_exit
    cleanup_on_signal()
    {
    cleanup_on_exit
    }

    # here we define a generic function to handle signals
    # treat them as errors with appropriate messages
    # example calls:
    # kill -15 this_script_name # POSIX; all shells compatible
    # kill -TERM this_script_name # Bash and alike; newer shells
    signal_handler_generic()
    # expected arguments:
    # $1 = signal code
    {
    # check if exactly one argument has been passed
    [ "${#}" -eq 1 ] || print_error_and_exit "signal_handler_generic()" "Exactly one argument has not been passed!\n\tPassed: ${*}"

    # check if the argument is a number
    is_number "${1}" || print_error_and_exit "signal_handler_generic()" "The argument is not a number!\n\Signal code expected.\n\tPassed: ${1}"

    number_argument=${1}
    signal_code=${number_argument}
    case "${number_argument}" in
    1 ) signal_human_friendly='HUP' ;;
    2 ) signal_human_friendly='INT' ;;
    3 ) signal_human_friendly='QUIT' ;;
    6 ) signal_human_friendly='ABRT' ;;
    15) signal_human_friendly='TERM' ;;
    * ) signal_human_friendly='' ;;
    esac

    if [ "${signal_human_friendly}" = "" ]
    then
    print_error_and_exit "signal_handler_generic()" "Given number code (${signal_code}) does not correspond to supported signal codes."
    else
    # tidy up any temp or lock files created along the way
    cleanup_on_signal
    # print human friendly and number signal code that has been caught
    print_error_and_exit "\ntrap()" "Caught ${signal_human_friendly} termination signal ${signal_code}.\n\tClean-up finished. Exiting. Bye!"
    fi
    }

    # use the above function for signal handling;
    # note that the SIG* constants are undefined in POSIX,
    # and numbers are to be used for the signals instead
    trap 'signal_handler_generic 1' 1
    trap 'signal_handler_generic 2' 2
    trap 'signal_handler_generic 3' 3
    trap 'signal_handler_generic 6' 6
    trap 'signal_handler_generic 15' 15

    # this is long and not relevant to this question, it does as its name says
    # you can find a review on it here: https://codereview.stackexchange.com/q/213156/104270
    is_java_program_running() { ... }

    ####################
    ### MAIN PROGRAM ###
    ####################

    if [ -f "${script_one_instance_lockfile}" ]
    then
    # if one instance of this script is already running, quit to shell
    print_error_and_exit "\nmain()" "One instance of this script should already be running.\n\tLock file: ${script_one_instance_lockfile}\n\tMore than one instance is not allowed. Exiting."
    else
    # create a .lock file for one instance handling
    touch "${script_one_instance_lockfile}"
    fi

    # keep the PROGRAM alive forever, check in 5 seconds interval
    while true
    do
    sleep 5s

    if ! is_java_program_running "${PROGRAM_java_process_identifier}"
    then
    my_date_time=$(date +%Y-%m-%d_%H:%M:%S)
    printf '%s %sn' "${my_date_time}" "(re-)starting PROGRAM"
    ( /full/path/to/program > /dev/null 2>&1 & )
    fi
    done

    # ordinary scripts don't have infinite loops
    # this code shall be unreachable, but it is good to have it here since I will be
    # copying / reusing the script and I would definitely forget on this
    cleanup_on_exit








    share









    $endgroup$















      0












      0








      0





      $begingroup$


      This script is running indefinitely as the Linux background process.



      I have put an enormous effort to make this POSIX shell script containing an infinite loop shut down tidily along with the operating system (TERM signal) and by me sending it a HUP signal.



      Ok, we don't call it exception-handling, but I didn't find any other suitable tag for it. Also did not find an appropriate tag for the script's termination.



      We have reviewed two big pieces of the puzzle already, so I cut it out.





      readonly script_one_instance_lockfile="${HOME}/.PROGRAM/$(basename "${0}").lock"

      # this is long and not relevant to this question, it does as its name says
      # you can find a review on it here: https://codereview.stackexchange.com/q/204828/104270
      print_error_and_exit() { ... }

      is_number()
      {
      [ "${1}" -eq "${1}" ] 2> /dev/null
      }

      # purpose is clear, i.e. to clean up some temp, lock files
      # which were created during script execution and should not be left in place
      cleanup_on_exit()
      {
      [ -f "${script_one_instance_lockfile}" ] && rm "${script_one_instance_lockfile}"
      }

      # this function is merely for future expansions of the script
      # it might very well be different from cleanup_on_exit
      cleanup_on_signal()
      {
      cleanup_on_exit
      }

      # here we define a generic function to handle signals
      # treat them as errors with appropriate messages
      # example calls:
      # kill -15 this_script_name # POSIX; all shells compatible
      # kill -TERM this_script_name # Bash and alike; newer shells
      signal_handler_generic()
      # expected arguments:
      # $1 = signal code
      {
      # check if exactly one argument has been passed
      [ "${#}" -eq 1 ] || print_error_and_exit "signal_handler_generic()" "Exactly one argument has not been passed!\n\tPassed: ${*}"

      # check if the argument is a number
      is_number "${1}" || print_error_and_exit "signal_handler_generic()" "The argument is not a number!\n\Signal code expected.\n\tPassed: ${1}"

      number_argument=${1}
      signal_code=${number_argument}
      case "${number_argument}" in
      1 ) signal_human_friendly='HUP' ;;
      2 ) signal_human_friendly='INT' ;;
      3 ) signal_human_friendly='QUIT' ;;
      6 ) signal_human_friendly='ABRT' ;;
      15) signal_human_friendly='TERM' ;;
      * ) signal_human_friendly='' ;;
      esac

      if [ "${signal_human_friendly}" = "" ]
      then
      print_error_and_exit "signal_handler_generic()" "Given number code (${signal_code}) does not correspond to supported signal codes."
      else
      # tidy up any temp or lock files created along the way
      cleanup_on_signal
      # print human friendly and number signal code that has been caught
      print_error_and_exit "\ntrap()" "Caught ${signal_human_friendly} termination signal ${signal_code}.\n\tClean-up finished. Exiting. Bye!"
      fi
      }

      # use the above function for signal handling;
      # note that the SIG* constants are undefined in POSIX,
      # and numbers are to be used for the signals instead
      trap 'signal_handler_generic 1' 1
      trap 'signal_handler_generic 2' 2
      trap 'signal_handler_generic 3' 3
      trap 'signal_handler_generic 6' 6
      trap 'signal_handler_generic 15' 15

      # this is long and not relevant to this question, it does as its name says
      # you can find a review on it here: https://codereview.stackexchange.com/q/213156/104270
      is_java_program_running() { ... }

      ####################
      ### MAIN PROGRAM ###
      ####################

      if [ -f "${script_one_instance_lockfile}" ]
      then
      # if one instance of this script is already running, quit to shell
      print_error_and_exit "\nmain()" "One instance of this script should already be running.\n\tLock file: ${script_one_instance_lockfile}\n\tMore than one instance is not allowed. Exiting."
      else
      # create a .lock file for one instance handling
      touch "${script_one_instance_lockfile}"
      fi

      # keep the PROGRAM alive forever, check in 5 seconds interval
      while true
      do
      sleep 5s

      if ! is_java_program_running "${PROGRAM_java_process_identifier}"
      then
      my_date_time=$(date +%Y-%m-%d_%H:%M:%S)
      printf '%s %sn' "${my_date_time}" "(re-)starting PROGRAM"
      ( /full/path/to/program > /dev/null 2>&1 & )
      fi
      done

      # ordinary scripts don't have infinite loops
      # this code shall be unreachable, but it is good to have it here since I will be
      # copying / reusing the script and I would definitely forget on this
      cleanup_on_exit








      share









      $endgroup$




      This script is running indefinitely as the Linux background process.



      I have put an enormous effort to make this POSIX shell script containing an infinite loop shut down tidily along with the operating system (TERM signal) and by me sending it a HUP signal.



      Ok, we don't call it exception-handling, but I didn't find any other suitable tag for it. Also did not find an appropriate tag for the script's termination.



      We have reviewed two big pieces of the puzzle already, so I cut it out.





      readonly script_one_instance_lockfile="${HOME}/.PROGRAM/$(basename "${0}").lock"

      # this is long and not relevant to this question, it does as its name says
      # you can find a review on it here: https://codereview.stackexchange.com/q/204828/104270
      print_error_and_exit() { ... }

      is_number()
      {
      [ "${1}" -eq "${1}" ] 2> /dev/null
      }

      # purpose is clear, i.e. to clean up some temp, lock files
      # which were created during script execution and should not be left in place
      cleanup_on_exit()
      {
      [ -f "${script_one_instance_lockfile}" ] && rm "${script_one_instance_lockfile}"
      }

      # this function is merely for future expansions of the script
      # it might very well be different from cleanup_on_exit
      cleanup_on_signal()
      {
      cleanup_on_exit
      }

      # here we define a generic function to handle signals
      # treat them as errors with appropriate messages
      # example calls:
      # kill -15 this_script_name # POSIX; all shells compatible
      # kill -TERM this_script_name # Bash and alike; newer shells
      signal_handler_generic()
      # expected arguments:
      # $1 = signal code
      {
      # check if exactly one argument has been passed
      [ "${#}" -eq 1 ] || print_error_and_exit "signal_handler_generic()" "Exactly one argument has not been passed!\n\tPassed: ${*}"

      # check if the argument is a number
      is_number "${1}" || print_error_and_exit "signal_handler_generic()" "The argument is not a number!\n\Signal code expected.\n\tPassed: ${1}"

      number_argument=${1}
      signal_code=${number_argument}
      case "${number_argument}" in
      1 ) signal_human_friendly='HUP' ;;
      2 ) signal_human_friendly='INT' ;;
      3 ) signal_human_friendly='QUIT' ;;
      6 ) signal_human_friendly='ABRT' ;;
      15) signal_human_friendly='TERM' ;;
      * ) signal_human_friendly='' ;;
      esac

      if [ "${signal_human_friendly}" = "" ]
      then
      print_error_and_exit "signal_handler_generic()" "Given number code (${signal_code}) does not correspond to supported signal codes."
      else
      # tidy up any temp or lock files created along the way
      cleanup_on_signal
      # print human friendly and number signal code that has been caught
      print_error_and_exit "\ntrap()" "Caught ${signal_human_friendly} termination signal ${signal_code}.\n\tClean-up finished. Exiting. Bye!"
      fi
      }

      # use the above function for signal handling;
      # note that the SIG* constants are undefined in POSIX,
      # and numbers are to be used for the signals instead
      trap 'signal_handler_generic 1' 1
      trap 'signal_handler_generic 2' 2
      trap 'signal_handler_generic 3' 3
      trap 'signal_handler_generic 6' 6
      trap 'signal_handler_generic 15' 15

      # this is long and not relevant to this question, it does as its name says
      # you can find a review on it here: https://codereview.stackexchange.com/q/213156/104270
      is_java_program_running() { ... }

      ####################
      ### MAIN PROGRAM ###
      ####################

      if [ -f "${script_one_instance_lockfile}" ]
      then
      # if one instance of this script is already running, quit to shell
      print_error_and_exit "\nmain()" "One instance of this script should already be running.\n\tLock file: ${script_one_instance_lockfile}\n\tMore than one instance is not allowed. Exiting."
      else
      # create a .lock file for one instance handling
      touch "${script_one_instance_lockfile}"
      fi

      # keep the PROGRAM alive forever, check in 5 seconds interval
      while true
      do
      sleep 5s

      if ! is_java_program_running "${PROGRAM_java_process_identifier}"
      then
      my_date_time=$(date +%Y-%m-%d_%H:%M:%S)
      printf '%s %sn' "${my_date_time}" "(re-)starting PROGRAM"
      ( /full/path/to/program > /dev/null 2>&1 & )
      fi
      done

      # ordinary scripts don't have infinite loops
      # this code shall be unreachable, but it is good to have it here since I will be
      # copying / reusing the script and I would definitely forget on this
      cleanup_on_exit






      error-handling sh posix





      share












      share










      share



      share










      asked 4 mins ago









      VlastimilVlastimil

      607318




      607318






















          0






          active

          oldest

          votes











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f213232%2flock-file-and-interrupt-signals-in-posix-shell-script-running-indefinitely%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          0






          active

          oldest

          votes








          0






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f213232%2flock-file-and-interrupt-signals-in-posix-shell-script-running-indefinitely%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          How to make a Squid Proxy server?

          Is this a new Fibonacci Identity?

          19世紀