#!/bin/sh # # Bootchart logger script # Ziga Mahkovec # # Modified heavily for Alpine Linux bootcharting # Timo Teras # # 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 SAMPLE_PERIOD=0.2 PROCESS_ACCOUNTING="yes" 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 [ -e kernel_pacct ] && accton } # 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 cpucount=$(grep -c '^processor' /proc/cpuinfo || [ $? -eq 1 ]) 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 start-initfs) NEWROOT="$2" ( cleanup=true trap "not_stop_logging=false" USR1 trap "cleanup=false; not_stop_logging=false" USR2 mkdir "$LOGDIR" cd "$LOGDIR" do_logging if $cleanup; then sleep $SAMPLE_PERIOD finalize fi ) & echo $! > $LOGDIR/bootchart.pid ;; stop-initfs) NEWROOT="$2" cd "$LOGDIR" mkdir "$NEWROOT$LOGDIR" cp /sbin/bootchartd $NEWROOT/sbin PID=$(cat bootchart.pid) kill -USR2 $PID wait $PID mv * "$NEWROOT$LOGDIR" ;; start-rootfs) ( trap "not_stop_logging=false" USR1 cd "$LOGDIR" do_logging finalize ) & shift exec "$@" ;; esac exit 0