STAP(1) | General Commands Manual | STAP(1) |
stap - překladač a řadič systemtap skriptů
stap [ VOLBY ] JMÉNO_SOUBORU [
ARGUMENTY ]
stap [ VOLBY ] - [ ARGUMENTY ]
stap [ VOLBY ] -e SKRIPT [ ARGUMENTY ]
stap [ VOLBY ] -l PROBE [ ARGUMENTY ]
stap [ VOLBY ] -L PROBE [ ARGUMENTY ]
stap [ VOLBY ] --dump-probe-types
stap [ VOLBY ] --dump-probe-aliases
stap [ VOLBY ] --dump-functions
Program stap je hlavním uživatelským rozhraním nástroje systemtap. Přijímá požadavky na sondování systému (probing) zapsané v jednoduchém skriptovacím jazyce, překládá je do jazyka C, výsledný kód zkompiluje a vytvoří jaderný modul, který následně zavede do běžícího linuxového jádra nebo dyninst instrumentačního nástroje, aby prováděl požadovanou analýzu zkoumaného systému. Skript může být čten ze souboru (JMÉNO_SOUBORU), ze standardního vstupu (v tom případě použijte "-" namísto JMÉNO_SOUBORU), z příkazové řádky (prostřednictvím přepínače -e SKRIPT, případně -E SKRIPT). Program běží dokud není přerušen uživatelem, nebo dokud skript nezavolá exit(), nebo dokud nedojde k nastřádání dostatečného množství tzv. měkkých chyb (soft errors).
Jazyk, který je popsán níže v sekci SKRIPTOVACÍ JAZYK, je striktně typovaný, imperativní, bez explicitních deklarací, procedurální, vhodný k prototypování a inspirovaný awk a C. Umožňuje spojit místo ve zdrojovém kódu linuxového jádra, nebo uživatelské aplikace, případně systémovou událost s obslužnými rutinami, což jsou bloky kódu vykonávané synchronně. Koncepčně to připomíná skriptování v gdb.
Pro SystemTap existuje množství vzdělávacích, dokumentačních a referenčních materiálů jak v online podobě, tak i v rámci distribučních balíčků. Online dokumentace se nachází na projektovém webu https://sourceware.org/systemtap/
man stránky | |
stap (tato stránka) | syntaxe jazyka, koncepty, funkce, volby |
stapprobes | sondážní body a jejich kontextové proměnné |
stapref | rychlá reference pro syntaxi jazyka |
stappaths | seznam důležitých umístění včetně knih a odkazů |
stap-prep | instalátor závislostí jako např. ladicích informací jádra |
tapset::* | vygenerovaný seznam tapsetů |
probe::* | vygenerovaný seznam tapsetových přezdívek |
function::* | vygenerovaný seznam tapsetových funkcí |
macro::* | vygenerovaný seznam tapsetových maker |
stapvars | vybrané globální proměnné definované v tapsetech |
staprun, stapdyn, stapbpf | programy pro spuštění zkompilovaných systemtap skriptů |
systemtap | systémová služba, analýza startu systému |
stap-server | kompilační server |
stapex | několik velmi jednoduchých příkladů |
knihy | |
Beginner's Guide | učebnice základů s praktickými ukázkami |
Tutorial | hutný úvod, cvičení |
Language Reference | podrobný manuál skriptovacího jazyka |
Tapset Reference | man stránky tapsetů v podobě knihy |
odkazy | |
example scripts | množství nástrojů pro správu systému, ukázkových skriptů a výukových hraček |
Příkaz stap akceptuje následující volby. Jakákoliv jiná volba vypíše seznam podporovaných voleb. Volby lze uvést na příkazové řádce, jak je obvyklé. Pokud existuje $SYSTEMTAP_DIR/rc, mohou být volby načteny odtud a interpretovány nejdříve. Pokud není $SYSTEMTAP_DIR nastavena, použije se $HOME/.systemtap jako výchozí.
V některých případech může výchozí hodnota volby záviset na konkrétní konfiguraci systému a proto zde není přímo uvedena. V takovém případě může pomoci "stap --help".
try { ... } catch { next }
blok, který způsobuje chyby v době běhu, bude tiše potlačen. Potlačené chyby se nebudou vyhodnocovat proti limitu MAXERRORS. V tomto režimu je taktéž potlačeno testování MAXSKIPPED , takže při běhu skriptu může dojít k libovolnému množství chyb. Celkové počty chyb budou nicméně reportovány při ukončení skriptu.
Pokud je stapusr nebo stapsys specifikováno při použití kompilačního serveru (viz --use-server), pak server zkontroluje skript a, pokud kompilace uspěje, server kryptograficky podepíše výsledný modul, kde specifikuje, že daný modul je bezpečný pro použití uživatelem s danou úrovní oprávnění.
Pokud se --privilege nespecifikuje, -pN se také nespecifikuje s N < 5 a daný uživatel není root ani člen skupiny stapdev, pak stap automaticky přidá odpovídající --privilege volbu k již specifikovaným volbám.
Pokud je server specifikován pomocí hostname nebo IP adresy, pak je volitelně možné určit i číslo portu. To je vhodné pro přístup k serverům, které nejsou na lokální síti, nebo pro specifikování konkrétního serveru.
IP adresou může být jak IPv4, tak IPv6.
Pokud existuje více než jedno rozhraní s danou link-local IPv6 adresou, pak je možné zvolit konkrétní rozhraní připojením znaku "%" a názvu rozhraní k adrese, například: "fe80::5eff:35ff:fe07:55ca%eth0".
Pro určení čísla portu IPv6 adresy je nutné uzavřít adresu do hranatých závorek , aby došlo k oddělení adresy od čísla portu. Například: "[fe80::5eff:35ff:fe07:55ca]:5000" nebo "[fe80::5eff:35ff:fe07:55ca%eth0]:5000".
Pokud --use-server nebylo specifikováno, -pN nebylo specifikováno s N < 5, a uživatel není root, není člen skupiny stapdev, ale je členem skupiny stapusr, pak stap automaticky přidá --use-server k již specifikovaným volbám.
--use-server-on-error je ekvivalentem pro --use-server-on-error=yes.
Kompilace může být přerušena pro určitý typ chyby, jako například nedostatek dat nebo zdrojů. K tomu může dojít i během rekompilace. Pro rekompilaci budou servery voleny automaticky tak, jako by byla použita volba --use-server bez parametrů.
Poznamenejme, že --list-servers používá avahi-daemon k detekci online serverů. Pokud tato služba není dostupná, pak --list-servers nebude detekovat žádné online servery. Aby --list-servers detekoval servery poslouchající na IPv6 adresách, musí konfigurační soubor avahi démona, /etc/avahi/avahi-daemon.conf , obsahovat "use-ipv6=yes". Po případné úpravě konfiguračního souboru je třeba službu restartovat.
--remote libvirt://MyDomain/qemu:///system
Viz <http://libvirt.org/uri.html> pro podrobnosti ohledně podporovaných formátů URI. Viz též stapvirt(1).
Všechny další argumenty z příkazové řádky se předají kompilátoru ke zpracování. Viz níže.
Skriptovací jazyk systemtapu připomíná awk a C. Existují v něm dva hlavní konstrukty: sondy a funkce. V jejich rámci se používají příkazy a výrazy se syntaxí podobnou syntaxi jazyka C.
Bílé místo se ignoruje. Podporovány jsou komentáře tří typů:
Na konci příkazové řádky lze skriptům předat parametry. V rámci skriptu k nim pak lze přistupovat prostřednictvím $1 ... $<NN> pokud jde literály neuzavřené do uvozovek, nebo @1 ... @<NN> pokud jde o řetězcové literály uzavřené do uvozovek. Počet argumentů je přístupný prostřednictvím $# (jakožto číslo neuzavřené do uvozovek) nebo prostřednictvím @# (jakožto číslo do uvozovek uzavřené). Tyto symboly lze použit na místě libovolné lexikální jednotky skriptu, a k jejich vyhodnocení dojde již v počáteční fázi překladu (preprocessing).
Součástí lexikální analýzy je jednoduchá fáze předzpracování. V ní lze (ne)vyhodnocovat části kódu na základě podmínky. Příslušná syntaxe se obecně podobá ternárnímu operátoru: podmínka ? výraz1 : výraz2
%( PODMÍNKA %? VÝRAZ-1 %) %( PODMÍNKA %? VÝRAZ-1 %: VÝRAZ-2 %)
PODMÍNKA je buďto výraz, jehož formát je určen prvním klíčovým slovem, nebo porovnání řetězcových či numerických literálů, nebo výraz složený z takových podmínek s využitím operátorů || a &&. Nicméně, závorky zde zatím nejsou podporovány, takže je důležité mít na zřeteli, že && má při vyhodnocení přednost před ||.
Pokud první částí podmínky je identifikátor kernel_vr nebo kernel_v odkazující se k verzi jádra s příponou ("2.6.13-1.322FC3smp"), nebo bez přípony ("2.6.13"), pak následovat musí jeden z operátorů porovnání: <, <=, ==, !=, >, a >=, a třetí částí podmínky je řetězcový literál vyjadřující verzi jádra v RPM-stylu.
Podmínka se považuje za splněnou, pokud verze běžícího jádra (volitelně předefinovaná volbou -r ) se srovnává se zadanou hodnotou. Srovnání provádí glibc funkce strverscmp().
Pokud operátorem je jednoduchá rovnost (==), nebo nerovnost (!=), a pravý operand obsahuje zástupné symboly (* nebo ? nebo [), , pak celý výraz bude interpretován jako "wildcard (mis)match" a bude vyhodnocen glibc funkcí fnmatch().
Pokud první částí podmínky je arch odkazující se k architektuře procesoru (pojmenované podle ARCH/SUBARCH v terminologii jádra), pak druhou částí podmínky je jeden z operátorů: == nebo !=, a třetí částí podmínky je požadovaný řetězcový literál, který může obsahovat zástupné symboly ("wildcard (mis)match").
Podobně, pokud první složkou podmínky je identifikátor jako CONFIG_* odkazující se ke konfigurační volbě jádra, pak druhou částí podmínky je == nebo !=, a třetí částí podmínky je řetězcový literál odpovídající volby (obvykle "y", nebo "m"). Neexistující, nebo nenastavené konfigurační volby v tomto kontextu odpovídají prázdnému řetězci. Vyhodnocení opět probíhá jako "wildcard (mis)match" s využitím fnmatch().
Pokud první částí je identifikátor systemtap_v, pak se test odkazuje k verzi systemtapu, kterou lze volitelně pro staré skripty nastavit prostřednictvím volby --compatible. Operátor porovnání je jako u kernel_v , a pravým operandem je řetězec vyjadřující verzi jádra. Viz též sekce ZASTARÁVÁNÍ níže.
Pokud první částí podmínky je systemtap_privilege, pak se test odkazuje k úrovni oprávnění se kterou je systemtap skript překládán. V tomto případě je podmínkou jeden z operátorů == nebo !=, a třetí částí podmínky je jeden z řetězcových literálů "stapusr", "stapsys", nebo "stapdev".
Pokud první částí podmínky je identifikátor guru_mode, pak test ověřuje, zda je systemtap skript překládán v "guru" režimu (-g). Operátorem pro tento případ může být == nebo !=, a třetí částí podmínky je číslo. Buďto 1, nebo 0.
Pokud prvním indetifikátorem je runtime, testuje se runtime režim (--runtime). Viz sekce ALTERNATIVNÍ RUNTIME níže pro informaci o dostupných runtime backendech. Porovnávací operátor v tomto případě je == nebo !=, a třetí částí podmínky je řetězcový literál odpovídající runtime. Porovnání je typu "wildcard (mis)match" s využitím fnmatch()
Poslední možností je situace, kdy PODMÍNKA srovnává prosté číselné, nebo řetězcové literály.
VÝRAZ-1 a VÝRAZ-2 představují výskyt nuly nebo více obecných lexikálních jednotek (které mohou obsahovat další vložené podmínky preprocesoru), a jsou preprocesorem předány na vstup parseru v závislosti na vyhodnocení uvedené podmínky. Například následující kód vyvolá kompilační chybu v případě že verze běžícího jádra na cílovém systému je novější, než 2.6.5:
%( kernel_v <= "2.6.5" %? **ERROR** %) # "invalid token sequence"
Naproti tomu následující kód umožní elegantně se vyrovnat s různými verzemi jádra:
probe kernel.function (
%( kernel_v <= "2.6.12" %? "__mm_do_fault" %:
%( kernel_vr == "2.6.13*smp" %? "do_page_fault" %:
UNSUPPORTED %) %) ) { /* ... */ } %( arch == "ia64" %?
probe syscall.vliw = kernel.function("vliw_widget") {} %)
Preprocesor přijímá jednoduchá makra a vyhodnocuje je v rámci samostatné procesní fáze před vyhodnocením podmínek.
Makra se definují následující konstrukcí:
@define NAME %( BODY %) @define NAME(PARAM_1, PARAM_2, ...) %( BODY %)
Makra (a také parametry uvnitř těla maker) jsou přístupná přidáním prefixu "@" před jejich jméno"
@define foo %( x %) @define add(a,b) %( ((@a)+(@b)) %)
@foo = @add(2,2)
K expanzi maker v současnosti dochází v samostatné preprocesní fázi před zpracováním podmínek. Proto dojde k vyhodnocení všech maker v rámci kondicionálu bez ohledu na konkrétní podmínku. To může vést k nezamýšleným chybám:
// Následující kód způsobí chybu: %( CONFIG_UTRACE == "y" %?
@define foo %( process.syscall %) %:
@define foo %( **ERROR** %) %) // Následující kód bude fungovat správně: @define foo %(
%( CONFIG_UTRACE == "y" %? process.syscall %: **ERROR** %) %)
První příklad je chybný, protože vyvolá duplicitní definici makra "foo".
Za normálních okolností je definice platná lokálně - pouze v souboru kde se vyskytuje. Makro definované v tapset skriptu tedy není veřejně použitelné v rámci uživatelského skriptu. Makra, která mají být veřejně dostupná, lze sdružovat do knihoven s příponou ".stpm" nacházející se v "tapset search path". Tyto soubory mohou obsahovat @define konstrukty, které budou dostupné nejen ve všech tapsetech, ale i v uživatelských skriptech. Volitelně mohou být definice maker v rámci ".stpm" souborů zabaleny v kondicionálech preprocesoru.
V rámci tapset skriptů, nebo guru skriptů je možno přistupovat ke konstantním symbolům, jako jsou například makra jazyka C, prostřednictvím vestavěného operátoru @const(). Pokud je potřeba přidat příslušný #include dodatečného hlavičkového souboru, lze tak učinit prostřednictvím vloženého kódu jazyka C.
@const("STP_SKIP_BADVARS")
Identifikátory pro proměnné a funkce jsou alfanumerické sekvence, které mohou obsahovat _ a $. Nesmí začínat číslicí (stejně jako v C). Proměnné jsou lokální vzhledem ke svému bloku (funkce nebo sondy) a jejich životnost je spojena s tímto blokem.
Skalární proměnné jsou implicitně řetězcového, nebo celočíselného typu. Asociativní pole mohou také obsahovat řetězcové nebo celočíselné hodnoty a jako klíč jim slouží n-tice řetězců nebo celých čísel. Zde je několik příkladů:
var1 = 5 var2 = "bar" array1 [pid()] = "name" # jednoduchý číselný klíč pole array2 ["foo",4,i++] += 5 # n-tice jako klíč pole if (["hello",5,4] in array2) println ("yes") # test na členství
Překladač provádí typové odvození (type inference) na všech identifikátorech včetně indexů polí a parametrů funkcí. Nekonzistentní zacházení s typy způsobí chybu překladu.
Proměnné lze definovat jako globální, takže mohou být sdíleny mezi sondami a funkcemi, a žijí stejně dlouho jako celé systemtap sezení. Pro globální proměnné existuje jediný jmenný prostor. Přístup ke globálním proměnným je chráněn zámky, viz BEZPEČNOST A OCHRANA SOUKROMÍ. Globální proměnnou lze deklarovat kdekoli ve vnější úrovni zdrojového kódu, tedy mimo bloky sond a funkcí. Globální proměnné, kterým byla přiřazena hodnota, ale nikdy nebyla čtena, budou automaticky zobrazeny na konci systemtap sezení. Překladač se pokusí odvodit datový typ z hodnot a případně, pokud jde o pole, i z klíčů. Volitelně lze globální proměnnou inicializovat řetězcovým, nebo číselným literálem. Zde jsou příklady deklarace globálních proměnných:
global var1, var2, var3=4
Globální proměnné lze také použít jako parametry systemtap modulu. Toho lze dosáhnout buďto použitím přepínače stap -G, nebo modul připravit předem pomocí stap -p4 a parametry mu předat později při jeho zavádění na příkazové řádce programu staprun. Viz staprun(8).
Rozsah platnosti globální proměnné lze omezit na tapset soubor, nebo na uživatelský skript prostřednictvím klíčového slova "private". V tom případě je klíčové slovo "global" volitelné. Následující deklarace označuje var1 a var2 jako privátní globální proměnné:
private global var1=2 private var2
Pole mají omezenou velikost parametrem MAXMAPENTRIES. Viz BEZPEČNOST A OCHRANA SOUKROMÍ
Volitelně lze polím (která jsou vždy globální) nastavit maximální velikost v hranatých závorkách, čímž se předefinuje MAXMAPENTRIES pro dané pole. Poznamenejme, že velikost se vztahuje jen k počtu prvků, nikoliv k celkové velikosti pole v paměti. Příklad:
global tiny_array[10], normal_array, big_array[50000]
Polím lze nastavit příznak "%". To způsobí, že pokud do pole přidáme více prvků, než pro kolik je dimenzováno, začnou staré prvky mizet (LIFO). To platí jak pro asociativní, tak pro statistická pole, viz níže. Příklad:
global wrapped_array1%[10], wrapped_array2%
Mnohé sondy poskytují kontextové proměnné, což jsou hodnoty získané za běhu z jádra, nebo zkoumané uživatelské aplikace. Jejich identifikátory začínají znakem $. Sekce KONTEXTOVÉ PROMĚNNÉ v manuálové stránce stapprobes(3stap) obsahuje jejich seznamy pro jednotlivé typy sond. Tyto kontextové proměnné se stanou normálními řetězcovými nebo numerickými proměnnými použitelnými ve skriptu, jakmile provedeme příslušné přiřazení (např. foo=$foo). Podívejte se níže na sekci PŘETYPOVÁNÍ, kde je popsáno jak takovou proměnnou přetypovat zpět na ukazatel je-li to třeba.
Příkazy umožňují procedurální řízení běhu skriptu. Mohou se vyskytovat uvnitř funkcí a obslužných rutin sond. Celkový počet příkazů, které je v reakci na nějakou událost možno spustit, je omezen na hodnotu definovanou makry MAXACTION_* ve vygenerovaném C-kódu a pohybuje se kolem 1000.
Není chybou pokusit se smazat prvek, který neexistuje.
SystemTap podporuje množství operátorů, které mají syntaxi a sémantiku velmi podobnou jejich C a awk protějškům. Aritmetické operace se provádějí v souladu s pravidly jazyka C pro celá čísla se znaménkem. Dělení nulou nebo přetečení rozsahu se detekuje a způsobí chybu.
Skriptovací jazyk systemtapu podporuje práci s regulárními výrazy. Základní operace testující (ne)shodu řetězce s regulárním výrazem:
exp =~ regex exp !~ regex
První operand musí být výraz vyhodnotitelný na řetězec; druhý operand musí být řetězcový literál obsahující platný regulární výraz.
Syntaxe regulárních výrazů podporuje většinu rozšířených regulárních výrazů POSIX standardu. Výjimkou je znovupoužití částí regulárního výrazu ("\1").
Po úspěšném nalezení je text vyhovující regulárnímu výrazu dostupný prostřednictvím tapsetových funkcí matched() a ngroups() následovně:
if ("an example string" =~ "str(ing)") {
matched(0) // -> vrací "string", t.j. celý odpovídající řetězec
matched(1) // -> vrací "ing", t.j. první odpovídající podřetězec
ngroups() // -> vrací 2, t.j. počet odpovídajících skupin řetězců }
Hlavním syntaktickým konstruktem skriptovacího jazyka jsou sondy (probes). Sondy spojují abstraktní události s bloky příkazů a vytvářejí tak obslužné rutiny událostí. Obecná syntaxe je následující:
probe PROBEPOINT [, PROBEPOINT] { [STMT ...] } probe PROBEPOINT [, PROBEPOINT] if (CONDITION) { [STMT ...] }
Události jsou určeny syntaxí nazývanou sondážní body (probe points). Existuje množství variant sondážních bodů. Některé jsou definovány překladačem a mnohé další jsou definovány v tapset skriptech jako přezdívky. Sondážní body mohou využívat zástupné znaky, být seskupovány, může být určováno jejich pořadí, či mohou být deklarovány jako volitelné. Více podrobností o syntaxi a sémantice sondážních bodů viz
Obslužná rutina sondy se interpretuje relativně ke kontextu dané události. Pro události související s kernel kódem může tento kontext obsahovat proměnné definované ve zdrojovém kódu jádra. Takové "kontextové" proměnné jsou pak přístupné ve skriptu z prefixem "$". Jsou přístupné pouze pokud byly kompilátorem jádra zachovány navzdory optimalizacím. To je stejné omezení s jakým se potýká debugger když pracuje s optimalizovaným kódem. Navíc musí tyto objekty být v momentě vykonávání obslužné rutiny sondy přítomny přímo v nastránkované (in-paged) paměti, protože systemtap nesmí zapříčinit žádné dodatečné stránkování. Některé sondy mají velmi málo kontextových proměnných. Viz stapprobes(3stap).
Proby mohou být doplněny podmínkou pro uzamčení, sestávající z jednoduchého booleovského výrazu. Sonda je "odemčená" (tedy neaktivní) vyhodnocuje-li se zamykací podmínka na false. V tomto stavu některé sondy snižují nebo zcela eliminují svoji režii, tedy nekonzumují systémové prostředky. Jakmile se zamykací podmínka vyhodnotí na true bude sonda brzy znovu uzamčena a její obslužná rutina začne brzy být opět volána když nastane příslušná událost. Přestože je zamykání rychlé, trvá nenulový čas, a některé události nemusejí být zachyceny. V případech kdy toto může představovat problém, je lepší zamykání sond nepoužívat.
Nové sondážní body lze definovat pomocí přezdívek (probe aliases). Definice přezdívky vypadá podobně jako definice sondy samotné, ale namísto aktivování sondy v daném místě pouze definují nové jméno - přezdívku pro již existující sondážní bod. Existují dva typy přezdívek: "prologue" a "epilogue", které jsou definovány pomocí "=" nebo resp. "+=".
Přezdívka typu "prologue" vznikne tak, že se blok příkazů, který následuje definici této přezdívky, přidá před sondu ke které se váže jako její prolog. Naproti tomu přezdíka typu "epilogue" vznikne tak, že blok příkazů, který následuje definici této přezdívky, se přidá za sondu ke které se váže jako její epilog. Například:
probe syscall.read = kernel.function("sys_read") {
fildes = $fd
if (execname() == "init") next # přeskočit zbytek sondy }
definuje nový sondážní bod. syscall.read, který se rozšiřuje na kernel.function("sys_read"), s daným příkazem jako prologem, což je výhodné k předdefinování některých proměnných pro danou přezdívku a/nebo pro přeskočení dané sondy v závislosti na podmínce. Naproti tomu
probe syscall.read += kernel.function("sys_read") {
if (tracethis) println ($fd) }
definuje nový sondážní bod s daným příkazem jako epilogem, což může být užitečné k provedení činností v závislosti na hodnotách proměnných nastavených uživatelem přezdívky. Poznamenejme, že v každém případě jsou příkazy v obslužné rutině přezdívky vykonávány za běhu, takže v danou chvíli zejména nedochází k vyhodnocování/substituci maker.
Přezdívku lze použít stejně jako vestavěnou sondu překladače.
probe syscall.read {
printf("reading fd=%d\n", fildes)
if (fildes > 10) tracethis = 1 }
Systemtap skripty mohou definovat funkce. Ty mohou přijímat libovolný počet skalárních (celočíselných nebo řetězcových) parametrů, a vrací jednu skalární funkční hodnotu. Příklad funkce:
function thisfn (arg1, arg2) {
return arg1 + arg2 }
Povšimněme si absence explicitních deklarací typů. Typy, jsou odvozeny (inferred) překladačem. Nicméně, pokud je to potřeba, může definice funkce zahrnovat explicitní deklarace návratového typu a/nebo typů argumentů. To je užitečné zejména pro vložené C funkce. V následujícím příkladě je automatické odvození typu nutné jen pro arg2 (řetězec):
function thatfn:string (arg1:long, arg2) {
return sprint(arg1) . arg2 }
Funkce se mohou volat navzájem až do určitého limitu zanoření. Tento limit je definován makrem MAXNESTING ve vygenerovaném zdrojovém kódu modulu a pohybuje se okolo 10.
Funkce lze označit za privátní použitím klíčového slova "private". Tím se omezí jejich platnost soubor (tapset nebo uživatelský skript) ve kterém jsou definovány. Příklad:
private function three:long () { return 3 }
Existuje několik funkcí, se kterými překladač zachází neobvykle. Poznamenejme, že data jsou generována v jaderném modulu a před tiskem musí být přenesena do uživatelského prostoru. Tyto funkce formátují hodnoty pro pohodlný tisk do výstupního proudu systemtapu. Varianty funkce
sprint* vracejí formátovaný řetězec namísto aby ho přímo vypisovaly.
Formátovací řetězec příkazu printf je podobný jako v jazyce C s tím, že zde probíhá typová kontrola.
Znak # zapíná alternativní formátování: Oktalovým číslům přidá prefix "0", hexadecimálním "0x", nebo "0X", a netisknutelným znakům v řetězci přidá prefix "escape" sekvence.
Příklady:
a = "alice", b = "bob", p = 0x1234abcd, i = 123, j = -1, id[a] = 1234, id[b] = 4567 print("hello") Vypíše: hello println(b) Vypíše: bob\n println(a . " is " . sprint(16)) Vypíše: alice is 16 foreach (name in id) printdln("|", strlen(name), name, id[name]) Vypíše: 5|alice|1234\n3|bob|4567 printf("%c is %s; %x or %X or %p; %d or %u\n",97,a,p,p,p,j,j) Vypíše: a is alice; 1234abcd or 1234ABCD or 0x1234abcd; -1 or 18446744073709551615\n printf("2 bytes of kernel buffer at address %p: %2m", p, p) Vypíše: 2 byte of kernel buffer at address 0x1234abcd: <binary data> printf("%4b", p) Vypíše (these values as binary data): 0x1234abcd printf("%#o %#x %#X\n", 1, 2, 3) Vypíše: 01 0x2 0X3 printf("%#c %#c %#c\n", 0, 9, 42) Vypíše: \000 \t *
Často je výhodné sbírat statistická data způsobem, který netrpí problémy s exkluzivním zamykáním globálních proměnných, kde se data udržují. Systemtap nabízí řešení ve formě speciálního operátoru pro uchovávání statistických dat a sady agregačních pseudofunkcí.
Agregační operátor je <<<, a připomíná přiřazení, nebo operaci pro zápis do výstupního proudu známou z C++. Levý operand je skalární proměnná (nebo /skalární/ prvek pole - viz příklad níže), která musí být deklarována jako globální. Pravým operandem je číselný výraz. Význam je intuitivní: Přidej dané číslo na hromadu nad kterou bude později možno provádět statistické operace. Seznam funkcí pro extrakci statistických údajů je uveden níže. Příklad:
foo <<< 1 stats[pid()] <<< memsize
Funkce pro extrakci statistiky jsou neobvyklé. Pro každý výskyt extrakční funkce pracující s daným identifikátorem zajistí překladač výpočet požadovaného statistického údaje. Statistický subsystém tedy funguje "na požádání" a výpočet probíhá v reálném čase na všech dostupných CPU.
Zde je seznam extrakčních funkcí. Prvním argumentem každé z nich je ta stejná l-hodnota, která byla použita pro akumulaci statistiky operátorem <<<. Extrakční funkce @count(v), @sum(v), @min(v), @max(v), @avg(v), @variance(v[, b]) počítají počet, sumu, minimum, maximum, aritmetický průměr, a střední kvadratickou odchylku přes všechny nashromážděné hodnoty. Funkčními hodnotami jsou celá čísla. Pole obsahující agregační data lze třídit a/nebo přes ně iterovat. Viz cyklus foreach výše.
Střední kvadratická odchylka se vyčísluje s použitím Welfordova algoritmu. Výpočty jsou prováděny v celočíselné aritmetice, proto mohou trpět nízkou přesností. Pro zlepšení přesnosti lze využít volitelný parametr b, tzv. bitový posun, s hodnotami od 0 (výchozí hodnota) do 62. Pro danou statistickou veličinu, resp. jí odpovídající globální proměnnou ve skriptu, lze použít pouze jednu jedinou hodnotu bitového posunu. Vyšší hodnoty bitového posunu zvyšují přesnost, ale zároveň zvyšují riziko přetečení.
$ stap -e \ > 'global x probe oneshot { for(i=1;i<=5;i++) x<<<i println(@variance(x)) }' 12 $ stap -e \ > 'global x probe oneshot { for(i=1;i<=5;i++) x<<<i println(@variance(x,1)) }' 2 $ python3 -c 'import statistics; print(statistics.variance([1, 2, 3, 4, 5]))' 2.5 $
K přetečení může dojít zejména při interním násobení velkých čísel. Pokud k tomu dojde, může střední kvadratická odchylka vycházet záporná, což je normálně nepřípustné. Zvažte normalizování vašich dat. Přičtení, či odečtení konstanty ke všem hodnotám statistického vzorku nemění hodnotu střední kvadratické odchylky. Podělení všech hodnot statistického vzorku konstantou způsobí zmenšení střední kvadratické odchylky o čtverec dané konstanty.
Dostupné jsou též histogramy. Například @hist_linear(v,start,stop,interval) reprezentuje lineární histogram od "start" do "stop" s inkrementem "interval". Inkrement musí být kladný. Podobně @hist_log(v) představuje binárně logaritmický histogram. Histogram lze vytisknout některou z rodiny print funkcí. Výsledkem je ASCII-art. Příklad:
probe timer.profile {
x[1] <<< pid()
x[2] <<< uid()
y <<< tid() } global x // pole global y // skalár probe end {
foreach ([i] in x @count+) {
printf ("x[%d]: avg %d = sum %d / count %d\n",
i, @avg(x[i]), @sum(x[i]), @count(x[i]))
println (@hist_log(x[i]))
}
println ("y:")
println (@hist_log(y)) }
Jakmile se ukazatel uloží do
celočíselné proměnné v rámci
systemtap skriptu, překladač ztrácí informaci o
typu, která je potřebná k
dereferencování.
(viz KONTEXTOVÉ PROMĚNNÉ man stránky
stapprobes(3stap)). Použitím operátoru
@cast() sdělujeme kompilátoru, jak má
interpretovat takové číslo jakožto
typovaný ukazatel. Příklad:
@cast(p, "type_name"[, "module"])->member
Takto bude p interpretován jako ukazatel do struktury/unionu type_name a dereferencovat member . Lze připojit další ->subfield a dereferencovat tak další úrovně. Poznamenejme, že pro přímé dereferencování ukazatele se doporučuje použít funkcí {kernel,user}_{char,int,...}($p). Více v sekci stapfuncs(5).
POZNÁMKA: stejný operátor -> se používá jak pro přímý odkaz na člena, tak pro dereferenci ukazatele. Systemtap automaticky interpretuje tuto dvojakost. Volitelná složka module informuje překladač, kde má hledat informaci o daném typu. module lze uvést vícekrát jako seznam s oddělovačem :. Pokud module není explicitně určen, budou pro jeho určení využity ladicí informace, nebo bude nastaven na "kernel" pro funkce a všechny ostatní typy sond.
Překladač může vytvořit svůj vlastní modul s informacemi o typech odvozením z hlavičkových souborů uzavřených ve špičatých závorkách v případě, že ladicí informace nejsou k dispozici. Hlavičkovým souborům jádra je třeba přidat řetězec "kernel" jako předponu. Ostatní hlavičkové soubory budou zpracovány s výchozími volbami kompilátoru. Lze specifikovat více hlavičkových souborů za sebou pro vyřešení závislostí.
@cast(tv, "timeval", "<sys/time.h>")->tv_sec @cast(task, "task_struct", "kernel<linux/sched.h>")->tgid @cast(task, "task_struct",
"kernel<linux/sched.h><linux/fs_struct.h>")->fs->umask
Hodnoty získané operátorem @cast lze přehledně vytisknout (pretty-print) připojením operátoru $ a $$ jak je popsáno v sekci KONTEXTOVÉ PROMĚNNÉ man stránky stapprobes(3stap).
V guru režimu (-g) umožňuje překladač také přiřadit novou hodnotu dereferencovaným ukazatelům.
Přetypování je také užitečné v případě void* členů jejichž typ lze určit až za běhu. Příklad:
probe foo {
if ($var->type == 1) {
value = @cast($var->data, "type1")->bar
} else {
value = @cast($var->data, "type2")->baz
}
print(value) }
V guru režimu přijímá překladač vložený C kód v uživatelských skriptech. Takový kód je uzavřen mezi značkami %{ a %} a je doslovně, bez analýzy, vložen do vnější úrovně vygenerovaného kódu systemtap modulu. Protože je vložen do vnější úrovně, je možné takto definovat #include direktivy a různé pomocné definice použitelné ve zbytku kódu.
Dalším místem, kde je vložené C povoleno, je tělo funkce. V tomto případě bude tělo systemtap funkce doslovně tvořeno vloženým C kódem uzavřeným mezi značky %{ a %}. Takto vložený C kód může vykonávat libovolnou rozumnou a bezpečnou činnost. Existuje množství nedokumentovaných a komplexních omezení ohledně atomicity, souběžnosti, spotřeby zdrojů a časových omezení, takže jde o pokročilou techniku.
Paměťová umístění vyhrazená pro vstupní a výstupní hodnoty jsou zpřístupněna pomocí maker STAP_ARG_* a STAP_RETVALUE. Chyby lze signalizovat pomocí STAP_ERROR, výstup pomocí STAP_PRINTF a návratovou hodnotu lze předat prostřednictvím STAP_RETURN. Zde je několik příkladů:
function integer_ops (val) %{
STAP_PRINTF("%d\n", STAP_ARG_val);
STAP_RETVALUE = STAP_ARG_val + 1;
if (STAP_RETVALUE == 4)
STAP_ERROR("wrong guess: %d", (int) STAP_RETVALUE);
if (STAP_RETVALUE == 3)
STAP_RETURN(0);
STAP_RETVALUE ++; %} function string_ops (val) %{
strlcpy (STAP_RETVALUE, STAP_ARG_val, MAXSTRINGLEN);
strlcat (STAP_RETVALUE, "one", MAXSTRINGLEN);
if (strcmp (STAP_RETVALUE, "three-two-one"))
STAP_RETURN("parametr měl být be three-two-"); %} function no_ops () %{
STAP_RETURN(); /* funkce bez návratové hodnoty */ %}
Typy funkčních hodnot a typ návratové hodnoty odvodí překladač ze způsobu volání dané funkce. Před vytvářením vlastních vložených C funkcí je vhodné prostudovat zdrojový kód, který překladač generuje pro běžné funkce skriptovacího jazyka a tím se inspirovat.
Poslední místo, kde je vložené C povoleno, je r-hodnota ve výrazu. V tomto případě se C-kód uzavře mezi značky %{ a %} a interpretuje se jako běžná hodnota výrazu. Předpokládá se pak, že jde o 64 bitové číslo se znaménkem, ovšem pokud se použije značka /* string */, bude hodnota výrazu interpretována jako řetězec. Příklad:
function add_one (val) {
return val + %{ 1 %} } function add_string_two (val) {
return val . %{ /* string */ "two" %} }
K nastavení bezpečnosti a optimalizace lze použít následující značky:
Skripty instalované v umístění definovaném ve stappaths(7) poskytují množství vestavěných sondážních bodů. Ty jsou popsány v man stránce stapprobes(3stap).
Systemtap zpracovává skript v pěti procesních fázích: "parse", "elaborate", "translate", "compile" a "run". Překladač zahájí fázi 1 lexikální analýzou uživatelského skriptu spolu se všemi tapset skripty (což jsou soubory s příponou *.stp) nalezenými v tapset adresáři. Adresáře vyjmenované prostřednictvím -I jsou následně zpracovány také, a to v guru režimu. Adresářová struktura se prohledává do hloubky. Některé podadresáře jsou specifické pro verzi jádra (volba -R ), a podle ní jsou (nebo nejsou) prohledávány, takže skripty specifičtější pro danou verzi jádra mohou předefinovat své méně specifické protějšky. Například pro verzi jádra 2.6.12-23.FC3 by byly prohledávány následující adresáře: 2.6.12-23.FC3/*.stp, 2.6.12/*.stp, 2.6/*.stp, a nakonec *.stp v tomto pořadí. Pokud překlad skončí na konci fáze 1 (-p1), pak překladač na standardní výstup vypíše derivační strom (parse tree).
Ve fázi 2 překladač analyzuje vstupní skript, aby vyhodnotil symboly a datové typy. Odkazy na proměnné, funkce a přezdívky, které se nepodaří vyhodnotit lokálně, se vyhodnotí proti tapset skriptům. Pokud je určitý symbol nalezen v tapset skriptu, pak daný tapset bude celý přidán do fronty pro zpracování překladačem. Tento iterativní proces skončí jakmile jsou vyhodnoceny všechny symboly s využitím dané podmnožiny tapset skriptů.
Dále se ověří validnost sondážních bodů. Sondy, které se odkazují k umístěním ve zdrojovém kódu ("synchronní sondážní body") vyžadují, aby byly nainstalovány příslušné ladicí informace. V obslužných rutinách sond se naleznou cílové proměnné (ty, které začínají znakem "$") a dekódují se jejich "run-time" lokace.
Dále se všechny sondy a funkce optimalizují. Cílem je odstranit zbytečné proměnné, výrazy a funkce, které nemají vedlejší účinky. U vložených C funkcí se předpokládá, že mají vedlejší účinky pokud ovšem neobsahují kouzelnou značku /* pure */. Vzhledem k tomu, že optimalizace mohou způsobit latentní chyby jako je například typová nekompatibilita, nebo neplatné kontextové proměnné, může být v některých případech užitečné optimalizace vypnout přepínačem -u.
Nakonec se z kontextu odvodí datové typy proměnných, funkcí, parametrů, polí a indexů. Ukončení překladu po fázi 2 (-p2) způsobí vypsání seznamu všech sond, funkcí a proměnných spolu s jejich odvozenými typy. Nekonzistentní nebo neodvoditelné typy způsobí chybu překladu.
Ve fázi 3 překladač zapíše vygenerovaný C kód a vytvoří Makefile který slouží k jeho přeložení do podoby jaderného modulu. Tyto soubory budou umístěny v dočasném adresáři. Zastavení překladače v této fázi (-p3) způsobí vypsání C souboru na standardní výstup.
Ve fázi 4 překladač vyvolá jaderný "build systém", aby sestavil systemtap modul. Při tom se v daném dočasném adresáři volá příkaz make. K úspěšnému provedení tohoto kroku je třeba, aby byl nainstalován "build systém" jádra, tj. hlavičkové soubory, config a Makefile soubory a to v obvyklém umístění /lib/modules/VERSION/build. Zastavení překladače v této fázi (-p4) může být užitečné, pokud chceme modul archivovat. Je to také poslední šance zastavit systemtap před zavedením a spuštěním modulu.
Ve fázi 5 překladač zavolá pomocný program staprun a předá mu vzniklý systemtap modul. Program staprun zavede modul do jádra, spustí jej a zajišťuje komunikaci s ním dokud činnost modulu neskončí. Jakákoliv chyba běhu, která se vyskytne v obslužných rutinách sond, jako např. vyčerpání dostupné paměti, dělení nulou, příliš hluboké zanoření, nebo překročení "run-time" limitů, způsobí měkkou chybu (soft error). Pokud počet měkkých chyb překročí MAXERRORS, zastaví se všechny sondy (kromě těch, které obsluhují chyby), a zastaví se sezení. Nakonec staprun odstraní modul z jádra a provede úklid.
Je dobré neukončovat stap proces násilím, například prostřednictvím signálu SIGKILL, protože proces stapio (potomek procesu stap) a systemtap modul by se nemusely korektně ukončit. Pokud se to přecejen stane, pošlete všem zbývajícím stapio procesům SIGTERM nebo SIGINT a použijte rmmod pro odstranění systemtap modulu z jádra.
Viz stapex(3stap) , kde se nachází několik krátkých příkladů, nebo viz adresář "examples" v RPM balíčcích "systemtap-client", či "systemtap-testsuite", kde se nachází rozsáhlá sbírka příkladů. Viz stappaths(7stap) pro podrobný popis konkrétních umístění. Příklady jsou také zveřejněny na webové stránce projektu systemtap.
Překladač systemtapu ukládá do cache výstup fáze 3 (tj. vygenerovaný C kód) a výstup fáze 4 (tj. zkompilovaný jaderný modul) pokud tyto fáze skončí bez chyb. Obsah cache se použije pokud se znovu překládá stejný skript a za předpokladu, že platí stejné podmínky (verze jádra, verze systemtapu atp.). Cache se nachází v adresáři $SYSTEMTAP_DIR/cache . Velikost cache lze omezit umístěním souboru cache_mb_limit do cache adresáře, přičemž tento soubor obsahuje ASCII číselnou hodnotu limitu, která vyjadřuje velikost cache v MiB. Pokud tento soubor neexistuje, vytvoří se nový s výchozí hodnotou 256. Jde o měkký limit v tom smyslu, že cache bude promazána až po určité době. Dočasně tedy může velikost cache překročit stanovený limit. Zmíněnou periodu je možno nastavit prostřednictvím souboru cache_clean_interval_s umístěného opět v cache adresáři. Předpokládá se, že tento soubor obsahuje ASCII celé číslo vyjadřující časový interval pro promazávání cache v sekundách. Pokud tento soubor neexistuje, vytvoří se nový s výchozí hodnotou 300.
Systemtap může být použit jako mocný administrativní nástroj. Může zpřístupnit privátní uživatelské informace v rámci interních jaderných struktur. To se netýká dyninst runtime, viz ALTERNATIVNÍ RUNTIME .
Překladač zajišťuje dodržování mnoha různých bezpečnostních omezení během kompilace a běhu modulu. Snaží se zajistit, aby žádná sonda neběžela příliš dlouho, aby nealokovala příliš mnoho paměti, neprováděla nebezpečné operace, nebo nežádoucím způsobem neovlivňovala systém. Při práci s globálními proměnnými se využívají zámky pro čtení a zápis, aby nedocházelo k chybám při souběhu. Pravidelně dochází k testu na deadlocky. Pro zjištění nepřiměřeného použití zámků lze použít přepínač -t. Experimentování se skripty je tedy v zásadě bezpečné. Guru"režim -g umožňuje administrátorům obejít většinu bezpečnostních opatření a umožnit tak invazivní zásahy a změny stavu systému, použít vložené C a obecně zvýšit riziko průšvihu. Za normálních okolností je pro všechny moduly aktivní ochrana proti přetížení. Tu lze vypnout přepínačem --suppress-time-limits.
Chyby zachycené při běhu za normálních okolností vedou k čistému ukončení skriptu s chybovou hláškou. Přepínač --suppress-handler-errors umožňuje zcela ignorovat měkké chyby, takže ani po nastřádání jejich většího počtu nedojde k ukončení skriptu.
Aby bylo možné spustit systemtap modul v rámci výchozí kernel runtime, musí uživatel splnit jednu z následujících podmínek:
Uživatel root, nebo uživatel, který je členem skupin stapdev a stapusr , může přeložit a spustit libovolný systemtap skript.
Uživatel, který je členem skupin stapsys a stapusr, může použít předem připravené systemtap moduly za následujících podmínek:
Členové pouze skupiny stapusr mohou používat jen předem připravené moduly za následujících podmínek:
nebo
Jaderné moduly vygenerované programem stap se zavádějí do jádra a spouštějí pomocí programu staprun. Staprun je součástí systemtap balíčku určeného k zavádění a odstraňování modulů (za daných podmínek). Slouží také k přenosu dat mezi systemtap modulem a uživatelelm. Protože staprun neprovádí žádné bezpečnostní kontroly modulu se kterým pracuje, bylo by od administrátora systému nemoudré přidat nedůvěryhodného uživatele do skupiny stapdev nebo stapusr .
Pokud má systém v rámci UEFI firmware zapnutý SecureBoot, všechny jaderné moduly musejí být kryptograficky podepsány. (Některá jádra dovolují vypnout SecureBoot za běhu kombinací kláves SysRq-X. Poté nemusí být moduly podepsané.) Kompilační server systemtapu může podepisovat moduly klíčem MOK (Machine Owner Key) který sdílí s daným systémem. Pro více informací viz následující wiki:
Mnoho omezení pro využívání prostředků systému se nachází ve formě maker ve vygenerovaném C kódu systemtap modulu. Ty lze předefinovat prostřednictvím přepínače -D. Seznam zmíněných maker:
global big[10000],little[5]
nebo je možno využít modifikátoru % , čímž se zapne array-wrapping (nahrazování "starých" prvků) jako v následujícím příkladu:
global big%
Viz sekce o polích.
MAXSTRINGLEN. Tento limit lze nastavit specificky pro jednotlivé sondy pomocí syntaxe .maxsize(MAXSIZE) .
Pokud skript obsahuje sondy vázané na přerušení, je možné, že k přerušení dojde tak často, že handler daného přerušení ještě nedoběhne zatímco dojde k dalšímu přerušení. V tomto případě bude obslužná rutina přeskočena, aby se zamezilo reentranci. Tento problém lze obejít použitím -DINTERRUPTIBLE=0kodstíněníběžícíobslužnérutinyoddanéhopřerušení. Tento přístup přináší jistou režii, ale v běžných případech zamezí reentranci. Nicméně, sondy v NMI handlerech a v samotném procesu stap, mohou stále být přeskočeny, aby se zamezilo reentranci.
Vznikne-li problém při běhu programu stap nebo staprun když už sondy běží, je možné bezpečně zabít oba tyto uživatelské procesy a odstranit systemtap modul pomocí rmmod. Část výstupu se tak nicméně může ztratit.
Systemtap umožňuje přístup k interním datům jádra a tedy potenciálně k soukromým datům uživatele. Z tohoto důvodu je plný přístup k systemtapu omezen na uživatele root a na uživatele, kteří jsou členy skupin stapdev a stapusr.
Nicméne omezená sada funkcí systemtapu může být dostupná důvěryhodným neprivilegovaným uživatelům. Tito uživatelé jsou členy pouze skupiny stapusr plus případně skupiny stapsys.
Tito uživatelé mohou zavést do jádra předem připravený modul, který byl podepsán důvěryhodným kompilačním serverem. Viz popis voleb --privilege a --use-server. Viz také README.unprivileged mezi zdrojovými soubory systemtapu. Tam je mj. popsáno jak nastavit důvěryhodný kompilační server.
Omezení která plynou z volby --privilege=stapsys mají zabránit neprivilegovaným uživatelům v
Omezení, která plynou z volby --privilege=stapusr mají zabránit neprivilegovaným uživatelům v
Člen skupin stapusr a stapsys má přístup ke všem sondám.
Člen pouze skupiny stapusr může použít následující sondy:
Následující vlastnosti skriptovacího jazyka jsou pro neprivilegovaného uživatele nedostupné:
Neprivilegovaných uživatelů se týkají také následující omezení runtime:
Na členy pouze skupiny stapusr se vztahují dodatečná omezení:
Některé volby příkazové řádky poskytují přístup k funkcionalitě, která nesmí být přístupná žádnému neprivilegovanému uživateli. Konkrétně
-a, -B, -D, -I, -r, -R
Neprivilegovaní uživatelé nesmějí nastavit následující proměnné prostředí:
SYSTEMTAP_RUNTIME SYSTEMTAP_TAPSET SYSTEMTAP_DEBUGINFO_PATH
Obecně jsou tapset funkce přístupné členům skupiny stapusr pokud nepřistupují k informacím, které by neměl právo získat libovolný uživatelský program běžící s identitou daného uživatele.
Existují dvě skupiny tapset funkcí pro neprivilegované uživatele. První kategorie sestává z funkcí, které mohou použít všichni uživatelé, jako napřiklad:
cpu:long () exit () str_replace:string (prnt_str:string, srch_str:string, rplc_str:string)
Druhou skupinou jsou tzv. myproc-unprivileged funkce, které mohou sbírat informace pouze o procesech, které daný uživatel vlastní. Skripty, které mají používat myproc-unprivileged funkce musí testovat is_myproc() a volat takové funkce jen když výsledek je 1. Skript se ihned ukončí, pokud tato podmínka nebude splněna. Přiklady myproc-unprivileged funkcí:
print_usyms (stk:string) user_int:long (addr:long) usymname:string (addr:long)
Pokud se uživatel patřící pouze do skupiny stapusr pokusí použít tapset funkci, která nespadá do žádné ze zmíněných dvou kategorií, dojde k chybě při kompilaci.
Jak již bylo zmíněno, systemtap používá jako výchozí tzv. "kernel runtime backend", který pracuje na principu jaderného modulu. To přináší výše zmíněná bezpečnostní úskalí. Systemtap nově obsahuje dva prototypy nových "backendů", které lze aktivovat volbami --runtime=dyninst a --runtime=bpf.
--runtime=dyninst využívá Dyninst a lze jej použít k instrumentaci uživatelských procesů. Není založen na bázi jaderných modulů a nevyžaduje rootovské oprávnění. Zůstávají v něm ale v platnosti omezení na povolené typy sond.
Dyninst backend pracuje v režimu připojení se k cílovému procesu, proto vyžaduje volbu -c COMMAND, nebo -x PID process. Napřiklad:
stap --runtime=dyninst -c "stap -V" \
-e "probe process.function("main")
{ println("hi from dyninst!") }"
Pro správnou funkci dyninst runtime může být nezbytné zapnout na cílovém systému SELinux volbu allow_execstack:
# setsebool allow_execstack 1
--runtime=bpf překládá systemtap skript na extended Berkeley Packet Filter (eBPF) program. Linuxové jádro kontroluje eBPF programy z hlediska bezpečnosti, a spouští je na svém interním virtuálním stroji. Tento "runtime backend" je v časné fázi vývoje, a momentálně trpí řadou omezení, viz stapbpf(8).
V případě úspěšného běhu vrátí příkaz stap kód 0 (exit code). V opačném případě se na standardní chybový výstup může vypsat chybová hláška a stap vrátí nenulový kód. Pro zvýšení upovídanosti použijte -v nebo -vp N .
V "listing" režimu (-l and -L), se chyby obvykle potlačují. Pokud byla nalezena alespoň jedna sonda vyhovující zadaným požadavkům, stap skončí s návratovým kódem 0.
Skript, který skončí svůj běh na žádost uživatele použitím ^C / SIGINT, se považuje za úspěšně ukončený.
Během vývoje systemtapu dochází občas ve skriptovacím jazyce k nekompatibilním změnám, takže staré skripty mohou přestat fungovat. V takovém případě může pomoci volba --compatible VERSION kde se určí poslední známá verze systemtapu, se kterou daný skript fungoval.
Při použití volby --check-version vypíše systemtap varování pokud narazí při lexikální analýze na nekompatibilní element. Informace o zastarávání se udržují v souboru NEWS.
Smyslem mechanizmu zastarávání je přinést žádoucí inovace skriptovacího jazyka a současně nerozbít kompatibilitu se starými existujícími skripty. Mechanizmus zastarávání by tedy měl být chápán především jako služba přinášející pohodlí uživatelům (a nepohodlí vývojářům) spíše než naopak.
Poznamenejme, že tapset identifikátory s předponou "_" jsou považovány za interní a občas podstupují změny při kterých je těžké zaručit zpětnou kompatibilitu i při použití mechanizmu zastarávání. V případě potřeby, prosím, navrhněte takový symbol k regulernímu zveřejnění.
stapprobes(3stap), function::*(3stap), probe::*(3stap), tapset::*(3stap), stappaths(7), staprun(8), stapdyn(8), systemtap(8), stapvars(3stap), stapex(3stap), stap-server(8), stap-prep(1), stapref(1), awk(1), gdb(1)
Prosím, použijte následující bugzilla link, nebo náš mailing list. http://sourceware.org/systemtap/, <systemtap@sourceware.org>.
error::reporting(7stap), https://sourceware.org/systemtap/wiki/HowToReportBugs