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 sed 's/\(.* \)\([0-9][0-9]*\) *\(.*\)K .*/\1:\2:\3/' | 49 while IFS=: read -r p1 p2 p3; do 50 name=`echo $p1 | sed 's/^ *//;s/ *$//'` 51 memuse=$p3 52 [ "$memuse" -ne 0 ] && echo "vmstat -m $name,$memuse" 53 done 54 55 # ITEM SIZE LIMIT USED 56 [ -z "$optz" ] && vmstat -z | 57 grep -vE '(rl_entry):' | 58 sed "1,2d;/^$/d;s/: /, /" | 59 sed -E 's/[^[:print:]\r\t]/ /g' | 60 while read l; do 61 IFS=',' 62 set $l 63 [ $# -lt 8 ] && 64 { echo "# args must be >= 8, but is $# in $l" 1>&2; 65 continue; } 66 size=$2 67 used=$4 68 [ -z "$used" -o -z "$size" ] && 69 { echo "used/size not set $l" 1>&2; continue; } 70 echo $used | egrep -q '^ *[0-9]{1,10}$' || 71 { echo "Bad used: $used. l=$l" 1>&2; continue; } 72 tot=$((((size * used) + 1023) / 1024)) 73 [ $tot -ne 0 ] && 74 echo "vmstat -z $1,$tot" 75 done 76 77 r=`sysctl -n vm.stats.vm.v_wire_count` 78 [ -n "$r" ] && 79 echo "vm.stats.vm.v_wire_count, \ 80 $((r * 4))" 81 r=`sysctl -n vm.stats.vm.v_free_count` 82 [ -n "$r" ] && 83 echo "pages in use, \ 84 $(((pages - r) * 4))" 85 r=`sysctl -n vm.kmem_map_size` 86 [ -n "$r" ] && 87 echo "kmem_map_size, $r" 88 sleep 10 89done | awk $debug -F, ' 90{ 91# Pairs of "name, value" are passed to this awk script. 92 name=$1; 93 size=$2; 94 if (size > s[name]) { 95 if (++n[name] > 60) { 96 cmd="date '+%T'"; 97 cmd | getline t; 98 close(cmd); 99 printf "%s \"%s\" %'\''dK\r\n", t, 100 name, size; 101 n[name] = 0; 102 } 103 s[name] = size; 104 if (debug == 1 && n[name] > 1) 105 printf "%s, size %d, count %d\r\n", 106 name, s[name], n[name] > "/dev/stderr" 107 } else if (size < s[name] && n[name] > 0) 108 n[name]-- 109}' | while read l; do 110 d=$(((`date '+%s'` - start) / 86400)) 111 echo "$d $l" 112done 113# Note: the %'d is used to trigger a thousands-separator character. 114