slitaz-dev-tools view libtaz/libtaz-modules/report @ rev 107

tazwiki: list uploaded files
author Pascal Bellard <pascal.bellard@slitaz.org>
date Wed Jun 01 21:21:06 2011 +0200 (2011-06-01)
parents 81157fb10757
children b571aa2a37b0
line source
2 # Usage : use_report functions/commands
3 # 'use_report' execute functions/commands and redirect the output.
4 # You can use 'report' function to display messages, steps, blocs and
5 # status in the terminal and organize the display of the log.
7 report_verbosity_opt=all
9 report_display()
10 {
11 while read out; do
12 [ "$out" = €øß ] && report_stop_display && return
13 echo -e " ...\n ~~~~~~~~~~~~~~~~~~~~ Messages ~~~~~~~~~~~~~~~~~~~~ "
14 echo "$out"
15 break
16 done
17 while read out; do
18 [ "$out" = €øß ] && report_stop_display && return
19 echo "$out"
20 done
21 }
23 report_create_html()
24 {
25 if ! [ -f "$log_opt" ]; then
26 mkdir -p "${log_opt%/*}"
27 cp /usr/share/slitaz/web/template.html "$log_opt"
28 sed -e "s/xml:lang=\"us\" lang=\"us\"/xml:lang=\"${LANG%%_*}\" lang=\"${LANG%%_*}\"/" \
29 -e "s~Title of the page~SliTaz GNU/Linux - Log: $0~" \
30 -e "s~Second Title~Log: $0~" -i "$log_opt"
31 echo '<div id="report">' >> "$log_opt"
32 else
33 sed 's~</div></body></html>~~' -i "$log_opt"
34 fi
36 echo -e "<h1>$(basename "$log_command")</h1>\n<em>$(date)</em>" >> "$log_opt"
37 [ -L "${log_opt%/*}/web" ] || ln -s /usr/share/slitaz/web "${log_opt%/*}/web"
38 }
40 report_start()
41 {
42 # Create the temporary directory if needed.
43 ! [ -d /tmp/libtaz/ ] && mkdir -p /tmp/libtaz
44 ! [ -d $SLITAZ_LOG ] && mkdir -p $SLITAZ_LOG
46 # Give permissions to all users if user is root.
47 if test $(id -u) = 0 ; then
48 chmod 777 /tmp/libtaz
49 chmod -R 777 $SLITAZ_LOG
50 fi
52 # Get a random logfile name.
53 if [ "$report_pid" ]; then
54 log_tmp=/tmp/libtaz/$report_pid
55 embeded_mode=enabled
56 initial_bloc_level=$bloc_level
57 if [ "$open_bloc" ]; then
58 initial_bloc_level=$(($bloc_level+1))
59 embeded_open_bloc=yes
60 fi
61 if [ -p $log_tmp.stdout ] && ! [ "$open_bloc" = yes ]; then
62 report_step_status
63 fi
64 else
65 log_tmp=/tmp/libtaz/$$
66 report_pid=$$
67 fi
69 # Use the default logfile if no logfile was specified by the main script.
70 [ ! "$log_opt" ] && [ "$report_log_all" = yes ] && \
71 log_opt="$SLITAZ_LOG/`basename $0`/$(date -Iseconds).html"
72 export report_pid log_opt
74 #if [ "$embeded_mode" != enabled ]; then
76 # Initialize html logfile if needed, or prepare it to be edited.
77 [ "$log_opt" ] && { [ ! "$embeded_mode" ] || [ ! -f "$log_opt" ]; } && report_create_html
79 echo -n "" > $log_tmp
81 # Initialize named pipes & set I/O redirections.
82 [ "$embeded_mode" ] || exec 3>&1 4>&2
84 # Start debugging if the option is enabled.
85 if [ "$debug_opt" ]; then
86 exec 2>$log_tmp.stdout
87 set -vx
88 echo "[--------------------------/!\ DEBUG MODE ENABLED /!\--------------------------]"
89 fi
91 # Theses variable are used to configure the display of steps in a terminal.
92 bloc1_delimiter="================================================================================"
93 bloc1_display=" "
94 bloc2_delimiter="----------------------------------------------------------------------------"
95 bloc2_display=" > "
96 bloc3_delimiter="* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *"
97 bloc3_display=" * "
99 # Use a trap to exit cleanly if app is killed.
100 trap "report_exit $(basename $0) killed by user" SIGINT SIGTERM
102 # Use another display function if quiet is enabled.
103 [ "$report_verbosity_opt" = "none" ] && report_display()
104 {
105 while read out; do
106 [ "$out" = €øß ] && report_stop_display && return
107 done
108 }
109 }
111 report_stop_display()
112 {
113 rm $log_tmp.stderr $log_tmp.stdout
114 sed '/^€øß$/d' -i $log_tmp
115 touch $log_tmp.end
116 }
118 report_listen()
119 {
120 mkfifo $log_tmp.stderr $log_tmp.stdout
121 {
122 { tee -a $log_tmp $log_tmp.error <$log_tmp.stderr | while read line; do echo -e "\\033[1;31m${line}\\033[0m"; done; }&
123 { tee -a $log_tmp <$log_tmp.stdout; }&
124 } | report_display&
125 usleep 10000
126 exec 1>>$log_tmp.stdout 2>>$log_tmp.stderr
127 }
129 report_stop_listen()
130 {
131 if [ -p $log_tmp.stdout ]; then
132 [ -f $log_tmp.end ] && rm $log_tmp.end
133 usleep 10000 && echo €øß
134 while ! [ -f $log_tmp.end ]; do
135 usleep 10000
136 done
137 exec 1>&3 2>&4
138 rm $log_tmp.end
139 fi
140 }
142 report_stop()
143 {
144 ! [ "$report_pid" ] && exit
145 # End step and close blocs.
146 [ "$step_running" ] && report end-step
147 while [ $(($bloc_level)) -gt $(($initial_bloc_level)) ]; do
148 report close-bloc
149 done
151 if [ "$embeded_mode" = enabled ]; then
152 [ "$bloc_level" ] && echo $(eval echo \$bloc${bloc_level}_status) > $log_tmp.status
153 if [ "$embeded_open_bloc" = opened ]; then
154 touch $log_tmp.eob
155 fi
156 else
157 [ "$log_opt" ] && echo '</div></body></html>' >> "$log_opt"
158 exec 3>&- 4>&-
159 rm -f $log_tmp*
160 unset report_pid log_opt
162 # Stop debugging
163 [ "$debug_opt" ] && set +vx
164 [ "$report_log_all" ] && create_log_index
165 fi
166 }
168 # Use this to stop a program with an error.
169 report_exit()
170 {
171 # Log&display error message.
172 echo -e "$@" >&2
174 # Close step as failed.
175 if [ "$step_running" ]; then
176 (exit 1)
177 report end-step
178 fi
180 # Set blocs as failed, report and exit.
181 bloc1_status="failed"
182 bloc2_status="failed"
183 bloc3_status="failed"
184 report_stop
185 exit 1
186 }
188 # Usage : report [command] [message]
189 #
190 # type :message simply display the message.
191 # step name the step and display status when ended.
192 # end-step display status of the step, it's done automatically when
193 # starting a new step, closing a bloc or stopping a report.
194 # open-bloc open the list of steps in the operation.
195 # close-bloc close the current bloc.
196 report()
197 {
198 # First : get status before it is changed by other commands.
199 check_status=$?
200 case "$1" in
201 start)
202 report_start
203 ;;
204 stop)
205 report_stop
206 ;;
207 exit)
208 shift && report_exit "$@"
209 ;;
210 # TODO : Code displaying a message during a step run.
211 message)
212 shift
213 echo -e "${current_bloc_display}$@"
214 report_message=$(echo "$@" | sed "s~$~<br />~g")
215 [ "$log_opt" ] && echo -e "<div class=\"message\">$report_message</div>" >> "$log_opt"
216 ;;
217 step)
218 [ "$log_step" ] && echo "$2" > $log_step
219 [ "$open_bloc" ] && report_open_bloc
220 [ "$step_running" ] && report_step_status
221 echo -ne "$current_bloc_display$2\\033[70G[ \\033[1;32mR\\033[33mU\\033[31mN\\033[0;39m ]" >&3
222 [ "$log_opt" ] && echo -e "<div class=\"$2\">\n<h$(($bloc_level+2))>$2</h$(($bloc_level+2))>" >> "$log_opt"
223 export step_running="$2"
224 report_listen
225 ;;
226 end-step)
227 if ! [ "$step_running" ]; then
228 report_return_code=$check_status
229 else
230 report_step_status
231 fi
232 ;;
233 open-bloc)
234 export open_bloc=yes
235 ;;
236 close-bloc)
237 if [ -f "$log_tmp.eob" ]; then
238 report_open_bloc
239 check_status=$(cat $log_tmp.status)
240 rm $log_tmp.status
241 report_set_bloc_status
242 elif [ "$step_running" ]; then
243 report_step_status
244 fi
246 # Then close the bloc and report status if it was open.
247 if ! [ "$open_bloc" ]; then
248 export current_bloc_display="$(eval echo \"\$bloc$((${bloc_level}-1))_display\")"
249 [ "$(eval echo \"\$bloc${bloc_level}_delimiter\")" ] && \
250 echo -e "$current_bloc_display$(eval echo \"\$bloc${bloc_level}_delimiter\")" >&3
251 echo -en "$current_bloc_display... $(eval echo \"\$bloc${bloc_level}_running\")" >&3
252 check_status=$(eval echo \$bloc${bloc_level}_status)
253 report_display_status
255 # Set the bloc status in the log file.
256 if [ "$log_opt" ]; then
257 sed "s~<div class=\"bloc_level$bloc_level\">~<div class=\"$check_status\">~" -i "$log_opt"
258 echo "</div>" >> "$log_opt"
259 fi
260 echo "" >&3
261 export bloc_level=$(($bloc_level-1))
262 [ "$bloc_level" = 0 ] && unset bloc_level
263 else
264 unset open_bloc
265 fi
266 ;;
267 sublog)
268 shift
269 ! [ "$log_list" ] && log_list="$log_opt"
270 export log_list="$1 $log_list"
271 export log_opt="$1"
272 report_create_html
273 ;;
274 end-sublog)
275 [ "$log_opt" ] || continue
276 export log_list="${log_list#* }"
277 echo '</div></body></html>' >> "$log_opt"
278 # Grep the summary of sublog (main action + status) and put
279 # it in the main log, plus a link.
280 [ "$log_list" ] && { sed -n '/<div id="report">/,$p' $log_opt | \
281 grep -A1 -F '<div class=' | sed 1,2!d &&
282 echo '<a class="sublog" href="'$log_opt'">SubLog</a>' && \
283 echo "</div>"
284 } >> ${log_list%% *}
285 export log_opt="${log_list%% *}"
286 report_step_status
287 ;;
288 esac
289 return $report_return_code
290 }
292 # Open a bloc of substeps in a terminal and log.
293 report_open_bloc()
294 {
295 unset open_bloc
296 [ "$embeded_open_bloc" = "yes" ] && embeded_open_bloc=opened
297 [ -f "$log_tmp.eob" ] && rm $log_tmp.eob
298 export bloc_level=$(($bloc_level+1))
299 export bloc${bloc_level}_running="$step_running"
300 if [ -p $log_tmp.stdout ]; then
301 if [ -s $log_tmp ]; then
302 prebloc=yes
303 report_step_status
304 prebloc=
305 else
306 report_stop_listen
307 echo ' ...' >&3
308 fi
309 [ "$(eval echo \$bloc${bloc_level}_delimiter)" ] && \
310 echo "$current_bloc_display$(eval echo \"\$bloc${bloc_level}_delimiter\")" >&3
311 [ "$log_opt" ] && sed "s~<div class=\"$step_running\">~<div class=\"bloc_level$bloc_level\">~" -i "$log_opt"
312 else
313 exec 1>&3 2>&4
314 fi
315 export current_bloc_display="$(eval echo \"\$bloc${bloc_level}_display\")"
316 unset bloc${bloc_level}_status
317 unset step_running
318 }
320 # These are the two new status functions used by the report tool.
321 # States are : ok - no error since the start of the step
322 # warning - there was an error(s) since the start of the step
323 # failed - the last executed command has exited abnormally
324 report_step_status()
325 {
326 unset report_return_code
327 if [ -p $log_tmp.stdout ]; then
328 report_stop_listen
330 # Close message bloc if opened.
331 if [ -s $log_tmp -a "$report_verbosity_opt" = all ] || \
332 [ -s $log_tmp.error -a "$report_verbosity_opt" != none ]; then
333 echo " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ " >&3
334 ! [ "$prebloc" ] && echo -en "$current_bloc_display... $step_running" >&3 && report_addemptyline="yes"
335 fi
337 # Check, display and log the status of the step.
338 if ! [ "$check_status" = "0" ]; then
339 check_status=failed
340 else
341 [ -s "$log_tmp.error" ] && check_status=warning || check_status=ok
342 fi
343 ! [ "$prebloc" ] && report_display_status
344 [ "$report_addemptyline" ] && echo "" >&3 && unset report_addemptyline
345 [ "$log_opt" ] && report_rec_log
346 fi
348 [ -f "$log_tmp.eob" ] && rm $log_tmp.eob
350 # Set blocs status if needed.
351 [ -f $log_tmp.status ] && check_status=$(cat $log_tmp.status) && rm $log_tmp.status
352 [ "$bloc_level" ] && report_set_bloc_status
354 # Clear variables / temporary logs.
355 ! [ "$prebloc" ] && export step_running=""
356 check_status=""
357 echo -n "" > $log_tmp.error
358 echo -n "" > $log_tmp
359 }
361 report_display_status()
362 {
363 [ "$report_return_code" = 1 ] && check_status=failed
364 echo -en "\\033[70G " >&3
365 echo -en "\\033[70G[ " >&3
366 [ "$check_status" = ok ] && report_return_code=0 && echo -en "\\033[1;32mOK" >&3
367 [ "$check_status" = warning ] && report_return_code=0 && echo -en "\\033[1;33mWarning" >&3
368 [ "$check_status" = failed ] && report_return_code=1 && echo -en "\\033[1;31mFailed" >&3
369 echo -e "\\033[0;39m ]" >&3
370 }
372 report_term_to_html()
373 {
374 report_decolorize | sed -e 's~<~\&lt;~' -e 's~>~\&gt;~' -e 's/$/<br \/>/' -e 's~STDERR: \(.*\)~<span class="error">\1<\/span>~' -e 's~ ~\&nbsp;\&nbsp;\&nbsp;\&nbsp;~'
375 }
377 report_decolorize()
378 {
379 tr -d '\e' | sed -r "s/\[([0-9]{1,3}(;[0-9]{1,3})*)[m|G]//g"
380 }
382 report_rec_log()
383 {
384 ! [ "$prebloc" ] && sed "s~<div class=\"$step_running\">~<div class=\"$check_status\">~" -i "$log_opt"
385 if [ -s "$log_tmp" ]; then
386 if [ -s "$log_tmp.error" ]; then
387 cat $log_tmp.error | sort -u | while read line; do
388 # Format line to avoid sed errors :
389 line=$(echo "$line" | sed -e 's~\*~\\\*~g' -e 's~\[~\\\[~g' -e 's~\]~\\\]~g')
390 sed "s~^$line$~STDERR: $line~" -i $log_tmp
391 done
392 fi
393 echo -n "<pre>" >> "$log_opt"
394 cat $log_tmp | report_term_to_html >> "$log_opt"
395 echo "</pre>" >> "$log_opt"
396 fi
397 ! [ "$prebloc" ] && echo "</div>" >> "$log_opt"
398 }
400 # These variables keep the status of the blocs.
401 # A bloc is reported as ok if all child steps are ok and has failed
402 # if all child steps are failed (or if a fatal error occurs).
403 # In other cases the bloc is reported as a warning.
404 report_set_bloc_status()
405 {
406 bloc_status=$(eval echo \$bloc${bloc_level}_status)
407 for n in $(seq $bloc_level -1 1); do
408 ! [ "$(eval echo \$bloc${n}_status)" ] && eval bloc${n}_status=$check_status
409 ! [ "$(eval echo \$bloc${n}_status)" = "$check_status" ] && \
410 eval bloc${n}_status=warning
411 done
412 }
414 create_log_index()
415 {
416 cd $SLITAZ_LOG
417 cp -f /usr/share/slitaz/web/template.html index.html
418 sed -e "s/xml:lang=\"us\" lang=\"us\"/xml:lang=\"${LANG%%_*}\" lang=\"${LANG%%_*}\"/" \
419 -e "s~Title of the page~SliTaz GNU/Linux - Logs Index~" \
420 -e "s~Second Title~Logs Index~" -i index.html
421 echo '<div id="report">' >> index.html
422 for log in $(ls -t */*); do
423 log_title=$(grep '<h1>.*</h1>' $log | sed 's~<h1>\(.*\)</h1>~\1~')
424 log_date=$(date -r $log)
425 log_status=$(grep '<div class=".*">' $log | sed -e 1!d -e 's~<.*"\(.*\)">~\1~')
426 echo -e " <a href=\"$log\"><div class=\"$log_status\">$log_date: $log_title</div></a>" >> index.html
427 done
428 echo -e '</div></body></html>' >> index.html
429 chmod 666 index.html
430 }