sh Provider

Skip to end of metadata
Go to start of metadata

sh Provider

The sh provider makes available probes that can be used to observe the behavior of bourne shell scripts.

This provider is in development and is not currently available

Top

Probes

Probe Description
builtin-entry Fires on entry to a shell builtin command.
builtin-return Fires on return from a shell builtin command.
command-entry Fires when the shell execs an external command.
command-return Fires on return from an external command.
function-entry Fires on entry into a shell function.
function-return Fires on return from a shell function.
line Fires before commands on a particular line of code are executed.
subshell-entry Fires when the shell forks a subshell.
subshell-return Fires on return from a forked subshell.
script-start Fires before any commands in a script are executed.
script-done Fires on script exit.
variable-set Fires on assignment to a variable.
variable-unset Fires when a variable is unset.

Note that the use of non-empty module or function names in a sh* probe is undefined at this time.

Top

sh Probe Arguments
Probe args[0] args[1] args[2] args[3] args[4]
builtin-entry,command-entry,function-entry char * char * int int char **
builtin-return,command-return,function-return char * char * int    
subshell-entry char * pid_t      
subshell-return char * int      
line char * int      
script-start char *        
script-done char * int      
variable-set char * char * char *    
variable-unset char * char *      

Top

sh Probe Arguments - more detail
builtin-entry,command-entry,function-entry
char * args[0] Script Name
char * args[1] Builtin/Command/Function Name
int args[2] Line Number
int args[3] # Arguments
char ** args[4] Pointer to argument list
builtin-return,command-return,function-return
char * args[0] Script Name
char * args[1] Builtin/Command/Function Name
int args[2] Return Value
subshell-entry
char * args[0] Script Name
pid_t args[1] Forked Process ID
subshell-return
char * args[0] Script Name
int {{args[1] Return Value
line
char * args[0] Script Name
int args[1] Line Number
script-start
char * args[0] Script Name
script-done
char * args[0] Script Name
int args[1] Exit Value
variable-set
char * args[0] Script Name
char * args[1] Variable Name
char * args[2] Value
variable-unset
char * args[0] Script Name
char * args[1] Variable Name

Top

Examples

Some simple examples of sh provider usage follow.

Catching a variable assignment

Say we want to determine which line in the following script has an assignment to WatchedVar:

#!/bin/sh

# starting script
WatchedVar=Value
unset WatchedVar
# ending script

We could use the following script

#!/usr/sbin/dtrace -s

#pragma D option quiet

sh$target:::line { self->line = arg1; }
sh$target:::variable-set /copyinstr(arg1) == "WatchedVar"/ {
        printf("%d: %s=%s\n", self->line, copyinstr(arg1),
	    copyinstr(arg2)); }
sh$target:::variable-unset /copyinstr(arg1) == "WatchedVar"/ {
        printf("%d: unset %s\n", self->line, copyinstr(arg1)); }
$ ./watch.d -c ./var.sh
4: WatchedVar=Value
5: unset WatchedVar

Top

Watching the time spent in functions
#!/usr/sbin/dtrace -s

#pragma D option quiet

sh$target:::function-entry { self->start = vtimestamp }
sh$target:::function-return {
	@[copyinstr(arg1)] = quantize(vtimestamp - self->start)
}

Similar for the other entry/return probes, with the exception of subshell as the probe name is unavailable.

Wasted time using external functions instead of builtins

This script is copied from the DTrace toolkit. It's function and how it works should be relatively self explanatory.

#!/usr/sbin/dtrace -Zs
/*
 * sh_wasted.d - measure Bourne shell elapsed times for "wasted" commands.
 *               Written for the sh DTrace provider.
 *
 * $Id: sh_wasted.d 25 2007-09-12 09:51:58Z brendan $
 *
 * USAGE: sh_wasted.d { -p PID | -c cmd }       # hit Ctrl-C to end
 *
 * This script measures "wasted" commands - those which are called externally
 * but are in fact builtins to the shell. Ever seen a script which calls
 * /usr/bin/echo needlessly? This script measures that cost.
 *
 * FIELDS:
 *              FILE            Filename of the shell or shellscript
 *              NAME            Name of call
 *              TIME            Total elapsed time for calls (us)
 *
 * IDEA: Mike Shapiro
 *
 * Filename and call names are printed if available.
 *
 * COPYRIGHT: Copyright (c) 2007 Brendan Gregg.
 *
 * CDDL HEADER START
 *
 *  The contents of this file are subject to the terms of the
 *  Common Development and Distribution License, Version 1.0 only
 *  (the "License").  You may not use this file except in compliance
 *  with the License.
 *
 *  You can obtain a copy of the license at Docs/cddl1.txt
 *  or http://www.opensolaris.org/os/licensing.
 *  See the License for the specific language governing permissions
 *  and limitations under the License.
 *
 * CDDL HEADER END
 *
 * 09-Sep-2007  Brendan Gregg   Created this.
 */

#pragma D option quiet

dtrace:::BEGIN
{
        isbuiltin["echo"] = 1;
        isbuiltin["test"] = 1;
        /* add builtins here */

        printf("Tracing... Hit Ctrl-C to end.\n");
        self->start = timestamp;
}

sh$target:::command-entry
{
        self->command = timestamp;
}

sh$target:::command-return
{
        this->elapsed = timestamp - self->command;
        this->path = copyinstr(arg1);
        this->cmd = basename(this->path);
}

sh$target:::command-return
/self->command && !isbuiltin[this->cmd]/
{
        @types_cmd[basename(copyinstr(arg0)), this->path] = sum(this->elapsed);
        self->command = 0;
}

sh$target:::command-return
/self->command/
{
        @types_wasted[basename(copyinstr(arg0)), this->path] =
            sum(this->elapsed);
        self->command = 0;
}

proc:::exit
/pid == $target/
{
        exit(0);
}

dtrace:::END
{
        this->elapsed = (timestamp - self->start) / 1000;
        printf("Script duration: %d us\n", this->elapsed);

        normalize(@types_cmd, 1000);
        printf("\nExternal command elapsed times,\n");
        printf("   %-30s %-22s %8s\n", "FILE", "NAME", "TIME(us)");
        printa("   %-30s %-22s %@8d\n", @types_cmd);

        normalize(@types_wasted, 1000);
        printf("\nWasted command elapsed times,\n");
        printf("   %-30s %-22s %8s\n", "FILE", "NAME", "TIME(us)");
        printa("   %-30s %-22s %@8d\n", @types_wasted);
}

Given the following silly little script (bad.sh), we can look at the amount of time spent executing external commands and split out the time that has been spent on commands we've defined that could have been builtins.

#!/bin/sh

for i in 0 1 2 3 4 5 6 7 8 9
do      for j in 0 1 2 3 4 5 6 7 8 9
        do      /bin/echo "$i$j \c"
                /bin/date
        done
done 
$ ./sh_wasted.d -c ./bad.sh
Tracing... Hit Ctrl-C to end.
00 Wed Jan  9 10:53:02 EST 2008
01 Wed Jan  9 10:53:03 EST 2008
02 Wed Jan  9 10:53:03 EST 2008
...
98 Wed Jan  9 10:53:20 EST 2008
99 Wed Jan  9 10:53:20 EST 2008
Script duration: 17998139 us

External command elapsed times,
   FILE                           NAME                   TIME(us)
   bad.sh                         /bin/date               1067426

Wasted command elapsed times,
   FILE                           NAME                   TIME(us)
   bad.sh                         /bin/echo               1040886

Top

Stability

The sh provider uses DTrace's stability mechanism to describe its stabilities, as shown in the following table. For more information about the stability mechanism, see Chapter 39, Stability.

Element Name stability Data stability Dependency class
Provider Unstable Unstable Common
Module Private Private Unknown
Function Private Private Unknown
Name Unstable Unstable Common
Arguments Unstable Unstable Common
Labels:
None
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.

Sign up or Log in to add a comment or watch this page.


The individuals who post here are part of the extended Oracle community and they might not be employed or in any way formally affiliated with Oracle. The opinions expressed here are their own, are not necessarily reviewed in advance by anyone but the individual authors, and neither Oracle nor any other party necessarily agrees with them.