1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
/*
* Oracle Linux DTrace.
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
/*
* NAME
* activity1.d - report on process create, exec and exit
*
* SYNOPSIS
* sudo dtrace -s activity1.d '"bash"'
*
* DESCRIPTION
* Show the processes that are created, executed and exited
* in the bash shell while the script is running.
*
* NOTES
* - This script uses the proc provider to trace the following process
* activities: create, exec, and exit.
*
* - A predicate is used to ensure that only those processes executed
* by bash are traced. While this could be hard coded, here the name
* is passed in as an argument.
*
* - This script is guaranteed to produce results if you start one or
* more bash commands while the script is running. There are two ways
* to do this:
* o Execute this script in the background, and type in the command(s).
* o Alternatively, run the script in the foreground and type the
* command(s) in a separate terminal window on the same system.
*
* - The script needs to be terminated with ctrl-C. In case the
* script is running in the background, get it to run in the
* foreground first by using the fg command and then use ctrl-C
* to terminate the process. Otherwise, typing in ctrl-C will do.
*
* - Associative arrays are used to store the information from the
* proc provider.
*
* - There is on important subtlety to pay attention to. Since
* bash (and other shells) optimize for performance, it may happen
* that proc:::create does not fire, because there is no call to
* fork(), clone(), etc. This is why two different probes for
* proc:::exec are defined.
*
* - The DTrace User Guide documents the proc provider probe
* arguments like args[0] and also structures like psinfo_t. It is
* strongly recommended to check the documentation for this info.
*/
/*
* Fires when a process (or process thread) is created using fork() or
* vfork(), which both invoke clone(). The psinfo_t corresponding to
* the new child process is pointed to by args[0].
*
* Use a predicate to only execute the clause if the condition is met.
* In this case that means that only processes executed in the bash
* shell are traced.
*/
proc:::create
/ execname == $1 /
{
/*
* Store the PID of both the parent and child process from the psinfo_t
* structure pointed to by args[0]. Use 3 associative arrays to store the
* various items of interest.
*/
this->childpid = args[0]->pr_pid;
this->parentpid = args[0]->pr_ppid;
/*
* Store the parent PID of the new child process.
*/
p_pid[this->childpid] = this->parentpid;
/*
* Parent command name.
*/
p_name[this->childpid] = execname;
/*
* Child has not yet been exec'ed.
*/
p_exec[this->childpid] = "";
}
/*
* The process starts. In case proc:::create has fired, store the
* absolute time and the full name of the child process.
*/
proc:::exec
/ execname == $1 && p_pid[pid] != 0 /
{
time[pid] = timestamp;
p_exec[pid] = args[0];
}
/*
* The process starts, but in this case, proc:::create has not fired.
* In addition to storing the name of the child process, store the
* various other items of interest.
*/
proc:::exec
/ execname == $1 && p_pid[pid] == 0 /
{
time[pid] = timestamp;
p_exec[pid] = args[0];
p_pid[pid] = ppid;
p_name[pid] = execname;
}
/*
* The process exits. Print the information.
*/
proc:::exit
/p_pid[pid] != 0 && p_exec[pid] != ""/
{
printf("%-16s (%d) executed %s (%d) for %d microseconds\n",
p_name[pid], p_pid[pid], p_exec[pid], pid, (timestamp - time[pid])/1000);
}
/*
* The process has forked itself and exits. Print the information.
*/
proc:::exit
/p_pid[pid] != 0 && p_exec[pid] == ""/
{
printf("%-16s (%d) forked itself (as %d) for %d microseconds\n",
p_name[pid], p_pid[pid], pid, (timestamp - time[pid])/1000);
}
/*
* Assign 0s to free memory associated with this pid.
*/
proc:::exit
/p_pid[pid] != 0/
{
time[pid] = 0;
p_exec[pid] = NULL;
p_pid[pid] = 0;
p_name[pid] = NULL;
}
|