1#!/bin/sh 2 3# 4# Copyright (c) 2015 EMC Corp. 5# All rights reserved. 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27# 28 29# Memory leak detector: run vmstat -m & -z in a loop. 30 31export LANG=en_US.ISO8859-1 32while getopts dmz flag; do 33 case "$flag" in 34 d) debug="-v debug=1" ;; 35 m) optz=n ;; 36 z) optm=n ;; 37 *) echo "Usage $0 [-d] [-m] [-z]" 38 return 1 ;; 39 esac 40done 41 42pages=`sysctl -n vm.stats.vm.v_page_count` 43start=`date '+%s'` 44OIFS=$IFS 45while true; do 46 # Type InUse MemUse 47 [ -z "$optm" ] && vmstat -m | sed 1d | 48 while read l; do 49 name=`echo $l | sed -E 's/ [0-9]+ .*//; s/^ *//'` 50 memuse=`echo $l | sed -E "s#$name##" | \ 51 awk '{print int(($2 + 1023) / 1024)}'` 52 [ "$memuse" -ne 0 ] && echo "vmstat -m $name,$memuse" 53 done 54 55 # ITEM SIZE LIMIT USED 56 [ -z "$optz" ] && vmstat -z | sed 1d | 57 while read l; do 58 name=`echo $l | sed 's/:.*//'` 59 l=`echo $l | sed 's/.*://'` 60 size=`echo $l | awk -F ',' '{print $1}'` 61 used=`echo $l | awk -F ',' '{print $3}'` 62 [ -z "$used" -o -z "$size" ] && 63 { echo "used/size not set $l" 1>&2; continue; } 64 echo $used | egrep -q '^ *[0-9]{1,10}$' || 65 { echo "Bad used: $used. l=$l" 1>&2; continue; } 66 tot=$((((size * used) + 1023) / 1024)) 67 [ $tot -ne 0 ] && 68 echo "vmstat -z $name,$tot" 69 done 70 71 r=`sysctl -n vm.stats.vm.v_wire_count` 72 [ -n "$r" ] && 73 echo "vm.stats.vm.v_wire_count, \ 74 $((r * 4))" 75 r=`sysctl -n vm.stats.vm.v_free_count` 76 [ -n "$r" ] && 77 echo "pages in use, \ 78 $(((pages - r) * 4))" 79 r=`sysctl -n vm.kmem_map_size` 80 [ -n "$r" ] && 81 echo "kmem_map_size, $r" 82 sleep 10 83done | awk $debug -F, ' 84{ 85# Pairs of "name, value" are passed to this awk script. 86 name=$1; 87 size=$2; 88 if (size > s[name]) { 89 if (++n[name] > 60) { 90 cmd="date '+%T'"; 91 cmd | getline t; 92 close(cmd); 93 printf "%s \"%s\" %'\''dK\r\n", t, 94 name, size; 95 fflush 96 n[name] = 0; 97 } 98 s[name] = size; 99 if (debug == 1 && n[name] > 1) 100 printf "%s, size %d, count %d\r\n", 101 name, s[name], n[name] > "/dev/stderr" 102 } else if (size < s[name] && n[name] > 0) 103 n[name]-- 104}' | while read l; do 105 d=$(((`date '+%s'` - start) / 86400)) 106 echo "$d $l" 107done 108# Note: the %'d is used to trigger a thousands-separator character. 109