bootchartd 4.46 KB
Newer Older
Timo Teräs's avatar
Timo Teräs committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#!/bin/sh
#
# Bootchart logger script
# Ziga Mahkovec  <ziga.mahkovec@klika.si>
#
# Modified heavily for Alpine Linux bootcharting
# Timo Teras <timo.teras@iki.fi>
#
# This script is used for data collection for the bootchart
# boot performance visualization tool (http://www.bootchart.org).
#
# This script is tied to Alpine Init scripts and charts the
# bootup procedure only.
#

PATH="/sbin:/bin:/usr/sbin:/usr/bin:$PATH"

# Configuration for bootchartd, the bootchart logger script.
TMPFS_SIZE=32m
20 21
SAMPLE_PERIOD=0.2
PROCESS_ACCOUNTING="yes"
Timo Teräs's avatar
Timo Teräs committed
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
BOOTLOG_DEST=/var/log/bootchart.tgz
LOGDIR=/bootchart
EXIT_PROC="mingetty agetty rungetty getty fgetty"

# Monitoring commands
log_cmd_1="cat /proc/stat"
log_target_1=proc_stat.log

# /proc/diskstats is available in 2.6 kernels
log_cmd_2="cat /proc/diskstats"
log_target_2=proc_diskstats.log

log_cmd_3="cat /proc/[1-9]*/stat 2>/dev/null"
log_target_3=proc_ps.log

# Uncomment this line for diskless stations
#log_cmd_4="cat /proc/net/dev"
#log_target_4=proc_netdev.log

max_log=3

do_logging()
{
	# Enable process accounting if configured
	if [ "$PROCESS_ACCOUNTING" = "yes" ]; then
		[ -e kernel_pacct ] || : > kernel_pacct
		accton kernel_pacct
	fi

	# open file descriptors
	i=1
	while [ $i -le $max_log ]; do
		eval target=\"\$log_target_$i\"
		if [ -z "$target" ]; then
			max_log=$i
			break
		fi

		fd=$((2 + $i))
		eval exec $fd'>>$target'
		eval log_fd_$i=$fd
		i=$(($i + 1))
	done

	not_stop_logging=true
	while $not_stop_logging && \
	{ ! pidof $EXIT_PROC >/dev/null; }; do
		if [ -r /proc/uptime ]; then
			# Write the time (in jiffies).
			read uptime < /proc/uptime
			uptime=${uptime%% [0-9]*}
			uptime=${uptime%.*}${uptime#*.}

			i=1
			while [ $i -le $max_log ]; do
				eval fd=\$log_fd_$i\; cmd=\$log_cmd_$i

				{
					echo $uptime
					# Log the command output
					eval $cmd
					echo
				} >&$fd
				i=$(($i + 1))
			done
		fi

		sleep $SAMPLE_PERIOD
	done

	# close file descriptors
	i=1
	while [ $i -le $max_log ]; do
		eval fd=\$log_fd_$i
		eval exec $fd'>&-'
		i=$(($i + 1))
	done

100
	[ -e kernel_pacct ] && accton
Timo Teräs's avatar
Timo Teräs committed
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
}

# Stop the boot logger.  The lock file is removed to force the loggers in
# background to exit.  Some final log files are created and then all log files
# from the tmpfs are packaged and stored in $BOOTLOG_DEST.
finalize()
{
	# Stop process accounting if configured
	local pacct=
	[ -e kernel_pacct ] && pacct=kernel_pacct

	# Write system information
	# Log some basic information about the system.
	(
		echo "version = $VERSION"
		echo "title = Boot chart for $( hostname | sed q ) ($( date ))"
		echo "system.uname = $( uname -srvm | sed q )"
		if [ -f /etc/alpine-release ]; then
			echo "system.release = $( sed q /etc/alpine-release )"
		elif [ -f /etc/gentoo-release ]; then
			echo "system.release = $( sed q /etc/gentoo-release )"
		elif [ -f /etc/SuSE-release ]; then
			echo "system.release = $( sed q /etc/SuSE-release )"
		elif [ -f /etc/debian_version ]; then
			echo "system.release = Debian GNU/$( uname -s ) $( cat /etc/debian_version )"
		elif [ -f /etc/frugalware-release ]; then
			echo "system.release = $( sed q /etc/frugalware-release )"
		elif [ -f /etc/pardus-release ]; then
			echo "system.release = $( sed q /etc/pardus-release )"
		else
			echo "system.release = $( sed 's/\\.//g;q' /etc/issue )"
		fi

		# Get CPU count
		local cpucount=$(grep -c '^processor' /proc/cpuinfo)
		if [ $cpucount -gt 1 -a -n "$(grep 'sibling.*2' /proc/cpuinfo)" ]; then
			# Hyper-Threading enabled
			cpucount=$(( $cpucount / 2 ))
		fi
		if grep -q '^model name' /proc/cpuinfo; then
			echo "system.cpu = $( grep '^model name' /proc/cpuinfo | sed q )"\
			     "($cpucount)"
		else
			echo "system.cpu = $( grep '^cpu' /proc/cpuinfo | sed q )"\
			     "($cpucount)"
		fi

		echo "system.kernel.options = $( sed q /proc/cmdline )"
	) >> header

	# Package log files
	tar -zcf "$BOOTLOG_DEST" header $pacct *.log
	rm "$LOGDIR"/*
	rmdir "$LOGDIR"
}

case "$1" in
158
start-initfs)
Timo Teräs's avatar
Timo Teräs committed
159 160
	NEWROOT="$2"
	(
161
		cleanup=true
Timo Teräs's avatar
Timo Teräs committed
162
		trap "not_stop_logging=false" USR1
163
		trap "cleanup=false; not_stop_logging=false" USR2
Timo Teräs's avatar
Timo Teräs committed
164

165 166
		mkdir "$LOGDIR"
		cd "$LOGDIR"
Timo Teräs's avatar
Timo Teräs committed
167
		do_logging
168
		if $cleanup; then
Timo Teräs's avatar
Timo Teräs committed
169 170 171 172
			sleep $SAMPLE_PERIOD
			finalize
		fi
	) &
173 174 175 176 177 178 179 180
	echo $! > $LOGDIR/bootchart.pid
	;;
stop-initfs)
	NEWROOT="$2"

	cd "$LOGDIR"
	mkdir "$NEWROOT$LOGDIR"
	cp /sbin/bootchartd $NEWROOT/sbin
181
	PID=$(cat bootchart.pid)
182 183 184
	kill -USR2 $PID
	wait $PID
	mv * "$NEWROOT$LOGDIR"
Timo Teräs's avatar
Timo Teräs committed
185
	;;
186 187 188 189 190 191 192 193 194
start-rootfs)
	(
		trap "not_stop_logging=false" USR1
		cd "$LOGDIR"
		do_logging
		finalize
	) &
	shift
	exec "$@"
Timo Teräs's avatar
Timo Teräs committed
195 196 197 198
	;;
esac

exit 0