]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/crashinfo/crashinfo.sh
sysctl(9): Fix a few mandoc related issues
[FreeBSD/FreeBSD.git] / usr.sbin / crashinfo / crashinfo.sh
1 #!/bin/sh
2 #
3 # SPDX-License-Identifier: BSD-3-Clause
4 #
5 # Copyright (c) 2008 Yahoo!, Inc.
6 # All rights reserved.
7 #
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions
10 # are met:
11 # 1. Redistributions of source code must retain the above copyright
12 #    notice, this list of conditions and the following disclaimer.
13 # 2. Redistributions in binary form must reproduce the above copyright
14 #    notice, this list of conditions and the following disclaimer in the
15 #    documentation and/or other materials provided with the distribution.
16 # 3. Neither the name of the author nor the names of any co-contributors
17 #    may be used to endorse or promote products derived from this software
18 #    without specific prior written permission.
19 #
20 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 # ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 # SUCH DAMAGE.
31 #
32 # $FreeBSD$
33
34 usage()
35 {
36         echo "usage: crashinfo [-b] [-d crashdir] [-n dumpnr]" \
37                 "[-k kernel] [core]"
38         exit 1
39 }
40
41 # Remove an uncompressed copy of a dump
42 cleanup()
43 {
44
45         [ -e $VMCORE ] && rm -f $VMCORE
46 }
47
48 # Find a gdb binary to use and save the value in GDB.
49 find_gdb()
50 {
51         local binary
52
53         for binary in /usr/local/bin/gdb /usr/libexec/gdb; do
54                 if [ -x ${binary} ]; then
55                         GDB=${binary}
56                         return
57                 fi
58         done
59 }
60
61 # Run a single gdb command against a kernel file in batch mode.
62 # The kernel file is specified as the first argument and the command
63 # is given in the remaining arguments.
64 gdb_command()
65 {
66         local k
67
68         k=$1 ; shift
69
70         if [ ${GDB} = /usr/local/bin/gdb ]; then
71                 ${GDB} -batch -ex "$@" $k
72         else
73                 echo -e "$@" | ${GDB} -x /dev/stdin -batch $k
74         fi
75 }
76
77 find_kernel()
78 {
79         local ivers k kvers
80
81         ivers=$(awk '
82         /Version String/ {
83                 print
84                 nextline=1
85                 next
86         }
87         nextline==1 {
88                 if ($0 ~ "^  [A-Za-z ]+: ") {
89                         nextline=0
90                 } else {
91                         print
92                 }
93         }' $INFO)
94
95         # Look for a matching kernel version, handling possible truncation
96         # of the version string recovered from the dump.
97         for k in `sysctl -n kern.bootfile` $(ls -t /boot/*/kernel); do
98                 kvers=$(gdb_command $k 'printf "  Version String: %s", version' | \
99                     awk "{line=line\$0\"\n\"} END{print substr(line,1,${#ivers})}" \
100                     2>/dev/null)
101                 if [ "$ivers" = "$kvers" ]; then
102                         KERNEL=$k
103                         break
104                 fi
105         done
106 }
107
108 BATCH=false
109 CRASHDIR=/var/crash
110 DUMPNR=
111 KERNEL=
112
113 while getopts "bd:n:k:" opt; do
114         case "$opt" in
115         b)
116                 BATCH=true
117                 ;;
118         d)
119                 CRASHDIR=$OPTARG
120                 ;;
121         n)
122                 DUMPNR=$OPTARG
123                 ;;
124         k)
125                 KERNEL=$OPTARG
126                 ;;
127         \?)
128                 usage
129                 ;;
130         esac
131 done
132
133 shift $((OPTIND - 1))
134
135 if [ $# -eq 1 ]; then
136         if [ -n "$DUMPNR" ]; then
137                 echo "-n and an explicit vmcore are mutually exclusive"
138                 usage
139         fi
140
141         # Figure out the crash directory and number from the vmcore name.
142         CRASHDIR=`dirname $1`
143         DUMPNR=$(expr $(basename $1) : 'vmcore\.\([0-9]*\)')
144         if [ -z "$DUMPNR" ]; then
145                 echo "Unable to determine dump number from vmcore file $1."
146                 exit 1
147         fi
148 elif [ $# -gt 1 ]; then
149         usage
150 else
151         # If we don't have an explicit dump number, operate on the most
152         # recent dump.
153         if [ -z "$DUMPNR" ]; then
154                 if ! [ -r $CRASHDIR/bounds ]; then
155                         echo "No crash dumps in $CRASHDIR."
156                         exit 1
157                 fi                      
158                 next=`cat $CRASHDIR/bounds`
159                 if [ -z "$next" ] || [ "$next" -eq 0 ]; then
160                         echo "No crash dumps in $CRASHDIR."
161                         exit 1
162                 fi
163                 DUMPNR=$(($next - 1))
164         fi
165 fi
166
167 VMCORE=$CRASHDIR/vmcore.$DUMPNR
168 INFO=$CRASHDIR/info.$DUMPNR
169 FILE=$CRASHDIR/core.txt.$DUMPNR
170 HOSTNAME=`hostname`
171
172 if $BATCH; then
173         echo "Writing crash summary to $FILE."
174         exec > $FILE 2>&1
175 fi
176
177 find_gdb
178 if [ -z "$GDB" ]; then
179         echo "Unable to find a kernel debugger."
180         echo "Please install the devel/gdb port or gdb package."
181         exit 1
182 fi
183
184 if [ ! -e $VMCORE ]; then
185         if [ -e $VMCORE.gz ]; then
186                 trap cleanup EXIT HUP INT QUIT TERM
187                 gzcat $VMCORE.gz > $VMCORE
188         elif [ -e $VMCORE.zst ]; then
189                 trap cleanup EXIT HUP INT QUIT TERM
190                 zstdcat $VMCORE.zst > $VMCORE
191         else
192                 echo "$VMCORE not found"
193                 exit 1
194         fi
195 fi
196
197 if [ ! -e $INFO ]; then
198         echo "$INFO not found"
199         exit 1
200 fi
201
202 # If the user didn't specify a kernel, then try to find one.
203 if [ -z "$KERNEL" ]; then
204         find_kernel
205         if [ -z "$KERNEL" ]; then
206                 echo "Unable to find matching kernel for $VMCORE"
207                 exit 1
208         fi
209 elif [ ! -e $KERNEL ]; then
210         echo "$KERNEL not found"
211         exit 1
212 fi
213
214 umask 077
215
216 # Simulate uname
217 ostype=$(gdb_command $KERNEL 'printf "%s", ostype')
218 osrelease=$(gdb_command $KERNEL 'printf "%s", osrelease')
219 version=$(gdb_command $KERNEL 'printf "%s", version' | tr '\t\n' '  ')
220 machine=$(gdb_command $KERNEL 'printf "%s", machine')
221
222 if ! $BATCH; then
223         echo "Writing crash summary to $FILE."
224         exec > $FILE 2>&1
225 fi
226
227 echo "$HOSTNAME dumped core - see $VMCORE"
228 echo
229 date
230 echo
231 echo "$ostype $HOSTNAME $osrelease $version $machine"
232 echo
233 sed -ne '/^  Panic String: /{s//panic: /;p;}' $INFO
234 echo
235
236 # XXX: /bin/sh on 7.0+ is broken so we can't simply pipe the commands to
237 # kgdb via stdin and have to use a temporary file instead.
238 file=`mktemp /tmp/crashinfo.XXXXXX`
239 if [ $? -eq 0 ]; then
240         echo "bt" >> $file
241         echo "quit" >> $file
242         ${GDB%gdb}kgdb $KERNEL $VMCORE < $file
243         rm -f $file
244         echo
245 fi
246 echo
247
248 echo "------------------------------------------------------------------------"
249 echo "ps -axlww"
250 echo
251 ps -M $VMCORE -N $KERNEL -axlww
252 echo
253
254 echo "------------------------------------------------------------------------"
255 echo "vmstat -s"
256 echo
257 vmstat -M $VMCORE -N $KERNEL -s
258 echo
259
260 echo "------------------------------------------------------------------------"
261 echo "vmstat -m"
262 echo
263 vmstat -M $VMCORE -N $KERNEL -m
264 echo
265
266 echo "------------------------------------------------------------------------"
267 echo "vmstat -z"
268 echo
269 vmstat -M $VMCORE -N $KERNEL -z
270 echo
271
272 echo "------------------------------------------------------------------------"
273 echo "vmstat -i"
274 echo
275 vmstat -M $VMCORE -N $KERNEL -i
276 echo
277
278 echo "------------------------------------------------------------------------"
279 echo "pstat -T"
280 echo
281 pstat -M $VMCORE -N $KERNEL -T
282 echo
283
284 echo "------------------------------------------------------------------------"
285 echo "pstat -s"
286 echo
287 pstat -M $VMCORE -N $KERNEL -s
288 echo
289
290 echo "------------------------------------------------------------------------"
291 echo "iostat"
292 echo
293 iostat -M $VMCORE -N $KERNEL
294 echo
295
296 echo "------------------------------------------------------------------------"
297 echo "ipcs -a"
298 echo
299 ipcs -C $VMCORE -N $KERNEL -a
300 echo
301
302 echo "------------------------------------------------------------------------"
303 echo "ipcs -T"
304 echo
305 ipcs -C $VMCORE -N $KERNEL -T
306 echo
307
308 # XXX: This doesn't actually work in 5.x+
309 if false; then
310 echo "------------------------------------------------------------------------"
311 echo "w -dn"
312 echo
313 w -M $VMCORE -N $KERNEL -dn
314 echo
315 fi
316
317 echo "------------------------------------------------------------------------"
318 echo "netstat -s"
319 echo
320 netstat -M $VMCORE -N $KERNEL -s
321 echo
322
323 echo "------------------------------------------------------------------------"
324 echo "netstat -m"
325 echo
326 netstat -M $VMCORE -N $KERNEL -m
327 echo
328
329 echo "------------------------------------------------------------------------"
330 echo "netstat -anA"
331 echo
332 netstat -M $VMCORE -N $KERNEL -anA
333 echo
334
335 echo "------------------------------------------------------------------------"
336 echo "netstat -aL"
337 echo
338 netstat -M $VMCORE -N $KERNEL -aL
339 echo
340
341 echo "------------------------------------------------------------------------"
342 echo "fstat"
343 echo
344 fstat -M $VMCORE -N $KERNEL
345 echo
346
347 echo "------------------------------------------------------------------------"
348 echo "dmesg"
349 echo
350 dmesg -a -M $VMCORE -N $KERNEL
351 echo
352
353 echo "------------------------------------------------------------------------"
354 echo "kernel config"
355 echo
356 config -x $KERNEL
357
358 echo
359 echo "------------------------------------------------------------------------"
360 echo "ddb capture buffer"
361 echo
362
363 ddb capture -M $VMCORE -N $KERNEL print