2

It seems local variables declared in a bash function are visible to called functions but not visible to trap handlers:

#!/bin/bash

function exit_handler() {
  echo "Exit handler: ${device_name}"
}

function other() {
  echo "Other: ${device_name}"
}

function do_something() {
  local device_name="abc"
  trap exit_handler EXIT
  other
}

do_something

Output:

$ bash test.sh 
Other: abc
Error handler: 

What is the best way to pass the value of the local variable to the trap handler? It is not important to me if the variable is expanded immediately or at the end of the function (in case the latter is not possible for local variables).

What I tried:

  1. Turning the variable into a global variable by removing local. This works, but I'm unhappy with this solution because I do not want to pollute the global name space.

  2. Passing the variable to the handler directly:

    function exit_handler() {
      local device_name="${1}"
      echo "Error handler: ${device_name}"
    }
    
    function do_something() {
      local device_name="abc"
      trap exit_handler "${device_name}" EXIT
    }
    

    This does not work (invalid signal specification), I assume the value gets interpreted as a signal name. Is there a way to separate the command from the signal name?

  3. Putting the trap command into single quotes (this is suggested by shellcheck):

    function exit_handler() {
      local device_name="${1}"
      echo "Exit handler: ${device_name}"
    }
    
    function do_something() {
      local device_name="abc"
      trap 'exit_handler "${device_name}"' EXIT
    }
    

    But this still gives me an empty output in the exit handler. So I assume the local variable might not live long enough.

2
  • Is your intention really to install an EXIT handler and not a RETURN handler?
    – Kusalananda
    Apr 27 '20 at 20:03
  • Thanks for pointing that out. I realized I was under the misconception that the EXIT handler runs at the end of the function rather than at the end of the script. However, it seems the RETURN handler does not trigger on all error paths, e.g. when a function does exit 1, so I would need the EXIT handler for that. Apr 28 '20 at 4:40
1

The solution 3. is very close , you must evaluate the variable in the context of function do_something

This is you updated example :

#!/bin/bash

function exit_handler() {
  local device_name="${1}"
  echo "Exit handler: ${device_name}"
}

function other() {
  echo "Other: ${device_name}"
}

function do_something() {
  local device_name="abc"
  trap "exit_handler '${device_name}'" EXIT
  other
}

do_something

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.