Handbuch zur dynamischen Ablaufverfolgung in Solaris

Kapitel 15 Scripting

Das Dienstprogramm dtrace(1M) bietet Ihnen die Möglichkeit, Shell-Skripten ähnliche Interpreterdateien aus D-Programmen zu erstellen, die Sie installieren und als wieder verwendbare, interaktive DTrace-Tools nutzen können. Der D-Compiler und der Befehl dtrace stellen einen Satz Makrovariablen zur Verfügung, die durch den D-Compiler erweitert werden und das Schreiben von DTrace-Skripten erleichtern. Dieses Kapitel dient als Referenz für die Makrovariableneinrichtung und enthält Tipps zum Erstellen dauerhafter Skripten.

Interpreterdateien

Ähnlich wie die Shell und Dienstprogramme wie awk(1) und perl(1) können mit dtrace(1M) ausführbare Interpreterdateien erzeugt werden. Eine Interpreterdatei beginnt mit einer Zeile in der Form:

#! Pfadname Arg

wobei Pfadname der Pfad des Interpreters und Arg ein einzelnes, optionales Argument ist. Wenn eine Interpreterdatei ausgeführt wird, ruft das System den angegebenen Interpreter auf. Wenn Arg in der Interpreterdatei angegeben wurde, wird es dem Interpreter als Argument übergeben. Dann werden der Pfad zur Interpreterdatei selbst und etwaige bei der Ausführung zusätzlich angegebene Argumente an die Interpreter-Argumentliste angehängt. Deshalb müssen Sie DTrace-Interpreterdateien stets mit mindestens drei Argumenten erstellen:

#!/usr/sbin/dtrace -s

Wenn die Interpreterdatei ausgeführt wird, ist das Argument für die Option -s folglich der Pfadname der Interpreterdatei selbst. Anschließend wird die Datei von dtrace gelesen, kompiliert und ausgeführt, als hätten Sie den folgenden Befehl in die Shell eingegeben:


# dtrace -s Interpreter-Datei

Das folgende Beispiel zeigt, wie eine dtrace-Interpreterdatei erzeugt und ausgeführt wird. Schreiben Sie den folgenden D-Quellcode und speichern Sie ihn in einer Datei namens interp.d:

#!/usr/sbin/dtrace -s
BEGIN
{
	trace("hello");
	exit(0);
}

Kennzeichnen Sie die Datei interp.d als ausführbar und führen Sie sie wie folgt aus:


# chmod a+rx interp.d
# ./interp.d
dtrace: script './interp.d' matched 1 probe
CPU     ID                    FUNCTION:NAME
  1      1                           :BEGIN   hello
#

Denken Sie daran, dass die #!-Direktive die ersten zwei Zeichen der Datei ohne vorangestellte oder eingefügte Leerstellen enthalten muss. Der D-Compiler ignoriert diese Zeile bei der Verarbeitung der Interpreterdatei automatisch.

dtrace verarbeitet Befehlszeilenoptionen mit getopt(3C). Das bedeutet, dass in dem einzelnen Interpreterargument mehrere Optionen kombiniert werden können. Um beispielsweise die Option -q in das obige Beispiel einzufügen, ließe sich die Interpreterdirektive wie folgt abändern:

#!/usr/sbin/dtrace -qs

Bei der Angabe mehrerer Optionsbuchstaben muss die Option -s stets die Liste der booleschen Optionen abschließen, sodass das nächste Argument (der Name der Interpreterdatei) als Argument der Option -s verarbeitet wird.

Wenn Sie in der Interpreterdatei mehr als eine Option angeben müssen, die ein Argument benötigt, passen die Optionen und Argumente nicht in das einzelne Interpreter-Argument hinein. Legen Sie die Optionen in diesem Fall mit der Syntax der Direktive #pragma D option fest. Für alle dtrace-Befehlszeilenoptionen stehen Ihnen #pragma-Pendants zur Verfügung, die in Kapitel 16Optionen und Tunables aufgeführt sind.

Makrovariablen

Der D-Compiler definiert einen Satz integrierter Makrovariablen, auf die Sie beim Schreiben von D-Programmen oder Interpreterdateien zurückgreifen können. Makrovariablen sind IDs mit einem vorangestellten Dollarzeichen ($), die bei der Verarbeitung der Eingabedatei einmal vom D-Compiler ersetzt werden. Der D-Compiler bietet die folgenden Makrovariablen:

Tabelle 15–1 D-Makrovariablen

Name 

Beschreibung 

Referenz 

$[0-9]+

Makroargumente 

Lesen Sie dazu Makroargumente

$egid

Effektive Gruppen-ID 

getegid(2)

$euid

Effektive Benutzer-ID 

geteuid(2)

$gid

Tatsächliche Gruppen-ID 

getgid(2)

$pid

Prozess-ID 

getpid(2)

$pgid

Prozess-Gruppen-ID 

getpgid(2)

$ppid

ID des übergeordneten Prozesses 

getppid(2)

$projid

Projekt-ID 

getprojid(2)

$sid

Sitzungs-ID 

getsid(2)

$target

ID des Zielprozesses 

Lesen Sie dazu ID des Zielprozesses

$taskid

Vorgangs-ID 

gettaskid(2)

$uid

Tatsächliche Benutzer-ID 

getuid(2)

Außer den Makroargumenten $[0-9]+ und der Makrovariable $target werden alle Makrovariablen durch die ganzzahligen Werte der Systemattribute wie beispielsweise Prozess-ID oder Benutzer-ID ersetzt. Die Variablen werden durch den Attributwert ersetzt, der entweder zu dem aktuellen dtrace-Prozess selbst oder dem den D-Compiler ausführenden Prozess gehört.

Durch den Einsatz von Makrovariablen in Interpreterdateien haben Sie die Möglichkeit, dauerhafte D-Programme zu erstellen, die Sie nicht bei jeder Verwendung neu bearbeiten müssen. Wenn Sie beispielsweise alle Systemaufrufe außer den vom Befehl dtrace ausgeführten zählen möchten, können Sie die folgende D-Programmklausel mit $pid verwenden:

syscall:::entry
/pid != $pid/
{
	@calls = count();
}

Diese Klausel bringt immer das gewünschte Ergebnis, obwohl jeder Aufruf des Befehls dtrace eine andere Prozess-ID haben wird.

Makrovariablen können überall dort in einem D-Programm verwendet werden, wo Ganzzahlen, IDs oder Zeichenketten erlaubt sind. Sie werden nur einmal (d. h. nicht rekursiv) bei der Analyse der Eingabedatei ersetzt. Alle Makrovariablen werden durch separate Eingabesymbole ersetzt und können nicht mit zusätzlichem Text verkettet werden, um ein einzelnes Symbol zu bilden. Wenn beispielsweise $pid durch den Wert 456 ersetzt wird, dann wird der D-Code:

123$pid

nicht als das einzelne, ganzzahlige Symbol 123456, sondern als zwei nebeneinander stehende Symbole 123 und 456 gewertet und ergibt einen Syntaxfehler.

Makrovariablen werden ersetzt und mit angrenzendem Text innerhalb von D-Prüfpunktbeschreibungen am Anfang der Programmklauseln verkettet. In der folgenden Klausel wird beispielsweise mit dem DTrace-Provider pid der Befehl dtrace instrumentiert:

pid$pid:libc.so:printf:entry
{
	...
}

Makrovariablen werden nur einmal in jedem Prüfpunktbeschreibungsfeld ersetzt; sie dürfen keine Begrenzungszeichen für Prüfpunktbeschreibungen (:) enthalten.

Makroargumente

Der D-Compiler bietet auch einen Satz Makrovariablen für alle zusätzlichen als Teil des dtrace-Befehlsaufrufs angegebenen Argument-Operanden. Auf diese Makroargumente wird über die integrierten Namen zugegriffen: $0 für den Namen der D-Programmdatei oder des dtrace-Befehls, $1 für den ersten zusätzlichen Operanden, $2 für den zweiten Operanden und so weiter. Wenn Sie die dtrace-Option -s verwenden, wird $0 durch den Wert des Namens der mit dieser Option verwendeten Eingabedatei ersetzt. Bei D-Programmen, die in der Befehlszeile angegeben werden, nimmt $0 den Wert von argv[0] an, das zum Ausführen von dtrace selbst verwendet wurde.

Makroargumente können in Abhängigkeit von der Form des zugehörigen Texts durch Ganzzahlen, IDs oder Zeichenketten ersetzt werden. Wie alle Makrovariablen können auch Makroargumente über all dort in einem D-Programm verwendet werden, wo Symbole in Form von Ganzzahlen, IDs und Zeichenketten zulässig sind. Alle nachfolgenden Beispiele könnten gültige D-Ausdrücke bilden, geeignete Makroargumentwerte vorausgesetzt:

execname == $1    /* with a string macro argument */
x += $1           /* with an integer macro argument */
trace(x->$1)      /* with an identifier macro argument */

Makroargumente können zum Erstellen von dtrace-Interpreterdateien eingesetzt werden, die als regelrechte Solaris-Befehle fungieren und Informationen verwenden, die von einem Benutzer oder einem anderen Tool angegeben werden, um deren Verhalten zu modifizieren. So zeichnet beispielsweise die folgende D-Interpreterdatei die durch einen bestimmten Prozess (ID) ausgeführten write(2)-Systemaufrufe auf:

#!/usr/sbin/dtrace -s

syscall::write:entry
/pid == $1/
{
}

Wenn Sie diese Interpreterdatei als ausführbar kennzeichnen, können Sie der Interpreterdatei den Wert von $1 über ein zusätzliches Befehlszeilenargument mitteilen:


# chmod a+rx ./tracewrite
# ./tracewrite 12345

Der entstehende Befehlsaufruf zählt alle durch den Prozess mit der ID 12345 ausgeführten write(2)-Systemaufrufe.

Verweist Ihr D-Programm auf ein nicht in der Befehlszeile angegebenes Makroargument, wird eine entsprechende Fehlermeldung ausgegeben und die Programmkompilierung schlägt fehl:


# ./tracewrite
dtrace: failed to compile script ./tracewrite: line 4:
  macro argument $1 is not defined

Wurde die Option defaultargs gesetzt, ist die Referenzierung nicht angegebener Makroargumente durch das Programm möglich. Wenn defaultargs gesetzt ist, nehmen die nicht angegebenen Argumente den Wert 0 an. Weitere Informationen zu den Optionen des D-Compilers finden Sie in Kapitel 16Optionen und Tunables . Der D-Compiler gibt auch dann eine Fehlermeldung aus, wenn in der Befehlszeile zusätzliche Argumente angegeben sind, auf die das D-Programm nicht verweist.

Die Werte der Makroargumente müssen mit der Form einer Ganzzahl, ID oder Zeichenkette übereinstimmen. Stimmt das Argument mit keiner dieser Formen überein, meldet der D-Compiler einen entsprechenden Fehler. Wenn Sie einer DTrace-Interpreterdatei ein Zeichenketten-Makroargument übergeben, schließen Sie das Argument in ein zusätzliches Paar einfacher Anführungszeichen ein, damit die Shell nicht den Inhalt der doppelten Anführungszeichen und der Zeichenkette interpretiert:


# ./foo '"a string argument"'

Wenn die D-Makroargumente als Zeichenketten-Symbole interpretiert werden sollen, obwohl sie mit der Form einer Ganzzahl oder ID übereinstimmen, stellen Sie dem Namen der Makrovariable oder des Arguments zwei Dollarzeichen voran (z. B. $$1). Dadurch wird der D-Compiler gezwungen, die Argumentwerte wie eine in doppelten Anführungszeichen eingeschlossene Zeichenkette zu interpretieren. Alle in D üblichen Ersatzdarstellungen für Zeichenketten (siehe Tabelle 2–5) werden innerhalb von etwaigen Zeichenketten-Makroargumenten aufgelöst. Dabei spielt es keine Rolle, ob sie in der Makroform $Arg oder $$Arg referenziert werden. Wenn die Option defaultargs gesetzt ist, nehmen nicht angegebene Argumente, auf die in der Form $$Arg verwiesen wird, den Wert der leeren Zeichenkette ("") an.

ID des Zielprozesses

Die Makrovariable $target dient zum Erstellen von Skripten, die sich gezielt auf einen Benutzerprozess von Interesse anwenden lassen, der entweder in der dtrace-Befehlszeile mit der Option -p ausgewählt oder mit der Option -c erzeugt wurde. In der Befehlszeile oder mit der Option -s angegebene D-Programme werden kompiliert, nachdem Prozesse erzeugt oder erfasst (grab) werden, und die Variable $target wird durch die ganzzahlige Prozess-ID des ersten dieser Prozesse ersetzt. Mit dem folgenden D-Skript ließe sich beispielsweise die Verteilung der von einem bestimmten Prozess ausgeführten Systemaufrufe ermitteln:

syscall:::entry
/pid == $target/
{
	@[probefunc] = count();
}

Um die Anzahl der vom Befehl date(1) ausgeführten Systemaufrufe zu ermitteln, speichern Sie das Skript in der Datei syscall.d und führen folgenden Befehl aus:


# dtrace -s syscall.d -c date
dtrace: script 'syscall.d' matched 227 probes
Fri Jul 30 13:46:06 PDT 2004
dtrace: pid 109058 has exited

  gtime                                                             1
  getpid                                                            1
  getrlimit                                                         1
  rexit                                                             1
  ioctl                                                             1
  resolvepath                                                       1
  read                                                              1
  stat                                                              1
  write                                                             1
  munmap                                                            1
  close                                                             2
  fstat64                                                           2
  setcontext                                                        2
  mmap                                                              2
  open                                                              2
  brk                                                               4