class: center, middle # Tracing unter GNU/Linux Roentgenblick-Superkraefte fuer SysOps --- # Was ist Tracing? > In software engineering, tracing involves a specialized use of logging to record information about a program's execution. > — **Wikipedia** -- ---- Def. nicht vollstaendig bzw. umfassend, weil heute auch andere Dinge als ein laufendes Programm "getraced" werden koennen, bspw. CPU Events. Auch ist Tracing heute nicht auf *ein* einzelnes Programm beschraenkt. -- ---- Beispiel **LogLevel Trace**: > Logs that contain the most detailed messages. These messages may contain sensitive application data. [...] > — **Microsoft ASP.Net Core Documentation** --- # Welche Vorteile bietet Tracing? Gegenueber etwa ... ## Logging Tracing ermoeglicht den Einblick in interne (Programm-)Ablaeufe in einem sehr hohen Detailgrad - und in Winkel hinein, die die Entwickler nicht a priori vorgesehen haben. -- ## dem Lesen von Quellcode Beim Tracing beobachte ich ein Programm, waehrend es arbeitet. Das spart Phantasie und Hirnschmalz, und ermoeglicht die Konzentration auf das konkrete Problem bzw. Verhalten. Ich kann auch Software tracen, die nicht im Quellcode vorliegt (pfui!). -- ## einem Debugger Viele Tracing-Methoden und -Werkzeuge sind nicht sprachspezifisch und daher (nahezu) universell einsetzbar. Viele Werkzeuge bieten auch ohne Debugging-Symbole (o. ae.) einen echten Mehrwert. --- # Tracing - Varianten und Werkzeuge (1/2) ## prozessspezifisches Tracing Ich lege eine oder mehrere Prozesse mithilfe eines Tracing-Werkzeuges unters virtuelle Mikroskop. Meist dann nuetzlich, wenn die Ursache eines Problems ziemlich sicher in einer bestimmten PID(-Gruppe) verortet ist. -- ### relevante Technologien und Tools - ptrace(2), perf_event_open(2) - **strace(1)**, ltrace(1), truss(1, UNIX), ... --- class: center, middle # strace - der Klassiker im Schnelldurchlauf --- # strace - der Klassiker im Schnelldurchlauf ## nuetzliche Switches und Tricks: - `strace -p
...` — haengt sich an einen bereits laufenden Prozess **pid** - `strace -e [qualifier=]
...` — schraenkt Ausgabe auf Syscall bzw. Syscall-"Sets" ein - `strace -ff ...` — traced auch alle forkenden Kind- und Kindeskindprozesse - `strace -s
...` — zeigt bis zu **num** (statt nur 32) Bytes in Strings an - `strace -yy ...` — zeigt Metadaten zu Dateideskriptoren (fds) - `strace -c ...` — zeigt einfache Statistiken per syscall-Typ - `strace -t[tt] ...` — zeigt Zeitstempel-Informationen - `strace -o
...` — schreibt Tracing-Informationen in Datei(en) statt auf _stderr_ - `strace -k ...` — zeigt Callstacks (wenn man das braucht, wechselt man besser das Tool) -- ## Vorteile - kleines, schlankes Tool mit wenigen Abhaengigkeiten, schnell installiert und fast ueberall verfuegbar - **immens** nuetzlich, auch ohne viel Uebung gut benutzbar - eher "ungefaehrlich", _ptrace(2)_ ist lange erprobt -- ## Nachteile - ggf. starke Verlangsamung der beobachteten Prozesse - kann _nur_ syscalls tracen; kaum Einblick in applikationsseitigen user mode Code --- # Tracing - Varianten und Werkzeuge (2/2) ## systemweites Tracing Wenn die vermutete Ursache eines Problems nicht naheliegenderweise mit spezifischen Prozessen in Verbindung zu bringen ist, muss ich in die Breite gehen. Dafuer kann ich Datenquellen, die der (Linux-)Kernel bzw. auch Programme/Libraries zur Verfuegung stellen, anzapfen, und mich bis zur Ursache durchfiltern und -tracen. ### relevante Technologien und Tools - **kprobes**, **uprobes**, **tracepoints**, USDT probes, ... - **bpftrace(8)**, **perf(8)**, ftrace(Kernel docs), dtrace(1, UNIX), ... --- # "next generation"-Tracing — Datenquellen ## "Static" sources: Von den Entwicklern im Quellcode definierte Einstiegspunkte fuer Tracer, die ueber lange Zeit hinweg stabil bleiben (= ihre Semantik garantiert nicht aendern) sollten -- - Kernel: **tracepoints** - User-space: user-level statically defined tracing (**USDT**) **probes** -- ## "Dynamic" sources: Dynamische, durch das Tracing-Tool definierte pre- und post-Hooks in Kernel- oder Userspace-Funktionsaufrufe -- - Kernel: **kprobes** - User-space: **uprobes** --- # "next generation"-Tracing — Linux perf **perf** ist ein mit dem Kernel im selben Source-Tree gepflegtes Tracing-Tool, das viele Aufgaben erfuellt. Es ist inzwischen so vielseitig, dass es unueberschaubar wird. -- Einfach (be)greifbare und oft nuetzliche perf-Kommandos: - `perf top` - aehnlich top(1), aber auf Funktionsebene - `perf stat` - zum Erheben von Performance-Kennzahlen (z. B. IPC, branch prediction, CPU cache eff., div. event-counts, ...) - `perf record` - zum Mitschneiden von tracing-Daten zur spaeteren Analyse zum Betrachten bzw. Definieren von probes - `perf report` - zur Auswertung der Daten aus `perf record` -- `perf` entfaltet seine volle Wirkung meist erst beim Vorhandensein von **Debug-Symbolen** (idealerweise: nebst dem gesamten Quellcode) fuer Libraries und Programme. --- # strace kann nicht immer helfen Seit vielen Monden findet sich ein Cronjob auf einigen unserer aelteren PROD-Hosts - ein Cronjob mit einer etwas eigenartigen Geschichte... -- ```no-highlight ** * * * * if ! test x$(stat -c '\%a' /tmp/.) = x1777; then echo "/tmp/ permissions broke"; stat /tmp/.; chmod 1777 /tmp/.; fi ``` -- In variierenden Abstaenden - manchmal Tage, manchmal Wochen oder Monate - hat unser **/tmp/**-Directory ploetzlich seine besonderen Permissions gewechselt (von `1777` auf `0755`), mit drastischen Auswirkungen. Wir waren ratlos ob der Ursache, und alle (root-)User waehnten sich unschuldig. -- Wie koennte ich die Ursache dieses Problems heute zielgerichtet und mit relativ wenig Aufwand aufdecken? --- # "next generation"-Tracing — bpftrace > bpftrace is a high-level tracing language for Linux enhanced Berkeley Packet Filter (eBPF) available in recent Linux kernels (4.x). -- ## Vorteile: - programmierbares Tracing-Tool mit eigener DSL, "_maechtiger wird's nicht_" - syntaktisch an awk(1) (bzw. dtrace(1)) angelehnt - mit ein bisschen C zum Drueberstreuen, wenn notwendig - kompiliert mittels LLVM zu eBPF-Bytecode -- ## Nachteile: - (vglw.) ein Dependency-Schwergewicht - nur auf sehr frischen Distributionen verfuegbar (z. B. Debian 10) - in manchen Ecken noch nervig buggy --- # Wie sieht ein bpftrace-Programm aus? Ein trivialer (und nutzloser) Einzeiler auf der Shell: ```bash root@host:~ > bpftrace -e 'BEGIN { printf("Hello detectives!\n"); }' ``` -- Auch eigene Script-Executables sind moeglich: ```bpftrace #!/usr/bin/env bpftrace BEGIN { printf("Hello detectives!\n"); } ``` --- # Wie sieht ein bpftrace-Programm aus? Welche Prozesse oeffnen welche Dateien auf meinem System? ```bpftrace #!/usr/bin/env bpftrace BEGIN { printf("Hello detectives!\n"; } kprobe:do_sys_open { time("%H:%M:%S "); printf("%s: %s\n", comm, str(arg1)); } ``` --- # Wie sieht ein bpftrace-Programm aus? Welche Prozesse oeffnen welche Dateien auf meinem System? ```bpftrace #!/usr/bin/env bpftrace BEGIN { printf("Hello detectives!\n"; } kprobe:do_sys_open # Probe(s) { # Action block time("%H:%M:%S "); # Function, string printf("%s: %s\n", comm, str(arg1)); # Function, string constant, builtin var, function(builtin var) } ``` --- # Wie sieht ein bpftrace-Programm aus? Welche Prozesse, _die nicht root gehoeren_, oeffnen welche Dateien auf meinem System? ```bpftrace #!/usr/bin/env bpftrace BEGIN { printf("Hello detectives!\n"; } kprobe:do_sys_open # Probe(s) /uid > 0/ # Filter { # Action block time("%H:%M:%S "); # Function, string printf("%s: %s\n", comm, str(arg1)); # Function, string constant, builtin var, function(builtin var) } ``` --- class: center, middle # bpftrace - ein bisschen Praxis --- # bpftrace - Survival Kit Kernelseitige Datenquellen (und ggf. Argumente/Variablen) auflisten: ```bash bpftrace -lv
# z. B. 'tracepoint:ext4*trim*' perf probe --funcs
# z. B. '*tcp*err*' ``` ---- User-Level Symbole (fuer uprobes) auflisten: ```bash nm -D
# aus binutils perf probe --funcs -x
``` ---- -- - bpftrace Reference Guide: https://github.com/iovisor/bpftrace/blob/master/docs/reference_guide.md - Live-Demo-Scripts aus diesem Talk: https://johannes.truschnigg.info/slides/linuxwochen-2019_tracing.tar.gz --- class: center, middle # Danke fuer die Aufmerksamkeit!