File: activity1.d

package info (click to toggle)
dtrace 2.0.5-1
  • links: PTS
  • area: main
  • in suites: sid
  • size: 24,408 kB
  • sloc: ansic: 61,247; sh: 17,997; asm: 1,717; lex: 947; awk: 754; yacc: 695; perl: 37; sed: 17; makefile: 15
file content (144 lines) | stat: -rwxr-xr-x 4,239 bytes parent folder | download
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;
}