Polecenie caller

man alias

caller: caller [wyrażenie]
    Zwrócenie kontekstu wywołania bieżącej procedury.
    
    Bez WYRAŻENIA zwracane jest "$linia $plik". Z WYRAŻENIEM zwracane jest
    "$linia $procedura $plik"; dodatkowe informacje służą do udostępnienia
    śladu stosu.
    
    Wartość WYRAŻENIA określa o ile ramek wywołań względem bieżącej ramki
    należy się cofnąć; numer najwyższej ramki to 0.
    
    Stan wyjściowy:
    Polecenie zwraca 0, chyba że powłoka nie wykonuje funkcji lub WYRAŻENIE
    jest nieprawidłowe.

Informacja

Polecenie caller pozwala na łatwiejsze debugowanie skryptu napisanego w bash, poprzez umożliwenie śledzenia skąd konkretna funkcja została wywołana („kto ją zawołał”).

Polecenie caler należy wywołać w ciele funkcji, która chcemy śledzić. Polecenie caller wyświetla miejsca użycia „śledzonej funkcji” w skrypcie, a rezultatem jej wykonania jest:

  • informacja o numerze linii w kodzie, w którym została wywołana „śledzona funkcja”,
  • nazwa funkcji w której użyto „śledzonej funkcji”,
  • nazwa pliku wykonywalnego z którego nastąpiło wywołanie „śledzonej funkcji”.

Ostrzeżenie

Polecenie caller nie zwróci nam listy wszystkich miejsc w skrypcie „skąd jest wywoływana moja funkcja?”. caller pozwala śledzić tylko takie funkcje, które zostały uruchomione w czasie wykonywania skryptu.

Przykłady użycia

johny@ThinkPad:~$ bash <<\EOF
czy_chodzi_o_mnie () {
  echo "> Czy ja to mam wykonac?"
  caller 0
  echo "> Tak to ja mam wykonac"
}

przygotuj_sie () {
  czy_chodzi_o_mnie
  echo "> Przygotowuje sie"
}

wykonaj_cos_skomplikowanego () {
  echo "> Rozpoczynam wykonywanie czegos skomplikowanego"
  przygotuj_sie
  echo "> Skonczylem wykonywanie czegos skomplikowanego"
  caller
}

echo -e "\n"
wykonaj_cos_skomplikowanego
EOF

> Rozpoczynam wykonywanie czegos skomplikowanego
> Czy ja to mam wykonac?
8 przygotuj_sie main
> Tak to ja mam wykonac
> Przygotowuje sie
> Skonczylem wykonywanie czegos skomplikowanego
19 NULL
johny@ThinkPad:~$ bash <<\EOF
die() {
  local frame=0
  while caller $frame; do
    ((frame++));
  done
  echo "$*"
  exit 1
}

f1() { die "*** an error occured ***"; }
f2() { f1; }
f3() { f2; }

echo -e "\n"
f3
EOF

10 f1 main
11 f2 main
12 f3 main
*** an error occured ***