diff --git a/tools/crm_report.in b/tools/crm_report.in index 6060463422..842d6ae927 100644 --- a/tools/crm_report.in +++ b/tools/crm_report.in @@ -1,408 +1,406 @@ #!/bin/sh # # Copyright 2010-2025 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # TEMP=`@GETOPT_PATH@ \ -o hv?xl:f:t:n:L:p:c:dSCu:D:MVse: \ --long help,corosync,dest:,node:,nodes:,from:,to:,sos-mode,logfile:,as-directory,single-node,cluster:,user:,max-depth:,version,features,rsh: \ -n 'crm_report' -- "$@"` # The quotes around $TEMP are essential eval set -- "$TEMP" progname=$(basename "$0") rsh="ssh -T" nodes="" compress=1 cluster="any" ssh_user="root" search_logs=1 sos_mode=0 report_data=`dirname $0` maxdepth=5 extra_logs="" sanitize_patterns="passw.*" log_patterns="CRIT: ERROR:" usage() { cat< "$l_base/$HALOG_F" fi for node in $nodes; do cat <$l_base/.env LABEL="$label" REPORT_HOME="$r_base" REPORT_MASTER="$host" REPORT_TARGET="$node" LOG_START=$start LOG_END=$end REMOVE=1 SANITIZE="$sanitize_patterns" CLUSTER=$cluster LOG_PATTERNS="$log_patterns" EXTRA_LOGS="$extra_logs" SEARCH_LOGS=$search_logs SOS_MODE=$sos_mode verbose=$verbose maxdepth=$maxdepth EOF if [ $host = $node ]; then cat <>$l_base/.env REPORT_HOME="$l_base" EOF cat $l_base/.env $report_data/report.common $report_data/report.collector > $l_base/collector bash $l_base/collector else cat $l_base/.env $report_data/report.common $report_data/report.collector \ | $rsh -l $ssh_user $node -- "mkdir -p $r_base; cat > $r_base/collector; bash $r_base/collector" | (cd $l_base && tar mxf -) fi done analyze $l_base > $l_base/$ANALYSIS_F if [ -f $l_base/$HALOG_F ]; then node_events $l_base/$HALOG_F > $l_base/$EVENTS_F fi for node in $nodes; do cat $l_base/$node/$ANALYSIS_F >> $l_base/$ANALYSIS_F if [ -s $l_base/$node/$EVENTS_F ]; then cat $l_base/$node/$EVENTS_F >> $l_base/$EVENTS_F elif [ -s $l_base/$HALOG_F ]; then awk "\$4==\"$nodes\"" $l_base/$EVENTS_F >> $l_base/$n/$EVENTS_F fi done log " " if [ $compress = 1 ]; then fname=`shrink $l_base` rm -rf $l_base log "Collected results are available in $fname" log " " log "Please create a bug entry at" log " @BUG_URL@" log "Include a description of your problem and attach this tarball" log " " log "Thank you for taking time to create this report." else log "Collected results are available in $l_base" fi log " " } # # check if files have same content in the cluster # cibdiff() { d1=$(dirname $1) d2=$(dirname $2) if [ -f "$d1/RUNNING" ] && [ ! -f "$d2/RUNNING" ]; then DIFF_OK=0 elif [ -f "$d1/STOPPED" ] && [ ! -f "$d2/STOPPED" ]; then DIFF_OK=0 else DIFF_OK=1 fi if [ $DIFF_OK -eq 1 ]; then if which crm_diff > /dev/null 2>&1; then crm_diff -c -n $1 -o $2 else info "crm_diff(8) not found, cannot diff CIBs" fi else echo "can't compare cibs from running and stopped systems" fi } diffcheck() { [ -f "$1" ] || { echo "$1 does not exist" return 1 } [ -f "$2" ] || { echo "$2 does not exist" return 1 } case $(basename "$1") in $CIB_F) cibdiff $1 $2 ;; *) diff -u $1 $2 ;; esac } # # remove duplicates if files are same, make links instead # consolidate() { for n in $nodes; do if [ -f $1/$2 ]; then rm $1/$n/$2 else mv $1/$n/$2 $1 fi ln -s ../$2 $1/$n done } analyze_one() { rc=0 node0="" for n in $nodes; do if [ "$node0" ]; then diffcheck $1/$node0/$2 $1/$n/$2 rc=$(($rc+$?)) else node0=$n fi done return $rc } analyze() { flist="$MEMBERSHIP_F $CIB_F $CRM_MON_F $SYSINFO_F" for f in $flist; do printf "Diff $f... " ls $1/*/$f >/dev/null 2>&1 || { echo "no $1/*/$f :/" continue } if analyze_one $1 $f; then echo "OK" [ "$f" != $CIB_F ] && consolidate $1 $f else echo "" fi done } node_names_from_xml() { awk ' /uname/ { for( i=1; i<=NF; i++ ) if( $i~/^uname=/ ) { sub("uname=.","",$i); sub("\".*","",$i); print $i; next; } } ' | tr '\n' ' ' } getnodes() { cluster="$1" # 1. Live (cluster nodes or Pacemaker Remote nodes) # TODO: This will not detect Pacemaker Remote nodes unless they # have ever had a permanent node attribute set, because it only # searches the nodes section. It should also search the config # for resources that create Pacemaker Remote nodes. cib_nodes=$(cibadmin -Q -o nodes 2>/dev/null) if [ $? -eq 0 ]; then debug "Querying CIB for nodes" echo "$cib_nodes" | node_names_from_xml return fi # 2. Saved if [ -f "@CRM_CONFIG_DIR@/cib.xml" ]; then debug "Querying on-disk CIB for nodes" grep "node " "@CRM_CONFIG_DIR@/cib.xml" | node_names_from_xml return fi # 3. logs # TODO: Look for something like crm_update_peer } if [ $compress -eq 1 ]; then require_tar fi -if [ "x$start_time" != "x" ]; then - masterlog="" - - if [ -z "$sanitize_patterns" ]; then - log "WARNING: The tarball produced by this program may contain" - log " sensitive information such as passwords." - log "" - log "We will attempt to remove such information if you use the" - log "-p option. For example: -p \"pass.*\" -p \"user.*\"" - log "" - log "However, doing this may reduce the ability for the recipients" - log "to diagnose issues and generally provide assistance." - log "" - log "IT IS YOUR RESPONSIBILITY TO PROTECT SENSITIVE DATA FROM EXPOSURE" - log "" - fi +if [ "x$start_time" = "x" ]; then + fatal "Not sure what to do, no time range to extract" +fi - # If user didn't specify a cluster stack, make a best guess if possible. - if [ -z "$cluster" ] || [ "$cluster" = "any" ]; then - cluster=$(get_cluster_type) - fi +masterlog="" + +if [ -z "$sanitize_patterns" ]; then + log "WARNING: The tarball produced by this program may contain" + log " sensitive information such as passwords." + log "" + log "We will attempt to remove such information if you use the" + log "-p option. For example: -p \"pass.*\" -p \"user.*\"" + log "" + log "However, doing this may reduce the ability for the recipients" + log "to diagnose issues and generally provide assistance." + log "" + log "IT IS YOUR RESPONSIBILITY TO PROTECT SENSITIVE DATA FROM EXPOSURE" + log "" +fi - # If user didn't specify node(s), make a best guess if possible. - if [ -z "$nodes" ]; then - nodes=`getnodes $cluster` - if [ -n "$nodes" ]; then - log "Calculated node list: $nodes" - else - fatal "Cannot determine nodes; specify --nodes or --single-node" - fi - fi +# If user didn't specify a cluster stack, make a best guess if possible. +if [ -z "$cluster" ] || [ "$cluster" = "any" ]; then + cluster=$(get_cluster_type) +fi - if - echo $nodes | grep -qs $host - then - debug "We are a cluster node" +# If user didn't specify node(s), make a best guess if possible. +if [ -z "$nodes" ]; then + nodes=`getnodes $cluster` + if [ -n "$nodes" ]; then + log "Calculated node list: $nodes" else - debug "We are a log master" - masterlog=`findmsg 1 "pacemaker-controld\\|CTS"` + fatal "Cannot determine nodes; specify --nodes or --single-node" fi +fi - - if [ -z $end_time ]; then - end_time=`perl -e 'print time()'` - fi - label="pcmk-`date +"%a-%d-%b-%Y"`" - log "Collecting data from $nodes (`time2str $start_time` to `time2str $end_time`)" - collect_data $label $start_time $end_time $masterlog +if echo $nodes | grep -qs $host; then + debug "We are a cluster node" else - fatal "Not sure what to do, no time range to extract" + debug "We are a log master" + masterlog=`findmsg 1 "pacemaker-controld\\|CTS"` fi +if [ -z $end_time ]; then + end_time=`perl -e 'print time()'` +fi + +label="pcmk-`date +"%a-%d-%b-%Y"`" +log "Collecting data from $nodes (`time2str $start_time` to `time2str $end_time`)" +collect_data $label $start_time $end_time $masterlog + # vim: set filetype=sh: