Guía de seguimiento dinámico de Solaris

Capítulo 15 Secuencias de comandos

Puede usar la utilidad dtrace(1M) para crear archivos de intérpretea partir de programas D similares a las secuencias de comandos de shell que puede instalar como herramientas DTrace interactivas reutilizables. El compilador D y el comando dtrace ofrecen un conjunto de variables de macro ampliadas por el compilador D que facilitan la tarea de creación de secuencias de comando DTrace. Este capítulo se presenta como una referencia para la función de variables de macro, y ofrece sugerencias para la creación de secuencias de comandos persistentes.

Archivos de intérprete

Similares a la shell y a utilidades como awk(1) y perl(1), dtrace(1M) pueden utilizarse para crear archivos de intérprete ejecutables. Los archivos de intérprete comienzan con una línea con el formato siguiente:

#! pathname arg

donde pathname es la ruta de acceso del intérprete y arg es un único argumento opcional. Al ejecutar un archivo intérprete, el sistema invoca al intérprete especificado. Si se especificó arg en el archivo intérprete, se transfiere como argumento al intérprete. La ruta hasta el archivo intérprete en sí mismo y cualquier argumento adicional especificado a la hora de ejecutarlo se agregará a la lista de argumentos del intérprete. Por lo tanto, será siempre necesario crear archivos intérprete DTrace con al menos tres argumentos:

#!/usr/sbin/dtrace -s

Al ejecutar el archivo intérprete, el argumento de la opción - s será por lo tanto la ruta de acceso del archivo intérprete en sí mismo. Posteriormente, dtrace leerá, compilará y ejecutará este archivo como si hubiera escrito el siguiente comando en la shell:


# dtrace -s interpreter-file

El siguiente ejemplo muestra cómo crear y ejecutar un archivo intérprete dtrace. Escriba el siguiente código fuente en D y guárdelo en un archivo llamado interp.d:

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

Marque el archivo interp.d como ejecutable y ejecútelo de la forma siguiente:


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

Recuerde que la directiva #! debe abarcar los primeros dos caracteres del archivo, sin espacios en blanco ni en medio ni precediendo. El compilador D sabe cómo ignorar automáticamente esta línea al procesar el archivo intérprete.

dtrace usa getopt(3C) para procesar opciones de línea de comandos, de forma que puede combinar varias opciones en un único argumento de intérprete. Por ejemplo, para agregar la opción -q al ejemplo anterior podría cambiar la directiva de intérprete a:

#!/usr/sbin/dtrace -qs

Si especifica varias letras de opción, la opción -s debe finalizar siempre la lista de opciones booleanas, de forma que el siguiente argumento (el nombre de archivo intérprete) se procesa como el argumento que corresponde a la opción -s.

Si es necesario especificar más de una opción que requiere un argumento en su archivo intérprete, no podrá incluir todas las opciones y argumentos en un único argumento intérprete. Utilice en su lugar la sintaxis de directiva #pragma D option para establecer las opciones. Todas las opciones de línea de comandos de dtrace tienen equivalentes #pragma que puede utilizar, tal y como se indica en el Capítulo 16Opciones y optimizables.

Variables macro

El compilador D define un conjunto de variables de macro incorporadas que puede utilizar a la hora de escribir programas D o archivos intérprete. Las variables macro son identificadores que tienen como prefijo un signo de dólar ($) y que se amplían una vez por el compilador D al procesar el archivo de entrada. El compilador D proporciona las siguientes variables macro:

Tabla 15–1 Variables macro D

Nombre 

Descripción 

Referencia 

$[0-9]+

argumentos macro 

Consulte Argumentos de macro

$egid

Id. de grupo efectivo 

getegid(2)

$euid

Id. de usuario efectivo 

geteuid(2)

$gid

Id. de grupo real 

getgid(2)

$pid

Id. de proceso 

getpid(2)

$pgid

Id. de grupo de procesos 

getpgid(2)

$ppid

Id. de proceso principal 

getppid(2)

$projid

Id. de proyecto 

getprojid(2)

$sid

Id. de sesión 

getsid(2)

$target

Id. de proceso de destino 

Consulte Id. de proceso de destino

$taskid

Id. de tarea 

gettaskid(2)

$uid

Id. de usuario real 

getuid(2)

A excepción de los argumentos de macro $[0-9]+ y la variable de macro $target, las variables de macro se expanden a enteros, que corresponden a atributos del sistema como son el Id. de proceso y el Id. de usuario. La variable se expande al valor de atributo asociado con el proceso dtrace actual en sí mismo, o al proceso en el que se está ejecutando el compilador D.

La utilización de variables macro en archivos intérprete le permite crear programas D persistentes que no necesitan editarse cada vez que desee utilizarlos. Por ejemplo, para contar todas las llamadas de sistema a excepción de las ejecutadas por el comando dtrace, puede utilizar la siguiente cláusula de programa D que contiene $pid:

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

Esta cláusula produce siempre el resultado deseado, incluso a pesar de que cada invocación del comando dtrace tendrá un Id. de proceso diferente.

Las variables macro pueden usarse en cualquier lugar en el que pueda utilizarse un entero, un identificador o una cadena en un programa D. Las variables macro se amplían sólo una vez (es decir, no se amplían de forma recursiva) al analizar el archivo de entrada. Cada variable macro se amplía para formar un símbolo de entrada independiente, y no pueden concatenarse con otro texto para producir un único símbolo. Por ejemplo, si $pid se amplía hasta el valor 456, el código D:

123$pid

se ampliaría a los dos símbolos adyacentes 123 y 456, lo que provocaría un error de sintaxis, en lugar del símbolo entero 123456.

Las variables macro se amplían y concatenan con texto adyacente en el interior de descripciones de sondeo D al principio de las cláusulas de programa. Por ejemplo, la siguiente cláusula utiliza al proveedor DTrace pid para instrumentar el comando dtrace:

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

Las variables macro sólo se amplían una vez dentro de cada campo de descripción de sondeo. Es posible que no contengan delimitadores de descripción de sondeo (:).

Argumentos de macro

El compilador D proporciona también un conjunto de variables macro correspondientes a cualquier operando de argumento adicional especificado como parte de la invocación del comando dtrace. A estos argumentos macro se accede mediante los nombres $0 incorporados para el nombre del archivo del programa D o el comando dtrace , $1 para el primer operando adicional, $2 para el segundo operando, y así, sucesivamente. Si utiliza la opción dtrace -s, $0 se amplía hasta el valor del nombre del archivo de entrada utilizado con esta opción. Para los programas D especificados en la línea de comandos, $0 se amplía hasta el valor de argv[0] utilizado para ejecutar dtrace.

Los argumentos macro pueden ampliarse a enteros, identificadores o cadenas, en función del formato del texto correspondiente. Al igual que ocurre con todas las variables macro, los argumentos macro pueden utilizarse en cualquier lugar en el que puedan utilizarse enteros, identificadores y símbolos de cadena en un programa D. Todos los ejemplos siguientes podrían componer expresiones D válidas si asumen los valores de argumento macro adecuados:

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

Los argumentos macro pueden utilizarse para crear archivos de intérprete de dtrace que actúen como auténticos comandos de Solaris y que utilicen la información especificada por un usuario, o por otra herramienta, para modificar su conducta. Por ejemplo, el siguiente archivo intérprete D realiza un seguimiento de las llamadas de sistema write(2) ejecutadas por un Id. de proceso determinado:

#!/usr/sbin/dtrace -s

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

Si convierte este archivo en ejecutable puede especificar el valor de $1 utilizando un argumento de línea de comandos adicional para su archivo intérprete:


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

La invocación de comando resultante cuenta las llamadas de sistema write(2) ejecutadas por el proceso con ID 12345.

Si su programa D hace referencia a un argumento macro no proporcionado en la línea de comandos, se imprimirá el mensaje de error pertinente y no se realizará correctamente la compilación del programa:


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

Los programas D pueden hacer referencia a argumentos macro no especificados si se establece la opción defaultargs. Si se establece la opción defaultargs, los argumentos no especificados tendrán el valor 0. Consulte el Capítulo 16Opciones y optimizables, para obtener más información sobre las opciones de compilador D. El compilador de D devolverá también un mensaje de error si se especifican argumentos adicionales en la línea de comandos a los que no haga referencia su programa D.

Los valores de los argumentos macro deben tener formato de entero, identificador o cadena. Si el argumento no coincide con ninguno de estos formatos, el compilador D devolverá el mensaje de error pertinente. Al especificar argumentos macro de cadena en un archivo de intérprete DTrace, sitúe el argumento entre un par adicional de comillas simples para evitar que la shell interprete las dobles comillas y el contenido de la cadena:


# ./foo '"a string argument"'

Si desea que se interpreten sus argumentos de macro de D como símbolos de cadena, incluso si el formato es el de un entero o identificador, coloque dos signos de dólar delante de la variable macro o el nombre del argumento (por ejemplo, $$1) para forzar que el compilador de D interprete el valor del argumento como si fuera una cadena rodeada de comillas dobles. Todas las secuencias de escape de cadena D habituales (consulte la Tabla 2–5) se amplían en el interior de cualquier argumento macro de cadena, con independencia de si se hace referencia a ellos con el formato de la macro $arg o $$arg. Si está definida la opción defaultargs, los argumentos no especificados a los que se haga referencia con el formato $$arg tendrán el valor de una cadena vacía ("").

Id. de proceso de destino

Utilice la variable macro $target para crear secuencias de comandos que puedan aplicarse a un proceso de usuario determinado de interés que está seleccionado en la línea de comandos dtrace utilizando la opción -p o que se ha creado mediante la opción -c. Los programas D especificados en la línea de comandos o mediante la opción -s se compilarán después de crear o capturar procesos y la variable $target se amplía hasta el Id. de proceso entero del primer proceso en cuestión. Por ejemplo, la siguiente secuencia de comandos D podría utilizarse para determinar la distribución de llamadas de sistema ejecutadas por el proceso de un sujeto determinado:

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

Para determinar el número de llamadas de sistema ejecutadas por el comando date(1), guarde la secuencia de comandos en el archivo syscall.d y ejecute el comando siguiente:


# 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