1#! /bin/bash 2 3help=$" 4 dreport creates an archive(xz compressed) consisting of the following: 5 * Configuration information 6 * Debug information 7 * A summary report 8 The type parameter controls the content of the data. The generated 9 archive is stored in the user specified location. 10 11usage: dreport [OPTION] 12 13Options: 14 -n, —-name <name> Name to be used for the archive. 15 Default name format obmcdump_<id>_<epochtime> 16 -d, —-dir <directory> Archive directory to copy the compressed report. 17 Default output directory is /tmp 18 -i, —-id <id> Dump identifier to associate with the archive. 19 Identifiers include numeric characters. 20 Default dump identifier is 0 21 -t, —-type <type> Data collection type. Valid types are 22 "user", "core", "elog". 23 Default type is "user" initiated. 24 -p, —-path <path> Optional contents to be included in the archive. 25 Valid paths are absolute file path or d-bus path 26 based on type parameter. 27 -Absolute file path for "core" type. 28 -elog d-bus object for "elog" type. 29 -s, --size <size> Maximum allowed size(in KB) of the archive. 30 Report will be truncated in case size exceeds 31 this limit. Default size is unlimited. 32 -v, —-verbose Increase logging verbosity. 33 -V, --version Output version information. 34 -q, —-quiet Only log fatal errors to stderr 35 -h, —-help Display this help and exit. 36" 37 38#CONSTANTS 39declare -rx TRUE=1 40declare -rx FALSE=0 41declare -rx UNLIMITED="unlimited" 42declare -rx SUMMARY_DUMP="summary" 43declare -rx TYPE_USER="user" 44declare -rx TYPE_CORE="core" 45declare -rx TYPE_ELOG="elog" 46declare -rx SUMMARY_LOG="summary.log" 47declare -rx DREPORT_LOG="dreport.log" 48declare -rx TMP_DIR="/tmp" 49declare -rx EPOCHTIME=$(date +"%s") 50declare -rx TIME_STAMP="date -u" 51declare -rx PLUGIN="pl_" 52declare -rx DREPORT_SOURCE="/usr/share/dreport.d" 53declare -rx DREPORT_INCLUDE="$DREPORT_SOURCE/include.d" 54declare -rx ZERO="0" 55declare -rx JOURNAL_LINE_LIMIT="500" 56 57#Error Codes 58declare -rx SUCCESS="0" 59declare -rx INTERNAL_FAILURE="1" 60declare -rx RESOURCE_UNAVAILABLE="2" 61 62#VARIABLES 63declare -x name="" 64declare -x dump_dir="/tmp" 65declare -x dump_id="00000000" 66declare -x dump_type=$TYPE_USER 67declare -x verbose=$FALSE 68declare -x quiet=$FALSE 69declare -x dump_size="unlimited" 70declare -x name_dir="" 71declare -x optional_path="" 72declare -x dreport_log="" 73declare -x summary_log="" 74declare -x cur_dump_size=0 75declare -x pid=$ZERO 76declare -x elog_id="" 77 78#Source dreport common functions 79. $DREPORT_INCLUDE/functions 80 81# @brief Initiate data collection based on the type. 82# @return 0 on success, error code otherwise 83function collect_data() 84{ 85 case $dump_type in 86 $TYPE_USER) 87 ;; 88 $TYPE_CORE) 89 log_summary "Core: $optional_path" 90 set_core_pid 91 ;; 92 $TYPE_ELOG) 93 log_summary "ELOG: $optional_path" 94 elog_id=$(basename "$optional_path") 95 set_elog_pid 96 ;; 97 98 $SUMMARY_DUMP) 99 #No data collection is required. 100 return 101 ;; 102 *) # unknown option 103 log_error "Skipping: Unknown dump type: $dump_type" 104 return 105 ;; 106 esac 107 108 plugin_path=$DREPORT_SOURCE/$PLUGIN$dump_type.d 109 110 # check plugin directory for this dump type? 111 if [ ! -d $plugin_path ]; then 112 log_error "$plugin_path does not exist, skipping dump collection" 113 return 0 114 fi 115 116 #Executes plugins based on the type. 117 for i in $plugin_path/* ; do 118 $i 119 done 120} 121 122# @brief set pid by reading information from the optional path. 123# dreport "core" type user provides core file as optional path parameter. 124# As per coredump source code systemd-coredump uses below format 125# https://github.com/systemd/systemd/blob/master/src/coredump/coredump.c 126# /var/lib/systemd/coredump/core.%s.%s." SD_ID128_FORMAT_STR “. 127# <process ID>.%s000000" 128function set_core_pid() 129{ 130 #Escape bash characters in file name 131 file=$(printf %q "$optional_path") 132 133 #matching systemd-coredump core file format. 134 pid=$(echo $file | awk -F . '{ print $5}') 135} 136 137# @brief set elog pid by reading _PID information from the elog d-bus object. 138# _PID information is stored elog Additional data field 139# Data format "_PID=<pid>" 140function set_elog_pid() 141{ 142 additional_data=$(busctl get-property xyz.openbmc_project.Logging \ 143 $optional_path \ 144 xyz.openbmc_project.Logging.Entry \ 145 AdditionalData) 146 147 #read _PID data. 148 if [ ! -z "$additional_data" ]; then 149 pid=$(echo $additional_data | \ 150 awk -F _PID= '{ print ($2+0)}') 151 fi 152} 153 154# @brief Initial version of the summary log 155init_summary() 156{ 157 log_summary "Name: $name.tar.xz" 158 log_summary "Epochtime: $EPOCHTIME" 159 log_summary "ID: $dump_id" 160 log_summary "Type: $dump_type" 161} 162 163# @brief Check the validity of user inputs and initialize global 164# variables. Create directory for temporary data collection 165# @return 0 on success, error code otherwise 166 167function initialize() 168{ 169 #Dump file name 170 if [ -z $name ]; then 171 name=$"obmcdump_"$dump_id"_$EPOCHTIME" 172 fi 173 174 #Create temporary data directory. 175 mkdir -p "$TMP_DIR/$name" 176 if [ $? -ne 0 ]; then 177 echo "Error: Failed to create the temporary directory." 178 return $RESOURCE_UNAVAILABLE; 179 fi 180 181 #name directory 182 name_dir="$TMP_DIR/$name" 183 184 #dreport log file 185 dreport_log="$name_dir/$DREPORT_LOG" 186 187 #summary log file 188 summary_log="$name_dir/$SUMMARY_LOG" 189 190 #Type 191 if [[ !($dump_type = $TYPE_USER || \ 192 $dump_type = $TYPE_CORE || \ 193 $dump_type = $TYPE_ELOG) ]]; then 194 log_error "Invalid -type, Only summary log is available" 195 dump_type=$SUMMARY_DUMP 196 fi 197 198 #Size 199 #Check the input is integer. 200 if [ "$dump_size" -eq "$dump_size" ] 2>/dev/null; then 201 #Converts in to bytes. 202 dump_size="$((dump_size * 1024))" 203 else 204 dump_size=$UNLIMITED 205 fi 206 207 return $SUCCESS 208} 209 210# @brief Packaging the dump and transferring to dump location. 211function package() 212{ 213 mkdir -p "$dump_dir" 214 if [ $? -ne 0 ]; then 215 log_error "Could not create the destination directory $dump_dir" 216 dest_dir=$TMP_DIR 217 fi 218 219 #tar and compress the files. 220 tar -Jcf "$name_dir.tar.xz" -C \ 221 $(dirname "$name_dir") $(basename "$name_dir") 222 223 if [ $? -ne 0 ]; then 224 echo $($TIME_STAMP) "Could not create the compressed tar file" 225 rm -r "$name_dir" 226 return $INTERNAL_FAILURE 227 fi 228 229 #remove the temporary name specific directory 230 rm -r "$name_dir" 231 232 echo $($TIME_STAMP) "Report is available in $dump_dir" 233 234 if [ "$TMP_DIR" == "$dump_dir" ]; then 235 return $SUCCESS 236 fi 237 238 #copy the compressed tar file into the destination 239 cp "$name_dir.tar.xz" "$dump_dir" 240 if [ $? -ne 0 ]; then 241 echo "Failed to copy the $name_dir.tar.xz to $dump_dir" 242 rm "$name_dir.tar.xz" 243 return $INTERNAL_FAILURE 244 fi 245 246 #Remove the temporary copy of the file 247 rm "$name_dir.tar.xz" 248} 249 250# @brief Main function 251function main() 252{ 253 #initialize the global variables and 254 #create temporary storage locations 255 initialize 256 result=$? 257 if [[ ${result} -ne $SUCCESS ]]; then 258 echo $($TIME_STAMP) "Error: Failed to initialize, Exiting" 259 exit; 260 fi 261 262 #Initialize the summary log 263 init_summary 264 265 #collect data based on the type. 266 collect_data 267 268 package #package the dump 269 result=$? 270 if [[ ${result} -ne $SUCCESS ]]; then 271 echo $($TIME_STAMP) "Error: Failed to package, Exiting" 272 else 273 echo $($TIME_STAMP) "Successfully completed" 274 exit; 275 fi 276} 277 278TEMP=`getopt -o n:d:i:t:s:p:vVqh \ 279 --long name:,dir:,dumpid:,type:,size:,path:,verbose,version,quiet,help \ 280 -- "$@"` 281 282if [ $? -ne 0 ] 283then 284 echo "Error: Invalid options" 285 exit 1 286fi 287 288eval set -- "$TEMP" 289 290while [[ $# -gt 1 ]]; do 291 key="$1" 292 case $key in 293 -n|--name) 294 name=$2 295 shift 2;; 296 -d|--dir) 297 dump_dir=$2 298 shift 2;; 299 -i|--dumpid) 300 dump_id=$2 301 shift 2;; 302 -t|--type) 303 dump_type=$2 304 shift 2;; 305 -s|--size) 306 dump_size=$2 307 shift 2;; 308 -p|--path) 309 optional_path=$2 310 shift 2;; 311 -v|—-verbose) 312 verbose=$TRUE 313 shift;; 314 -V|--version) 315 shift;; 316 -q|—-quiet) 317 quiet=$TRUE 318 shift;; 319 -h|--help) 320 echo "$help" 321 exit;; 322 *) # unknown option 323 log_error "Unknown argument: $1" 324 log_info "$help" 325 exit 1;; 326 esac 327done 328 329main #main program 330exit $? 331