BASH_SOURCE и FUNCNAME: как понять, откуда реально вызвали функциюВ больших Bash-скриптах функция может вызываться из другой функции, которая пришла из отдельного файла. Обычный
$0 в такой ситуации мало что объясняет.Для этого у Bash есть специальные массивы:
BASH_SOURCE
FUNCNAME
▪️Простой пример
foo() {
echo "file: ${BASH_SOURCE[0]}"
echo "caller: ${BASH_SOURCE[1]}"
echo "function: ${FUNCNAME[0]}"
}
fooBASH_SOURCE[0] показывает файл, в котором выполняется текущая функция, а BASH_SOURCE[1] - файл, откуда она была вызвана.▪️Посмотреть весь стек вызовов
foo() {
printf '%s\n' "${FUNCNAME[@]}"
}
bar() {
foo
}
barМожно получить примерно:
foo
bar
main
То есть Bash хранит стек функций.
▪️Особенно полезно для логирования
Например:
log() {
printf '[%s] %s: %s\n' \
"$(date '+%F %T')" \
"${FUNCNAME[1]}" \
"$*"
}Теперь:
deploy() {
log "starting deployment"
}
deployможет вывести:
[2026-08-24 12:30:01] deploy: starting deployment
Лог сразу показывает, какая функция создала сообщение.
▪️А если скрипт состоит из нескольких файлов
Допустим:
main.sh
lib.sh
utils.sh
и функции вызывают друг друга через
source.Тогда:
printf '%s\n' "${BASH_SOURCE[@]}"покажет цепочку файлов, через которые прошёл вызов.
▪️Чем это отличается от
$0echo "$0"
обычно показывает имя запущенного скрипта или shell.
А:
echo "${BASH_SOURCE[0]}"показывает конкретный Bash-файл, где находится текущий код.
Это особенно заметно при использовании:
source lib.sh
▪️Почему это важно
При отладке больших shell-проектов сообщение вроде:
ERROR: failedпочти бесполезно.
А:
ERROR: deploy() in lib/deploy.shуже позволяет быстро найти источник проблемы.
BASH_SOURCE и FUNCNAME превращают Bash-функции из непрозрачного набора вызовов в трассируемый стек.BashTex 📱 #bash #linux