File: bootchartd.in

package info (click to toggle)
bootchart2 0.14.4-3
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd, sid, stretch, wheezy
  • size: 5,036 kB
  • sloc: ansic: 1,805; python: 1,764; sh: 155; makefile: 88
file content (212 lines) | stat: -rwxr-xr-x 5,425 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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#!/bin/bash
#
# Bootchart logger script
# Ziga Mahkovec  <ziga.mahkovec@klika.si>
# Michael Meeks  <michael.meeks@novell.com>
#
# This script is used for data collection for the bootchart2
# boot performance visualization tool.
#
# To profile the boot process, bootchartd should be called instead of
# /sbin/init.  Modify the kernel command line to include:
#
# init=/sbin/bootchartd initcall_debug printk.time=y quiet
#
# bootchartd will then start itself in background and exec /sbin/init
# (or an alternative init process if specified using bootchart_init=)
#
# To profile a running system, run:
# $ /sbin/bootchartd start; sleep 30; /sbin/bootchartd stop
#

# Use a directory we know will be there, such that we can mount
# our 'proc' without having to touch a (potentially) read-only
# file-system.
LIBDIR="@LIBDIR@"
TMPFS="${LIBDIR}/bootchart/tmpfs"
COLLECTOR_BIN="${LIBDIR}/bootchart/bootchart-collector"

# some initrds don't have usleep etc.
USLEEP="$COLLECTOR_BIN --usleep"

# we need to find our tools
PATH="/sbin:/bin:/usr/sbin:/usr/bin:$PATH"

# Defaults, in case we can't find our configuration
SAMPLE_HZ=50
BUILDLOG_DEST=/var/log/bootchart.tgz
AUTO_RENDER="no"
AUTO_RENDER_DIR="/var/log"
AUTO_RENDER_FORMAT="png"

# The processes we have to wait for
EXIT_PROC="kdm_greet xterm konsole gnome-terminal metacity mutter gnome-shell compiz ldm icewm-session enlightenment xfwm4 openbox"

# Read configuration.
CONF="/etc/bootchartd.conf"
if [ -f $PWD/bootchartd.conf ]; then
	. $PWD/bootchartd.conf
elif [ -f $CONF ]; then
	. $CONF
else
	echo "$CONF missing"
fi

# Start the boot logger.
start()
{
	# If in init start ourselves in our familiar system
	if [ -n "$INIT_PROCESS" ]; then
#		echo "bootchartd started in init" >> kmsg
		$COLLECTOR_BIN $SAMPLE_HZ

	# Otherwise, manually launched to profile something
	else
		# bail out, if already running
		pidof bootchart-collector && exit 0
#		echo "bootchartd started manually" >> kmsg
		$COLLECTOR_BIN -r $SAMPLE_HZ &

		if [ "$#" -gt 0 ]; then
			# If a command was passed, run it
			# (used for profiling specific applications)
			echo "profile.process = $( basename $1 )" >> header
			$@
			stop
		else
			echo "no command passed, you need to manually stop the service sometime"
		fi
	fi
}

# Wait for the boot process to end.
wait_boot()
{
	# Wait for /proc first - without it we have issues
	while [ ! -e /proc/cmdline ]; do
		$USLEEP 5000
	done

	while true; do
		if [ -n "$EXIT_PROC" -a -n "$( pidof $EXIT_PROC )" ]; then
			# give an unambiguous settle afterwards - so we get
			# more post-login data for slow systems
			$USLEEP 20000000

			# Write / flush the log files
			stop
			return
		fi
		$USLEEP 1000000
	done;
}

# Extract the log data from the running bootchart collector
# process (via ptrace) - fun. Store logs into $BOOTLOG_DEST.
stop()
{
	tmpdir=`mktemp -d /tmp/bootchart.XXXXXXXXXX`
	if [ "z$tmpdir" = "z" ]; then
		echo "Failed to generate directory for logging"
		exit 1
	fi

	if ! $COLLECTOR_BIN --dump $tmpdir; then
		echo "Can't extract boot chart from collector"
		exit 1
	fi

	cd $tmpdir
	if [ ! -e proc_stat.log ]; then
		echo "Can't find bootchart output in $tmpdir - aborting"
		exit 1
	fi

	# Archive it all up into the bootchart output
	# expect dmesg log only if bootchartd was started as an init process
	if [ -n "$INIT_PROCESS" ] ; then
		tar -zcf "$BOOTLOG_DEST" header dmesg *.log
	else
		tar -zcf "$BOOTLOG_DEST" header *.log
	fi

	rm -Rf $tmpdir

	# Render the chart if configured (and the renderer is installed)
	if [ "$AUTO_RENDER" = "yes" -a -x /usr/bin/pybootchartgui ]; then
		cd $AUTO_RENDER_DIR
		/usr/bin/pybootchartgui -o "$AUTO_RENDER_DIR"/bootchart.$AUTO_RENDER_FORMAT -f $AUTO_RENDER_FORMAT "$BOOTLOG_DEST"
	fi

	# execute custom post-collect (and possibly post-render) command (which could get params from the conf file by itself if needed)
	if [ -x "$CUSTOM_POST_CMD" ]; then
		"$CUSTOM_POST_CMD"
	fi
}

if [ $$ -eq 1 ]; then
	# Either started by the kernel - in which case, we start the
	# logger in background and exec init [ re-using this pid (1) ]
	# Or - started after the initrd has completed, in which case
	# we try to do nothing much.
	INIT_PROCESS="yes"
	echo "Starting bootchart logging"

	init="/sbin/init"

	# Are we running in the initrd ?
	if [ -x /init -o -x /linuxrc ]; then
		IN_INITRD="yes"
		[ -x /linuxrc ] && init="/linuxrc"
		[ -x /init ] && init="/init"
		start &
	else # running inside the main system
		echo "bootchart: no initrd used; starting"
		start &
		wait_boot &
		# wait a little, until the collector is going, before allowing
		# the rest of the system to charge ahead, so we catch it
		$USLEEP 250000
		echo "bootchart continuing boot" >> $TMPFS/kmsg
	fi

	# Optionally, an alternative init(1) process may be specified using
	# the kernel command line (e.g. "bootchart_init=/sbin/initng")
	[ -n "$bootchart_init" ] && init="$bootchart_init"
	for i in $@; do
		if [ "${i%%=*}" = "bootchart_init" ]; then
			init="${i#*=}"
			break
		fi
		if [ "${i%%=*}" = "init" ]; then
			_init=${i#*=}
			if test "$_init" != "/sbin/bootchartd"; then
				init="$_init"
				break
			fi
		fi
	done
	export PATH=$OLDPATH

	# switch to - either the initrd's init, or the main system's
	exec $init $*
fi

case "$1" in
	"start")
		# Started by the user
		shift
		start $@
		;;
	"wait")
		# Wait for boot
		wait_boot
		;;
	"stop")
		stop
		;;
	*)
		echo "Usage: $0 {wait|start|stop}"
		;;
esac