2026-03-12 20:23:15
This commit is contained in:
10
tpt/tools/unix/findhomes.sh
Normal file
10
tpt/tools/unix/findhomes.sh
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
# A little helper script for finding ORACLE_HOMEs for all running instances in a Linux server
|
||||
# by Tanel Poder (http://blog.tanelpoder.com)
|
||||
|
||||
printf "%6s %-20s %-80s\n" "PID" "NAME" "ORACLE_HOME"
|
||||
pgrep -lf _pmon_ |
|
||||
while read pid pname y ; do
|
||||
printf "%6s %-20s %-80s\n" $pid $pname `ls -l /proc/$pid/exe | awk -F'>' '{ print $2 }' | sed 's/bin\/oracle$//' | sort | uniq`
|
||||
done
|
||||
|
||||
58
tpt/tools/unix/heapdump_analyzer
Normal file
58
tpt/tools/unix/heapdump_analyzer
Normal file
@@ -0,0 +1,58 @@
|
||||
#!/bin/ksh
|
||||
################################################################################
|
||||
## Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
## Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
##
|
||||
## File name: heapdump_analyzer
|
||||
## Purpose: Script for aggregating Oracle heapdump chunk sizes
|
||||
##
|
||||
## Author: Tanel Poder
|
||||
## Copyright: (c) http://www.tanelpoder.com
|
||||
##
|
||||
## Usage: 1) Take a heapdump ( read http://www.juliandyke.com )
|
||||
##
|
||||
## 2) run ./heapdump_analyzer <heapdump tracefile name>
|
||||
## For example: ./heapdump_analyzer ORCL_ora_4345.trc
|
||||
##
|
||||
## Other: Only take heapdumps when you know what you're doing!
|
||||
## Taking a heapdump on shared pool (when bit 2 in heapdump event
|
||||
## level is enabled) can hang your database for a while as it
|
||||
## holds shared pool latches for a long time if your shared pool
|
||||
## is big and heavily active.
|
||||
##
|
||||
## Private memory heapdumps are safer as only the dumped process is
|
||||
## affected.
|
||||
##
|
||||
## On Solaris you may need to replace awk with nawk in this script
|
||||
##
|
||||
################################################################################
|
||||
|
||||
if [ "$1" == "-t" ]; then
|
||||
EXCLUDE='dummy_nonexistent_12345'
|
||||
shift
|
||||
else
|
||||
EXCLUDE='Total heap size$'
|
||||
fi
|
||||
|
||||
echo
|
||||
echo " -- Heapdump Analyzer v1.03 by Tanel Poder ( https://blog.tanelpoder.com )"
|
||||
echo
|
||||
echo " Total_size #Chunks Chunk_size, From_heap, Chunk_type, Alloc_reason"
|
||||
echo " ------------ ------- ------------ ----------------- ----------------- -----------------"
|
||||
|
||||
cat $1 | awk '
|
||||
/^HEAP DUMP heap name=/ { split($0,ht,"\""); HTYPE=ht[2]; doPrintOut = 1; }
|
||||
/Chunk/{ if ( doPrintOut == 1 ) {
|
||||
split($0,sf,"\"");
|
||||
printf "%12.0f , %16s, %16s, %16s\n", $4, HTYPE, $5, sf[2];
|
||||
}
|
||||
}
|
||||
/Total heap size/ {
|
||||
printf "%12.0f , %16s, %16s, %16s\n", $5, HTYPE, "TOTAL", "Total heap size";
|
||||
doPrintOut=0;
|
||||
}
|
||||
' | grep -v "$EXCLUDE" | sort -n | uniq -c | awk '{ printf " %12.0f %s\n", $1*$2, $0 }' | sort -nr
|
||||
|
||||
echo
|
||||
|
||||
|
||||
190
tpt/tools/unix/os_explain
Normal file
190
tpt/tools/unix/os_explain
Normal file
@@ -0,0 +1,190 @@
|
||||
#!/bin/bash
|
||||
################################################################################
|
||||
## Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
## Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
##
|
||||
## File name: os_explain (version 1.1)
|
||||
## Purpose: Script to explain the currently active branch of SQL plan
|
||||
## execution from Oracle server process stack trace
|
||||
##
|
||||
## Author: Tanel Poder
|
||||
## Copyright: (c) http://www.tanelpoder.com
|
||||
##
|
||||
## Usage: 1) Take a stack trace of an Oracle process (either by using a
|
||||
## a debugger, pstack or extract the stack from a corefile,
|
||||
## save it to a file (pstack.txt for example)
|
||||
## 2) run ./os_explain <stack_trace_file>
|
||||
## For example: ./os_explain pstack.txt
|
||||
##
|
||||
##
|
||||
##
|
||||
## Alternatively you can pipe pstack output directly to os_explain
|
||||
## STDIN:
|
||||
##
|
||||
## pstack <SPID> | ./os_explain
|
||||
##
|
||||
## Other: Get stack using pstack on Solaris and Linux, using procstack
|
||||
## on AIX and by using pstack on recent versions of HP-UX.
|
||||
## Older HP-UX versions may require a debugger for getting stack
|
||||
## from OS. As an alternative (especially on Windows) you could
|
||||
## use ORADEBUG DUMP ERRORSTACK for dumping stack of a process.
|
||||
## Note that ORADEBUG's stack dump mechanism is not 100% safe
|
||||
## on active processes
|
||||
##
|
||||
## Most of Oracle kernel function prefix translations are based
|
||||
## on Metalink note 175982.1 (google for it, it's gone from the
|
||||
## Oracle site)
|
||||
##
|
||||
## On Solaris you may need to replace awk with nawk in this script
|
||||
## I don't remember why anymore, but for some reason I used it
|
||||
##
|
||||
################################################################################
|
||||
|
||||
# LIFO line reverser
|
||||
f_lifo() {
|
||||
|
||||
#echo Entering f_lifo()
|
||||
|
||||
MAX_ARRAY=1023 # Max stack array depth. You can use 4095 here but older linuxes and hp-ux shell may not like it
|
||||
|
||||
i=$MAX_ARRAY
|
||||
|
||||
IFS=^
|
||||
while read input ; do
|
||||
array[i]=$input
|
||||
((i=i-1))
|
||||
done
|
||||
|
||||
i=1
|
||||
|
||||
for output in ${array[@]} ; do
|
||||
|
||||
if test "$1" = "-n" ; then
|
||||
printf "%4d %s\n" $i $output
|
||||
else
|
||||
printf "%s\n" $output
|
||||
fi
|
||||
((i=i+1))
|
||||
done
|
||||
|
||||
}
|
||||
|
||||
|
||||
TRANSLATION_STRING='
|
||||
/----------------- lwp# 2/,$d;
|
||||
s/(.*//;
|
||||
s/ [[0-9][a-f]]{16} /./;
|
||||
s/qerae/AND-EQUAL: /g;
|
||||
s/qerba/BITMAP INDEXAND : /g;
|
||||
s/qerbc/BITMAP INDEX COMPACTION: /g;
|
||||
s/qerbi/BITMAP INDEX CREATION: /g;
|
||||
s/qerbm/MINUS: /g;
|
||||
s/qerbo/BITMAP INDEX OR: /g;
|
||||
s/qerbt/BITMAP CONVERT: /g;
|
||||
s/qerbu/BITMAP INDEX UNLIMITED-OR: /g;
|
||||
s/qerbx/BITMAP INDEX ACCESS: /g;
|
||||
s/qercb/CONNECT BY: /g;
|
||||
s/qercbi/SUPPORT FOR CONNECT BY: /g;
|
||||
s/qerco/COUNT: /g;
|
||||
s/qerdl/DELETE: /g;
|
||||
s/qerep/EXPLOSION: /g;
|
||||
s/qerff/FIFO BUFFER: /g;
|
||||
s/qerfi/FIRST ROW: /g;
|
||||
s/qerfl/FILTER DEFINITION: /g;
|
||||
s/qerfu/UPDATE: /g;
|
||||
s/qerfx/FIXED TABLE: /g;
|
||||
s/qergi/GRANULE ITERATOR: /g;
|
||||
s/qergr/GROUP BY ROLLUP: /g;
|
||||
s/qergs/GROUP BY SORT: /g;
|
||||
s/qerhc/HASH CLUSTERS: /g;
|
||||
s/qerhj/HASH JOIN: /g;
|
||||
s/qeril/IN-LIST: /g;
|
||||
s/qerim/INDEX MAINTENANCE: /g;
|
||||
s/qerix/INDEX: /g;
|
||||
s/qerjot/NESTED LOOP JOIN: /g;
|
||||
s/qerjo/NESTED LOOP OUTER: /g;
|
||||
s/qerle/LINEAR EXECUTION IMPLEMENTATION: /g;
|
||||
s/qerli/PARALLEL CREATE INDEX: /g;
|
||||
s/qerlt/LOAD TABLE: /g;
|
||||
s/qerns/GROUP BY NO SORT: /g;
|
||||
s/qeroc/OBJECT COLLECTION ITERATOR: /g;
|
||||
s/qeroi/EXTENSIBLE INDEXING QUERY COMPONENT: /g;
|
||||
s/qerpa/PARTITION: /g;
|
||||
s/qerpf/QUERY EXECUTION PREFETCH: /g;
|
||||
s/qerpx/PARALLELIZER: /g;
|
||||
s/qerrm/REMOTE: /g;
|
||||
s/qerse/SET IMPLEMENTATION: /g;
|
||||
s/qerso/SORT: /g;
|
||||
s/qersq/SEQUENCE NUMBER: /g;
|
||||
s/qerst/QUERY EXECUTION STATISTICS: /g;
|
||||
s/qertb/TABLE ACCESS: /g;
|
||||
s/qertq/TABLE QUEUE: /g;
|
||||
s/qerua/UNION-ALL: /g;
|
||||
s/qerup/UPDATE: /g;
|
||||
s/qerus/UPSERT: /g;
|
||||
s/qervw/VIEW: /g;
|
||||
s/qerwn/WINDOW: /g;
|
||||
s/qerxt/EXTERNAL TABLE FETCH : /g;
|
||||
s/opifch2/SELECT FETCH: /g
|
||||
s/qergh/HASH GROUP BY: /g
|
||||
'
|
||||
|
||||
# main()
|
||||
|
||||
case `uname -s` in
|
||||
Linux)
|
||||
FUNCPOS=4
|
||||
;;
|
||||
SunOS)
|
||||
FUNCPOS=2
|
||||
;;
|
||||
*)
|
||||
FUNCPOS=2
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$1X" == "-aX" ] ; then
|
||||
FILTER="^\$|oracle|----------"
|
||||
INDENT=" "
|
||||
shift
|
||||
else
|
||||
FILTER="^\$|\?\?|oracle|----------"
|
||||
TRANSLATION_STRING="/opifch /,\$d;/opiefn0/,\$d;/opiodr/,\$d;/opiexe/,\$d; $TRANSLATION_STRING"
|
||||
INDENT=" "
|
||||
fi
|
||||
|
||||
if [ "$1X" == "-kX" ] ; then
|
||||
FUNCPOS=2 # this is for linux kernel stack samples from /proc/PID/stack
|
||||
TRANSLATION_STRING="s/+.*//g; $TRANSLATION_STRING"
|
||||
shift
|
||||
fi
|
||||
|
||||
if [ $# -eq 0 ] ; then
|
||||
|
||||
sed -e "$TRANSLATION_STRING" \
|
||||
| egrep -v "$FILTER" \
|
||||
| sed 's/^ *//g;s/__PGOSF[0-9]*_//' \
|
||||
| awk -F" " "{ for (f=$FUNCPOS; f <= NF; f++) { printf \"%s \", \$f }; printf \"\n\" }" \
|
||||
| f_lifo \
|
||||
| awk "
|
||||
BEGIN{ option=\" \" } /rwsfcd/{ option=\"* \" } !/rwsfcd/{ pref=(pref \"$INDENT\") ;
|
||||
print pref option \$0 ; option=\" \" }
|
||||
"
|
||||
else
|
||||
|
||||
for i in $* ; do
|
||||
sed -e "$TRANSLATION_STRING" < $i \
|
||||
| egrep -v "$FILTER" \
|
||||
| sed 's/^ *//g;s/__PGOSF[0-9]*_//' \
|
||||
| awk -F" " "{ for (f=$FUNCPOS; f <= NF; f++) { printf \"%s \", \$f }; printf \"\n\" }" \
|
||||
| f_lifo \
|
||||
| awk "
|
||||
BEGIN{ option=\" \" } /rwsfcd/{ option=\"* \" } !/rwsfcd/{ pref=(pref \"$INDENT\") ;
|
||||
print pref option \$0 ; option=\" \" }
|
||||
"
|
||||
done
|
||||
|
||||
fi
|
||||
|
||||
# that's all!
|
||||
|
||||
24
tpt/tools/unix/procio.sh
Normal file
24
tpt/tools/unix/procio.sh
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Tiny Linux /proc/<pid>/io demo script by Tanel Poder
|
||||
# http://www.tanelpoder.com
|
||||
|
||||
PID=$1
|
||||
TMPFILE1=/tmp/procio.${PID}.tmp1
|
||||
TMPFILE2=/tmp/procio.${PID}.tmp2
|
||||
SLEEP=5
|
||||
|
||||
trap 'rm -f $TMPFILE1 $TMPFILE2 ; exit 0' 0
|
||||
|
||||
echo Sampling process $PID IO every $SLEEP seconds...
|
||||
|
||||
cat /proc/$PID/io > $TMPFILE2
|
||||
|
||||
while true ; do
|
||||
mv $TMPFILE2 $TMPFILE1
|
||||
sleep $SLEEP
|
||||
cat /proc/$PID/io > $TMPFILE2
|
||||
paste $TMPFILE1 $TMPFILE2 | awk '{ printf "%30s %d\n", $1, $4-$2 }'
|
||||
echo
|
||||
done
|
||||
|
||||
170
tpt/tools/unix/procmm.py
Normal file
170
tpt/tools/unix/procmm.py
Normal file
@@ -0,0 +1,170 @@
|
||||
#!/bin/env python
|
||||
|
||||
# Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
# Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
# perms
|
||||
# r = read
|
||||
# w = write
|
||||
# x = execute
|
||||
# s = shared
|
||||
# p = private (copy on write)
|
||||
|
||||
import sys, os, pwd, re, json
|
||||
|
||||
re_mapheader = re.compile('[0-9a-f]+-[0-9a-f]+', re.IGNORECASE)
|
||||
|
||||
def readFileLines(name):
|
||||
with file(name) as f:
|
||||
s = f.readlines()
|
||||
return s
|
||||
|
||||
def readFile(name):
|
||||
x=readFileLines(name)
|
||||
if x:
|
||||
return x[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
def getProcRec(pid):
|
||||
try:
|
||||
mr={}
|
||||
mr['pid'] = pid
|
||||
mr['comm'] = readFile('/proc/' + pid + '/comm')
|
||||
mr['cmdline'] = readFile('/proc/' + pid + '/cmdline')
|
||||
mr['username'] = pwd.getpwuid(os.stat('/proc/' + pid).st_uid).pw_name
|
||||
|
||||
except IOError as e:
|
||||
print "Process gone"
|
||||
except Exception as e:
|
||||
print "error", e
|
||||
raise
|
||||
return mr
|
||||
|
||||
def getProcMemData(pid):
|
||||
memseg={}
|
||||
memdetail={}
|
||||
allmemseg={}
|
||||
allmemdetail={}
|
||||
|
||||
try:
|
||||
for l in readFileLines('/proc/' + pid + '/smaps'):
|
||||
if re_mapheader.match(l):
|
||||
memseg['baddr_hex'] = l.split()[0].split('-')[0]
|
||||
memseg['eaddr_hex'] = l.split()[0].split('-')[1]
|
||||
memseg['perms'] = l.split()[1]
|
||||
memseg['offset'] = l.split()[2]
|
||||
memseg['dev'] = l.split()[3]
|
||||
memseg['inode'] = l.split()[4]
|
||||
if len(l.split()) >= 6:
|
||||
s = l.split()[5]
|
||||
if s.startswith('/dev/shm'):
|
||||
s = '/dev/shm'
|
||||
#re.sub('', '', s)
|
||||
#print "s =", s
|
||||
memseg['name'] = s
|
||||
else:
|
||||
memseg['name'] = '[anon]'
|
||||
memseg['baddr'] = int(memseg['baddr_hex'], 16)
|
||||
memseg['eaddr'] = int(memseg['eaddr_hex'], 16)
|
||||
memseg['size'] = memseg['eaddr'] - memseg['baddr']
|
||||
|
||||
allmemseg[memseg['name']] = memseg
|
||||
else:
|
||||
# smaps format example:
|
||||
# Size: 136 kB
|
||||
# Rss: 40 kB ...
|
||||
memdetail[l.split()[0].replace(':','')] = memdetail.get(l.split()[0].replace(':',''), 0) + int(l.split()[1])
|
||||
|
||||
allmemdetail[memseg['name']] = memdetail
|
||||
|
||||
return allmemseg, allmemdetail
|
||||
|
||||
except IOError as e:
|
||||
print "Process gone"
|
||||
except Exception as e:
|
||||
print "error", e
|
||||
raise
|
||||
|
||||
def getProcMemDataSum(pidlist):
|
||||
memsum = {}
|
||||
for p in pidlist:
|
||||
procrec = getProcRec(p)
|
||||
#print "\n============ PID: %d %s" % ( int(procrec['pid']), procrec['cmdline'].replace('\x00','') )
|
||||
memseg, memdata = getProcMemData(p)
|
||||
#print memseg
|
||||
for ms in memseg:
|
||||
memsum[ms] = memdata[ms]
|
||||
#for i in memdata[ms]:
|
||||
# #print "%-25s %10d kB %s" % ( i, memdata[ms][i], ms )
|
||||
# memsum[(ms,i)] = memsum.get((ms,i), 0) + memdata[ms][i]
|
||||
|
||||
return memsum
|
||||
|
||||
def main(argv):
|
||||
memdatasum = getProcMemDataSum(argv)
|
||||
#print memdatasum
|
||||
#print json.dumps(memdatasum, indent=4)
|
||||
print "%10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %s" % (
|
||||
'VSize'
|
||||
, 'PTE'
|
||||
, 'Locked'
|
||||
, 'MMUPages'
|
||||
, 'Priv_Clean'
|
||||
, 'Priv_Dirty'
|
||||
, 'Pss'
|
||||
, 'Referenced'
|
||||
, 'Rss'
|
||||
, 'Shr_Clean'
|
||||
, 'Shr_Dirty'
|
||||
, 'Swap'
|
||||
, ' Segment_Name'
|
||||
)
|
||||
print "%10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %10s %s" % (
|
||||
'----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, '----------'
|
||||
, ' ----------------------------------------------------------------------'
|
||||
)
|
||||
for mseg in memdatasum:
|
||||
m = memdatasum[mseg]
|
||||
print "%10d %10d %10d %10d %10d %10d %10d %10d %10d %10d %10d %10d %s" % (
|
||||
m.get('Size', 0)
|
||||
, m.get('KernelPageSize', 0)
|
||||
, m.get('Locked', 0)
|
||||
, m.get('MMUPageSize', 0)
|
||||
, m.get('Private_Clean', 0)
|
||||
, m.get('Private_Dirty', 0)
|
||||
, m.get('Pss', 0)
|
||||
, m.get('Referenced', 0)
|
||||
, m.get('Rss', 0)
|
||||
, m.get('Shared_Clean', 0)
|
||||
, m.get('Shared_Dirty', 0)
|
||||
, m.get('Swap', 0)
|
||||
, mseg
|
||||
)
|
||||
|
||||
#for a in argv:
|
||||
# procrec = getProcRec(a)
|
||||
# print "\n============ PID: %d %s" % ( int(procrec['pid']), procrec['cmdline'].replace('\x00','') )
|
||||
# memseg, memdata = getProcMemData(a)
|
||||
# #for i in sorted(memdata, key=memdata.get, reverse=False):
|
||||
# for i in sorted(memdata, reverse=False):
|
||||
# print "%-25s %10d kB" % ( i, memdata[i] )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv[1:])
|
||||
|
||||
134
tpt/tools/unix/procmm.sh
Normal file
134
tpt/tools/unix/procmm.sh
Normal file
@@ -0,0 +1,134 @@
|
||||
#!/usr/bin/sh
|
||||
|
||||
################################################################################
|
||||
# Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
# Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
#
|
||||
# Script: procmm.sh (Process Memory Matrix) v1.03
|
||||
#
|
||||
# Purpose: Show process memory usage for different mappings and segment types
|
||||
#
|
||||
# Copyright: Copyright (c) 2010 Tanel Poder ( http://tech.e2sn.com )
|
||||
# All rights reserved.
|
||||
#
|
||||
# ------------------------------------------------------------------------------
|
||||
#
|
||||
# Usage: procmm.sh [-t|-a] <pidlist>
|
||||
#
|
||||
# Without any special options procmm.sh will show you a matrix
|
||||
# of the processes address space segment types and their respective
|
||||
# memory usages/reservations, separately for every process in the
|
||||
# pidlist.
|
||||
#
|
||||
# -t option will only show total memory usage of all processes
|
||||
# listed in pidlist. Any ANON memory usage and swap reservation
|
||||
# for *shared* mappings (mapped binaries, libraries, shared memory
|
||||
# segments - Oracle SGA) is not shown.
|
||||
# Note that pmap command is not cheap one, so you probably do not
|
||||
# want to run it over many processes frequently
|
||||
#
|
||||
# -a option will list ANON memory usage and swap reservation also for
|
||||
# shared mappings. The -t and -a options are mutually exclusive
|
||||
# as it doesn not make sense to sum together the same shared mapping
|
||||
# memory usage of multiple processes.
|
||||
#
|
||||
# Comments: This script currently only works on Solaris as the pmap command
|
||||
# on other platforms doesnt currently show all required info. On
|
||||
# Linux it will be possible to read this info from proc filesystem (TODO)
|
||||
#
|
||||
# If you are getting "address space is changing" errors from pmap then try
|
||||
# again or suspend the process for duration of this script run.
|
||||
# NB! Suspending processes may be dangerous in some cases (such as when
|
||||
# it is holding a hot latch) so you better know what you are doing.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
get_matrix() {
|
||||
p_pid="$1"
|
||||
#[ "$1" -eq 0 ] && p_pid="all" || p_pid=$1
|
||||
#pmap -x $p_pid | tr '[]' ' ' | egrep -v "^ *Address|^---------|total Kb|^[0-9]*:" | nawk ''
|
||||
join -j 1 /tmp/procmm-x.$$ /tmp/procmm-s.$$ > /tmp/blah
|
||||
join -j 1 /tmp/procmm-x.$$ /tmp/procmm-s.$$ | sed 's/ism shmid/ism_shmid/g' | tr '[]' ' ' | egrep -v "^ *Address|^---------|total Kb|^[0-9]*:" | nawk '
|
||||
{
|
||||
item=$7
|
||||
#print "before", s
|
||||
sub(/.*\.so.*/, "lib", item)
|
||||
#print "after", s
|
||||
#item = gensub(/.*\.so.*/, "lib", "g", $7)
|
||||
#item = gensub(/lib.+|ld\..+/, "lib", "g", $7)
|
||||
#print $7 " = " item
|
||||
vmem[item] += $2
|
||||
rss[item] += $3
|
||||
anon[item] += $4
|
||||
locked[item] += $5
|
||||
swap[item] += $9
|
||||
#print $0
|
||||
}
|
||||
END {
|
||||
printf "%6-s %20s %12s %12s %12s %12s %12s\n", "PID", "SEGMENT_TYPE", "VIRTUAL", "RSS", "ANON", "LOCKED", "SWAP_RSVD"
|
||||
printf "------ -------------------- ------------ ------------ ------------ ------------ ------------\n"
|
||||
for (x in vmem) {
|
||||
printf "%6-d %20s %12d %12d %12d %12d %12d\n", '$p_pid', x, vmem[x], rss[x], anon[x], locked[x], swap[x]
|
||||
|
||||
total_vmem += vmem[x]
|
||||
total_rss += rss[x]
|
||||
total_anon += anon[x]
|
||||
total_locked += locked[x]
|
||||
total_swap += swap[x]
|
||||
}
|
||||
|
||||
printf "------ -------------------- ------------ ------------ ------------ ------------ ------------\n"
|
||||
printf "%6-d %20s %12d %12d %12d %12d %12d\n\n", '$p_pid', "TOTAL(kB)", total_vmem, total_rss, total_anon, total_locked, total_swap
|
||||
|
||||
}
|
||||
'
|
||||
}
|
||||
|
||||
echo "\n-- procmm.sh: Process Memory Matrix v1.03 by Tanel Poder ( http://tech.e2sn.com )"
|
||||
|
||||
if [ $# -lt 1 ] ; then
|
||||
echo "\nUsage:\n"
|
||||
echo " $0 [-a|-t] <pidlist>\n"
|
||||
echo " Option -a would report swap reservations and anonymous memory"
|
||||
echo " for shared mappings (like Oracle SGA) too\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# defaults
|
||||
pmap_option=""
|
||||
compute_total=0
|
||||
|
||||
case "$1" in
|
||||
"-a") pmap_option="a" ; shift ;;
|
||||
"-t") compute_total=1 ; shift ;;
|
||||
esac
|
||||
|
||||
echo "-- All numbers are shown in kilobytes\n"
|
||||
|
||||
pidlist="$*"
|
||||
#echo $pidlist
|
||||
|
||||
if [ $compute_total -eq 0 ]; then
|
||||
for pid in $pidlist; do
|
||||
# ps -opid,vsz,rss,args -p $pid | nawk '/ *[0-9]+/{ printf "-- ps info: PID=%d VSZ=%d RSS=%d ARGS=%s\n\n", $1,$2,$3,$4 }'
|
||||
rm -f /tmp/procmm-x.$$ /tmp/procmm-s.$$
|
||||
pmap -x$pmap_option $pid | sed 's/ism shmid/ism_shmid/g' | tr '[]' ' ' | egrep -v "^ *Address|^---------|total Kb|^[0-9]+:" > /tmp/procmm-x.$$
|
||||
pmap -S$pmap_option $pid | sed 's/ism shmid/ism_shmid/g' | tr '[]' ' ' | egrep -v "^ *Address|^---------|total Kb|^[0-9]+:" > /tmp/procmm-s.$$
|
||||
get_matrix $pid
|
||||
rm -f /tmp/procmm-x.$$ /tmp/procmm-s.$$
|
||||
done
|
||||
else
|
||||
rm -f /tmp/procmm-x.$$ /tmp/procmm-s.$$
|
||||
printf "Total PIDs %d, working: " $#
|
||||
for pid in $pidlist; do
|
||||
# ps -opid,vsz,rss,args -p $pid | nawk '/ *[0-9]+/{ printf "-- ps info: PID=%d VSZ=%d RSS=%d ARGS=%s\n\n", $1,$2,$3,$4 }'
|
||||
pmap -x$pmap_option $pid | sed 's/ism shmid/ism_shmid/g' | tr '[]' ' ' | egrep -v "^ *Address|^---------|total Kb|^[0-9]*:" >> /tmp/procmm-x.$$
|
||||
pmap -S$pmap_option $pid | sed 's/ism shmid/ism_shmid/g' | tr '[]' ' ' | egrep -v "^ *Address|^---------|total Kb|^[0-9]*:" >> /tmp/procmm-s.$$
|
||||
printf "."
|
||||
done
|
||||
printf "\n\n"
|
||||
get_matrix 0
|
||||
echo "-- Note that in Total (-t) calculation mode it makes sense to look into ANON and SWAP_RSVD"
|
||||
echo "-- totals only as other numbers may be heavily \"doublecounted\" due to overlaps of shared mappings\n"
|
||||
rm -f /tmp/procmm-x.$$ /tmp/procmm-s.$$
|
||||
fi
|
||||
32
tpt/tools/unix/runqlat.sh
Normal file
32
tpt/tools/unix/runqlat.sh
Normal file
@@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Tiny Linux /proc/<pid>/schedstat demo script by Tanel Poder
|
||||
# https://tanelpoder.com
|
||||
#
|
||||
# You may want to run this with high priority:
|
||||
# sudo nice -n -10 ./runqlat.sh PID
|
||||
#
|
||||
# currently this script assumes that it will speep exactly for $SLEEP
|
||||
# seconds, but it can itself be affected by CPU overload and you may
|
||||
# see values that don't add up to 1000 ms per sec
|
||||
# (or negative percentages in the derived BLKD% column)
|
||||
|
||||
PID=$1
|
||||
SLEEP=1
|
||||
|
||||
echo Sampling /proc/$PID/schedstat every $SLEEP seconds...
|
||||
|
||||
printf "%6s %6s %6s\n" "CPU%" "RUNQ%" "SLP%"
|
||||
while true ; do
|
||||
read -r CPU_NS_1 LAT_NS_1 SLICES_ON_THIS_CPU_1 < /proc/$PID/schedstat
|
||||
sleep $SLEEP
|
||||
read -r CPU_NS_2 LAT_NS_2 SLICES_ON_THIS_CPU_2 < /proc/$PID/schedstat
|
||||
|
||||
ON_CPU=$((($CPU_NS_2-$CPU_NS_1)/10000000))
|
||||
ON_RUNQ=$((($LAT_NS_2-$LAT_NS_1)/10000000))
|
||||
OTHER=$((100-($ON_CPU+ON_RUNQ)))
|
||||
|
||||
printf "%6d %6d %6d" $ON_CPU $ON_RUNQ $OTHER
|
||||
echo
|
||||
done
|
||||
|
||||
49
tpt/tools/unix/ssexplorer.sh
Normal file
49
tpt/tools/unix/ssexplorer.sh
Normal file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# System State Dump "explorer"
|
||||
# It just adds links to parent State Object location in the file for easier navigation
|
||||
|
||||
# Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
# Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
|
||||
TRACEFILE=$1
|
||||
OUTPUTFILE=$1.html
|
||||
|
||||
sed -e '
|
||||
s/</\</g
|
||||
s/>/\>/g
|
||||
s/SO: \(0x[A-Fa-f0-9]*\)/<a name="\1"><mark>SO: \1<\/mark><\/a>/
|
||||
s/LIBRARY HANDLE:\(0x[A-Fa-f0-9]*\)/<a name="\1">LIBRARY HANDLE:\1<\/a>/
|
||||
s/owner: \(0x[A-Fa-f0-9]*\)/owner: <a href="#\1">\1<\/a>/
|
||||
s/handle=\(0x[A-Fa-f0-9]*\)/handle=<a href="#\1">\1<\/a>/
|
||||
' $TRACEFILE | awk '
|
||||
BEGIN { print "<html><head><title>System State Dump Explorer by Tanel Poder</title></head><body><pre><code>" }
|
||||
{ print $0 }
|
||||
END { print "</code></pre></body></html>" }
|
||||
' > $OUTPUTFILE
|
||||
|
||||
echo Done writing into $OUTPUTFILE
|
||||
echo
|
||||
ls -l $OUTPUTFILE
|
||||
|
||||
|
||||
#awk '
|
||||
#
|
||||
# BEGIN { print "<html><head><title>System State Dump Explorer by Tanel Poder</title></head><body><pre><code>" }
|
||||
#
|
||||
# /0x[A-Fa-f0-9]/ { gsub( /(0x[A-Fa-f0-9]*)/, "<a href=\"#&\">&</a>", $0 ) }
|
||||
#
|
||||
## /SO: 0x[A-Za-z0-9]/ {
|
||||
## match($0, /(0x[A-Fa-f0-9]*),/ , arr)
|
||||
## printf ("<a name=\"%s\"></a>%s\n", arr[1], gsub( /(0x[A-Fa-f0-9]*)/, "<a href=\"#&\">&</a>", $0 ) )
|
||||
##
|
||||
## }
|
||||
## !/SO: 0x[A-Fa-f0-9]/ { gsub(/(0x[A-Fa-f0-9]*)/, "<a href=\"#&\">&</a>", $0) ; printf("%s\n", $0) }
|
||||
#
|
||||
#
|
||||
# END { print "</code></pre></body></html>" }
|
||||
#
|
||||
#
|
||||
#' | awk '/SO: / { sub( /<a href=/, "<a name=" ) }' > > $1.html
|
||||
|
||||
|
||||
24
tpt/tools/unix/strip_stack
Normal file
24
tpt/tools/unix/strip_stack
Normal file
@@ -0,0 +1,24 @@
|
||||
#!/bin/ksh
|
||||
#
|
||||
# Copyright 2018 Tanel Poder. All rights reserved. More info at http://tanelpoder.com
|
||||
# Licensed under the Apache License, Version 2.0. See LICENSE.txt for terms & conditions.
|
||||
# strip_stack by Tanel Poder (www.tanelpoder.com)
|
||||
#
|
||||
# strips program counter function offsets and aggregates dtrace stack sampler output
|
||||
#
|
||||
# usage: strip_stack <filename>
|
||||
#
|
||||
|
||||
cat $1 | sed 's/^ *//;s/+.*$//' | \
|
||||
awk '/^$/{ printf "\n" }/^[0-9]*$/{ printf ";%s", $1 }/[a-z]/{ printf "%s<-", $1 }END{ printf "\n" }' | \
|
||||
sort | \
|
||||
awk -F";" '
|
||||
/NR==1/{ sum=0; total=0; oldstack=$2 }
|
||||
{
|
||||
if (oldstack==$2) {sum+=$3;total+=$3}
|
||||
else {printf "%d %s\n", sum, oldstack; oldstack=$2; sum=$3}
|
||||
}
|
||||
END {printf "%d %s\n%d total samples\n", sum, oldstack,total}
|
||||
' | \
|
||||
sort -bnr
|
||||
|
||||
Reference in New Issue
Block a user