Sometimes Bash quietly hides features that make you stop, blink, and say:
“Wait… that’s been there the whole time?!”
This post is about one of those features: Bash knows which function you’re in — and even keeps a call stack. You can use it for logging, debugging, and some truly delightful shell wizardry.
Printing the Name of the Current Function
If you’re inside a Bash function and want to know its name, Bash gives it to you for free via the FUNCNAME array.
myfunc() {
echo "I was called as: ${FUNCNAME[0]}"
}
Running it:
myfunc
Outputs:
I was called as: myfunc
What’s FUNCNAME?
- FUNCNAME[0] → the current function
- FUNCNAME[1] → the caller
- FUNCNAME[2] → the caller’s caller
… and so on
Yes — Bash has a call stack.
Seeing Who Called You
Let’s demonstrate:
outer() {
inner
}
inner() {
echo "Current: ${FUNCNAME[0]}"
echo "Called by: ${FUNCNAME[1]}"
}
Output:
Current: inner
Called by: outer
This alone is already hugely useful for debugging and logging.
A Reusable Logging Helper
Here’s where it gets fun. You can write a single helper function that logs who called it:
log() {
echo "[${FUNCNAME[1]}] $*"
}
do_thing() {
log "starting"
sleep 1
log "done"
}
Output:
[do_thing] starting
[do_thing] done
No hardcoded function names. No copy/paste mistakes. Chef’s kiss.
Add Line Numbers for Instant Context
Bash also gives you line numbers via BASH_LINENO.
log() {
echo "[${FUNCNAME[1]}:${BASH_LINENO[0]}] $*"
}
Output now looks like:
[do_thing:6] starting
[do_thing:8] done
At this point your shell scripts are starting to feel… civilised.
Printing a Call Stack (Yes, Really)
Want to see how you got here? Here’s a simple stack trace function:
stacktrace() {
echo "Call stack:"
for ((i=1; i<${#FUNCNAME[@]}; i++)); do
echo " ${FUNCNAME[$i]}:${BASH_LINENO[$((i-1))]}"
done
}
Example usage:
oops() {
stacktrace
}
a() { b; }
b() { oops; }
a
Output:
Call stack:
oops:2
b:5
a:4
Tell me that’s not beautiful.
Automatic Stack Traces on Errors (Dark Magic)
You can even hook this into Bash’s error handling.
Add this to your .bashrc or script:
set -o errtrace
trap 'echo "💥 Error in ${FUNCNAME[0]} at line ${LINENO}"; stacktrace' ERR
Now, when a command fails, Bash prints:
- the function it failed in
- the line number
- the full call stack
Congratulations — you’ve invented poor man’s exceptions.
Caveats
- This is Bash-specific
- It won’t work in POSIX sh
- It does work in interactive shells and scripts
- Zsh has similar features, but with different variables
Final Thoughts
Once you start using FUNCNAME and BASH_LINENO, scripts without them feel… naked.
If you write anything non-trivial in Bash — especially helpers, install scripts, or admin tooling — this stuff is pure gold.
Happy shell hacking 🐚✨