blob: 7fc1c32ac65f9f20fb1ef80564f7896977529fd7 [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"
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"
Jayanth Othayothaa146d62018-01-08 06:57:53 -060054declare -rx ZERO="0"
55declare -rx JOURNAL_LINE_LIMIT="500"
Jayanth Othayoth5ce15502017-10-16 00:02:44 -050056
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
Jayanth Othayothaa146d62018-01-08 06:57:53 -060075declare -x pid=$ZERO
Jayanth Othayoth5ce15502017-10-16 00:02:44 -050076declare -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
Gunnar Mills95a72982017-10-25 17:00:14 -0500262 #Initialize the summary log
Jayanth Othayoth5ce15502017-10-16 00:02:44 -0500263 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
Gunnar Mills95a72982017-10-25 17:00:14 -0500273 echo $($TIME_STAMP) "Successfully completed"
Jayanth Othayoth5ce15502017-10-16 00:02:44 -0500274 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 $?