#!/bin/bash # collect_updatelogs: collect MDT updatelog files on live server node. # # This tool retrieves updatelogs from live server for further analysis # # Tool does the following: # - get update_log catlist using debugfs to find per-MDT update catalog FIDs # - get llog catalogs according with that list # - optionally get everything else from update_log_dir # # Script requires parameter is physical device of MDT server # # Script saves updatelog with prefixes 'catlog' to identify them # easily # PROG=$(basename $0) LLOG_READER=${LLOG_READER:-llog_reader} DEBUGFS=${DEBUGFS:-debugfs} usage() { cat -- <&2 usage: collect_updatelog [--help|-h] [--mdt|-m indices] [--path|-p ]\n --help|-h show this usage message --mdt|-m get llogs of selected MDTs only --path|-p save all llogs into directory by given path The 'mdt_device' argument should be physical MDT device being mounted. Examples: collect_updatelog /dev/sda1 collect_updatelog -p /tmp/llogs_mdt0 /dev/sda1 collect_updatelog -m 0,1 /dev/sda1 USAGE exit 1 } OPT_PATH="./" OPT_DEV="" OPT_MDTS=() OPT_MDTIDX=() # Examine any long options and arguments while [ -n "$*" ]; do arg="$1" case "$arg" in -h|--help) usage;; -m|--mdt) OPT_MDTIDX=($(echo $2 | tr "," " "));; -p|--path) OPT_PATH="$2"; shift;; *) [ -e "$arg" ] && OPT_DEV="$arg" && break esac shift done collect_updatelog() { local mdt_dev=$OPT_DEV local dest=$OPT_PATH local catlist=${dest}/update_log local llogdir=${dest}/update_log_dir local length=0 if [[ ! $(which $DEBUGFS 2>/dev/null) ]] ; then echo "$PROG: $DEBUGFS is missing." exit 1 fi mkdir -p $llogdir || exit 1 $DEBUGFS -c -R "dump update_log $catlist" $mdt_dev if [[ ! -f $catlist ]] ; then echo "$PROG: $catlist wasn't retrieved" else read -r -d '' -a OPT_MDTS <<< $(hexdump -v -e '2/8 " %16x" 2/8 "\n"' $catlist | awk '{print "[0x"$2":0x"$1":0x0]"}') length=${#OPT_MDTS[@]} (( ${#OPT_MDTIDX[@]} > 0 )) || OPT_MDTIDX=($(seq 0 $((length - 1)))) echo "Selected MDTS: ${OPT_MDTIDX[*]}" for i in ${OPT_MDTIDX[@]} ; do local catfid=${OPT_MDTS[$i]} local dstcat=$llogdir/catlog$i.$catfid local dstdir=$llogdir/catlog${i}_llogs if (( $i >= $length)) ; then echo "skip wrong index $i, total $length MDTs" continue fi echo "Getting MDT$i llog catalog $catfid to $dstcat" $DEBUGFS -c -R "dump update_log_dir/$catfid $dstcat" $mdt_dev if [[ ! -f $dstcat ]] ; then echo "$PROG: llog catalog #$i wasn't received." continue fi if [[ ! $(which $LLOG_READER 2>/dev/null) ]] ; then echo "$PROG: no $LLOG_READER, skip plain llogs" continue fi if (( $(stat -c %s $dstcat) >= 8192 )) ; then mkdir -p $dstdir while read -r plain ; do local dstplain=$dstdir/${plain##*/} echo "Save $plain to $dstplain" $DEBUGFS -c -R "dump $plain $dstplain" $mdt_dev done < <(llog_reader $dstcat | awk -F "path=" '/path=/ { print $2 }') else echo "$PROG: $dstcat is too small." fi done fi } if [ -z $OPT_DEV ] ; then echo "Mount is not specified, exiting" exit 1 fi collect_updatelog