blob: 165e11e80c77bd20f069cc7f7179e28222025d60 [file] [log] [blame]
Jayanth Othayoth5ce15502017-10-16 00:02:44 -05001#! /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"
Marri Devender Rao0deb2872018-11-12 07:45:54 -060046declare -rx TYPE_CHECKSTOP="checkstop"
Jayanth Othayoth5ce15502017-10-16 00:02:44 -050047declare -rx SUMMARY_LOG="summary.log"
48declare -rx DREPORT_LOG="dreport.log"
49declare -rx TMP_DIR="/tmp"
50declare -rx EPOCHTIME=$(date +"%s")
51declare -rx TIME_STAMP="date -u"
52declare -rx PLUGIN="pl_"
53declare -rx DREPORT_SOURCE="/usr/share/dreport.d"
54declare -rx DREPORT_INCLUDE="$DREPORT_SOURCE/include.d"
Jayanth Othayothaa146d62018-01-08 06:57:53 -060055declare -rx ZERO="0"
56declare -rx JOURNAL_LINE_LIMIT="500"
Jayanth Othayoth5ce15502017-10-16 00:02:44 -050057
58#Error Codes
59declare -rx SUCCESS="0"
60declare -rx INTERNAL_FAILURE="1"
61declare -rx RESOURCE_UNAVAILABLE="2"
62
63#VARIABLES
64declare -x name=""
65declare -x dump_dir="/tmp"
66declare -x dump_id="00000000"
67declare -x dump_type=$TYPE_USER
68declare -x verbose=$FALSE
69declare -x quiet=$FALSE
70declare -x dump_size="unlimited"
71declare -x name_dir=""
72declare -x optional_path=""
73declare -x dreport_log=""
74declare -x summary_log=""
75declare -x cur_dump_size=0
Jayanth Othayothaa146d62018-01-08 06:57:53 -060076declare -x pid=$ZERO
Jayanth Othayoth5ce15502017-10-16 00:02:44 -050077declare -x elog_id=""
78
79#Source dreport common functions
80. $DREPORT_INCLUDE/functions
81
82# @brief Initiate data collection based on the type.
83# @return 0 on success, error code otherwise
84function collect_data()
85{
86 case $dump_type in
87 $TYPE_USER)
88 ;;
89 $TYPE_CORE)
90 log_summary "Core: $optional_path"
91 set_core_pid
92 ;;
93 $TYPE_ELOG)
94 log_summary "ELOG: $optional_path"
95 elog_id=$(basename "$optional_path")
96 set_elog_pid
97 ;;
Marri Devender Rao0deb2872018-11-12 07:45:54 -060098 $TYPE_CHECKSTOP)
99 log_summary "CHECKSTOP: $optional_path"
100 elog_id=$(basename "$optional_path")
101 set_elog_pid
102 ;;
Jayanth Othayoth5ce15502017-10-16 00:02:44 -0500103
104 $SUMMARY_DUMP)
105 #No data collection is required.
106 return
107 ;;
108 *) # unknown option
109 log_error "Skipping: Unknown dump type: $dump_type"
110 return
111 ;;
112 esac
113
114 plugin_path=$DREPORT_SOURCE/$PLUGIN$dump_type.d
115
116 # check plugin directory for this dump type?
117 if [ ! -d $plugin_path ]; then
118 log_error "$plugin_path does not exist, skipping dump collection"
119 return 0
120 fi
121
122 #Executes plugins based on the type.
123 for i in $plugin_path/* ; do
124 $i
125 done
126}
127
128# @brief set pid by reading information from the optional path.
129# dreport "core" type user provides core file as optional path parameter.
130# As per coredump source code systemd-coredump uses below format
131# https://github.com/systemd/systemd/blob/master/src/coredump/coredump.c
132# /var/lib/systemd/coredump/core.%s.%s." SD_ID128_FORMAT_STR “.
133# <process ID>.%s000000"
134function set_core_pid()
135{
136 #Escape bash characters in file name
137 file=$(printf %q "$optional_path")
138
139 #matching systemd-coredump core file format.
140 pid=$(echo $file | awk -F . '{ print $5}')
141}
142
143# @brief set elog pid by reading _PID information from the elog d-bus object.
144# _PID information is stored elog Additional data field
145# Data format "_PID=<pid>"
146function set_elog_pid()
147{
148 additional_data=$(busctl get-property xyz.openbmc_project.Logging \
149 $optional_path \
150 xyz.openbmc_project.Logging.Entry \
151 AdditionalData)
152
153 #read _PID data.
154 if [ ! -z "$additional_data" ]; then
155 pid=$(echo $additional_data | \
156 awk -F _PID= '{ print ($2+0)}')
157 fi
158}
159
160# @brief Initial version of the summary log
161init_summary()
162{
163 log_summary "Name: $name.tar.xz"
164 log_summary "Epochtime: $EPOCHTIME"
165 log_summary "ID: $dump_id"
166 log_summary "Type: $dump_type"
167}
168
169# @brief Check the validity of user inputs and initialize global
170# variables. Create directory for temporary data collection
171# @return 0 on success, error code otherwise
172
173function initialize()
174{
175 #Dump file name
176 if [ -z $name ]; then
177 name=$"obmcdump_"$dump_id"_$EPOCHTIME"
178 fi
179
180 #Create temporary data directory.
181 mkdir -p "$TMP_DIR/$name"
182 if [ $? -ne 0 ]; then
183 echo "Error: Failed to create the temporary directory."
184 return $RESOURCE_UNAVAILABLE;
185 fi
186
187 #name directory
188 name_dir="$TMP_DIR/$name"
189
190 #dreport log file
191 dreport_log="$name_dir/$DREPORT_LOG"
192
193 #summary log file
194 summary_log="$name_dir/$SUMMARY_LOG"
195
196 #Type
Dhruvaraj Subhashchandranfdc0c3a2020-09-14 01:38:27 -0500197 if [[ ! ($dump_type = $TYPE_USER || \
198 $dump_type = $TYPE_CORE || \
199 $dump_type = $TYPE_ELOG || \
200 $dump_type = $TYPE_CHECKSTOP) ]]; then
Jayanth Othayoth5ce15502017-10-16 00:02:44 -0500201 log_error "Invalid -type, Only summary log is available"
202 dump_type=$SUMMARY_DUMP
203 fi
204
205 #Size
206 #Check the input is integer.
207 if [ "$dump_size" -eq "$dump_size" ] 2>/dev/null; then
208 #Converts in to bytes.
209 dump_size="$((dump_size * 1024))"
210 else
211 dump_size=$UNLIMITED
212 fi
213
214 return $SUCCESS
215}
216
217# @brief Packaging the dump and transferring to dump location.
218function package()
219{
220 mkdir -p "$dump_dir"
221 if [ $? -ne 0 ]; then
222 log_error "Could not create the destination directory $dump_dir"
223 dest_dir=$TMP_DIR
224 fi
225
226 #tar and compress the files.
227 tar -Jcf "$name_dir.tar.xz" -C \
228 $(dirname "$name_dir") $(basename "$name_dir")
229
230 if [ $? -ne 0 ]; then
231 echo $($TIME_STAMP) "Could not create the compressed tar file"
232 rm -r "$name_dir"
233 return $INTERNAL_FAILURE
234 fi
235
236 #remove the temporary name specific directory
237 rm -r "$name_dir"
238
239 echo $($TIME_STAMP) "Report is available in $dump_dir"
240
Chirag Sharmaa63f4a62020-07-13 06:14:22 -0500241 if [ "$TMP_DIR" == "$dump_dir" ] || [ "$TMP_DIR/" == "$dump_dir" ]; then
Jayanth Othayoth5ce15502017-10-16 00:02:44 -0500242 return $SUCCESS
243 fi
244
245 #copy the compressed tar file into the destination
246 cp "$name_dir.tar.xz" "$dump_dir"
247 if [ $? -ne 0 ]; then
248 echo "Failed to copy the $name_dir.tar.xz to $dump_dir"
249 rm "$name_dir.tar.xz"
250 return $INTERNAL_FAILURE
251 fi
252
253 #Remove the temporary copy of the file
254 rm "$name_dir.tar.xz"
255}
256
257# @brief Main function
258function main()
259{
260 #initialize the global variables and
261 #create temporary storage locations
262 initialize
263 result=$?
264 if [[ ${result} -ne $SUCCESS ]]; then
265 echo $($TIME_STAMP) "Error: Failed to initialize, Exiting"
266 exit;
267 fi
268
Gunnar Mills95a72982017-10-25 17:00:14 -0500269 #Initialize the summary log
Jayanth Othayoth5ce15502017-10-16 00:02:44 -0500270 init_summary
271
272 #collect data based on the type.
273 collect_data
274
275 package #package the dump
276 result=$?
277 if [[ ${result} -ne $SUCCESS ]]; then
278 echo $($TIME_STAMP) "Error: Failed to package, Exiting"
279 else
Gunnar Mills95a72982017-10-25 17:00:14 -0500280 echo $($TIME_STAMP) "Successfully completed"
Jayanth Othayoth5ce15502017-10-16 00:02:44 -0500281 exit;
282 fi
283}
284
285TEMP=`getopt -o n:d:i:t:s:p:vVqh \
286 --long name:,dir:,dumpid:,type:,size:,path:,verbose,version,quiet,help \
287 -- "$@"`
288
289if [ $? -ne 0 ]
290then
291 echo "Error: Invalid options"
292 exit 1
293fi
294
295eval set -- "$TEMP"
296
297while [[ $# -gt 1 ]]; do
298 key="$1"
299 case $key in
300 -n|--name)
301 name=$2
302 shift 2;;
303 -d|--dir)
304 dump_dir=$2
305 shift 2;;
306 -i|--dumpid)
307 dump_id=$2
308 shift 2;;
309 -t|--type)
310 dump_type=$2
311 shift 2;;
312 -s|--size)
313 dump_size=$2
314 shift 2;;
315 -p|--path)
316 optional_path=$2
317 shift 2;;
318 -v|—-verbose)
319 verbose=$TRUE
320 shift;;
321 -V|--version)
322 shift;;
323 -q|—-quiet)
324 quiet=$TRUE
325 shift;;
326 -h|--help)
327 echo "$help"
328 exit;;
329 *) # unknown option
330 log_error "Unknown argument: $1"
331 log_info "$help"
332 exit 1;;
333 esac
334done
335
336main #main program
337exit $?