Subject: [PATCH] [BZ 94480] dbginfo.sh: Improvements on logging, content and collecting sysfs.
From: Wolfgang Taphorn <taphorn@de.ibm.com>

Description: dbginfo.sh: Improvements on logging, content and collecting sysfs.
Symptom:     The collection of the sysfs tree takes very long.
             The logs are not written serialized, instead they are mixed up.
Problem:     * The collection of the sysfs tree runs a logic to verify the
               existence of the file, the target directory along with the
               verification of the right permissions for each file to copy.
               This is a time consuming task and can be optimized.
             * In the logs, some output is mixed up. This is due to the
               different used mechanisms to write the information into the
               files (redirection vs tee in parallel).
             * Some files are missing in the generated TAR file.
             * Naming of log file is not unique enough to identify different
               machines.
             * The execution of 'pvscan -vvv' may cause system hangs.
             * Whitespaces in file names for qethqoat output.
Solution:    * Collecting the following additional configuration files:
               - /etc/*.conf
               - /etc/hosts*
               - /etc/inittab
               - /etc/logrotate.d
               - /etc/pam.d
               - /etc/profile
               - /etc/profile.d
               - /etc/resolv.*
               - /etc/syslog*
               - /etc/xinet.d
             * Collecting the following additional proc files:
               - /proc/service_levels
             * Removing the execution of 'pvscan -vvv'.
             * Unify the coding style within the script.
             * To speed up collecting the sysfs tree, the logic for copying the
               files has been re-implemented to avoid obsolete verification for
               this scenario. Now, the logic first creates the whole directory
               structure and copies afterwards the files into it, without any
               additional verification. Error messages will still be logged
               into the appropriate log files.
             * To log the information, tee and redirection is no longer used in
               parallel. Instead, the script redirects all of its output into
               a log file. Only those few exceptions that should be printed to
               stdout (and log file) are redirected again appropriate.
             * The file naming of the resulting TAR archive has been extended
               to add the processor ID of the first processor. This allows
               to identify guests with the same hostname but running on
               different machines via the file name.
             * The man page has been extended for these latest changes.
             * Strip the whitespaces from the output of lsqeth to avoid
               whitespaces in the file names used to collect the qethqoat
               output.
Reproduction: -
Upstream-ID:  -
Problem-ID:   94480

Signed-off-by: Wolfgang Taphorn <taphorn@de.ibm.com>
---
 scripts/dbginfo.sh |  328 ++++++++++++++++++++++++++++++-----------------------
 1 file changed, 189 insertions(+), 139 deletions(-)

--- a/scripts/dbginfo.sh
+++ b/scripts/dbginfo.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 ###############################################################################
-# Copyright IBM Corp. 2002, 2012
+# Copyright IBM Corp. 2002, 2013
 #
 # Collect some configuration, trace, and debug information about the
 # Linux on System z machine
@@ -29,7 +29,7 @@
 ###############################################################################
 
 # The kernel release version as delivered from uname -r
-readonly KERNEL_RELEASE_VERSION="$(uname -r 2>/dev/null)"
+readonly KERNEL_RELEASE_VERSION="`uname -r 2>/dev/null`"
 
 ########################################
 # Global used variables
@@ -38,11 +38,24 @@ readonly KERNEL_RELEASE_VERSION="$(uname
 # The general name of this script
 readonly SCRIPTNAME="${0##*/}"
 
+# The terminal
+readonly TERMINAL="`tty 2>/dev/null`"
+
+# The processor ID for the first processor
+readonly PROCESSORID=`grep -E ".*processor 0:.*" /proc/cpuinfo | sed 's/.*identification[[:space:]]*\=[[:space:]]*\([[:alnum:]]*\).*/\1/g'`
+
+# The current date
+readonly DATETIME=`date +%Y-%m-%d-%H-%M-%S 2>/dev/null`
+
 # The base working directory
 readonly WORKDIR_BASE="/tmp/"
 
 # The current working directory for the actual script execution
-readonly WORKDIR_CURRENT="DBGINFO-$(date +%Y-%m-%d-%H-%M-%S)-$(hostname)"
+if test -z ${PROCESSORID}; then
+    readonly WORKDIR_CURRENT="DBGINFO-"${DATETIME}"-`hostname -s 2>/dev/null`"
+else
+    readonly WORKDIR_CURRENT="DBGINFO-"${DATETIME}"-`hostname -s 2>/dev/null`-${PROCESSORID}"
+fi
 
 # The current path where the collected information is put together
 readonly WORKPATH="${WORKDIR_BASE}${WORKDIR_CURRENT}/"
@@ -72,13 +85,13 @@ readonly MOUNT_POINT_DEBUGFS="/sys/kerne
 readonly COLLECTION_COUNT=7
 
 # The kernel version (e.g. '2' from 2.6.32 or '3' from 3.2.1)
-readonly KERNEL_VERSION="$(uname -r 2>/dev/null | cut -d'.' -f1)"
+readonly KERNEL_VERSION="`uname -r 2>/dev/null | cut -d'.' -f1`"
 
 # The kernel major revision number (e.g. '6' from 2.6.32 or '2' from 3.2.1)
-readonly KERNEL_MAJOR_REVISION="$(uname -r 2>/dev/null | cut -d'.' -f2)"
+readonly KERNEL_MAJOR_REVISION="`uname -r 2>/dev/null | cut -d'.' -f2`"
 
 # The kernel mainor revision number (e.g. '32' from 2.6.32 or '1' from 3.2.1)
-readonly KERNEL_MINOR_REVISION="$(uname -r 2>/dev/null | cut -d'.' -f3 | sed s/[^0-9].*//g)"
+readonly KERNEL_MINOR_REVISION="`uname -r 2>/dev/null | cut -d'.' -f3 | sed s/[^0-9].*//g`"
 
 # Is this kernel supporting sysfs - since 2.4 (0=yes, 1=no)
 if test ${KERNEL_VERSION} -lt 2 ||
@@ -131,6 +144,7 @@ PROCFILES="\
   /proc/qeth\
   /proc/qeth_perf\
   /proc/qeth_ipa_takeover\
+  /proc/service_levels\
   /proc/slabinfo\
   /proc/stat\
   /proc/swaps\
@@ -144,7 +158,7 @@ PROCFILES="\
 # Adding files to PROCFILES in case scsi devices are available
 if test -e /proc/scsi; then
     PROCFILES="${PROCFILES}\
-      `find /proc/scsi -type f -perm +0444`\
+      `find /proc/scsi -type f -perm /444 2>/dev/null`\
       "
 fi
 
@@ -163,7 +177,7 @@ fi
 if test ${LINUX_SUPPORT_SYSFSDBF} -eq 1; then
     if test -e /proc/s390dbf; then
 	PROCFILES="${PROCFILES}\
-          `find /proc/s390dbf -type f -not -path \"*/raw\" -not -path \"*/flush\"`\
+          `find /proc/s390dbf -type f -not -path \"*/raw\" -not -path \"*/flush\" 2>/dev/null`\
           "
     fi
 fi
@@ -189,45 +203,40 @@ LOGFILES="\
 ########################################
 
 CONFIGFILES="\
+  /etc/*.conf\
   /etc/anacrontab\
   /etc/auto.*\
-  /etc/ccwgroup.conf\
-  /etc/chandev.conf\
   /etc/cron.*\
   /etc/crontab\
   /etc/crypttab\
-  /etc/dasd.conf\
   /etc/depmod.d\
-  /etc/dracut.conf\
   /etc/dracut.conf.d\
   /etc/exports\
   /etc/fstab\
-  /etc/hba.conf\
-  /etc/IBMtaped.conf\
+  /etc/hosts*\
   /etc/iscsi\
-  /etc/lin_taped.conf\
+  /etc/inittab\
+  /etc/logrotate.d\
   /etc/lvm\
-  /etc/mdadm.conf\
   /etc/modprobe.conf*\
   /etc/modprobe.d\
-  /etc/modules.conf\
   /etc/mtab\
-  /etc/multipath.conf\
   /etc/multipath\
   /etc/networks\
+  /etc/pam.d\
+  /etc/profile\
+  /etc/profile.d\
   /etc/rc.d\
   /etc/rc.local\
-  /etc/rsyslog.conf\
+  /etc/resolv.*\
   /etc/rsyslog.d\
-  /etc/syslog.conf\
   /etc/sysconfig\
-  /etc/sysctl.conf\
   /etc/sysctl.d\
+  /etc/syslog*\
   /etc/udev*\
-  /etc/zipl.conf\
-  /etc/zfcp.conf\
+  /etc/xinet.d\
   /etc/*release\
-  `find /lib/modules -name modules.dep`\
+  `find /lib/modules -name modules.dep 2>/dev/null`\
   "
 
 ########################################
@@ -243,7 +252,7 @@ CMDS="uname -a\
   :last\
   :lsshut\
   :ifconfig -a\
-  :nm-tool
+  :nm-tool\
   :route -n\
   :ip route list\
   :ip rule list\
@@ -271,7 +280,6 @@ CMDS="uname -a\
   :lszfcp\
   :lszfcp -D\
   :lszfcp -V\
-  :pvscan -vvv\
   :SPident\
   :rpm -qa | sort\
   :sysctl -a\
@@ -353,7 +361,7 @@ collect_cmdsout() {
     local cmd
     local ifs_orig="${IFS}"
 
-    echo " 1 of ${COLLECTION_COUNT}: Collecting command output"
+    pr_log_stdout " 1 of ${COLLECTION_COUNT}: Collecting command output"
 
     IFS=:
     for cmd in ${CMDS}; do
@@ -361,7 +369,7 @@ collect_cmdsout() {
     done
     IFS="${ifs_orig}"
 
-    echo
+    pr_log_stdout " "
 }
 
 
@@ -375,7 +383,7 @@ collect_vmcmdsout() {
     local ifs_orig="${IFS}"
 
     if test ${LINUX_ON_ZVM} -eq 0; then
-	echo " 2 of ${COLLECTION_COUNT}: Collecting z/VM command output"
+	pr_log_stdout " 2 of ${COLLECTION_COUNT}: Collecting z/VM command output"
 
 	if type vmcp >/dev/null 2>&1; then
 	    cp_command="vmcp"
@@ -388,18 +396,19 @@ collect_vmcmdsout() {
 		modprobe cpint && module_loaded=0 && sleep 2
 	    fi
 	else
-	    echo "  WARNING: No program found to communicate to z/VM CP"
-	    echo "  WARNING: Skipping the collection of z/VM command output"
-	    echo ""
+	    pr_log_stdout " "
+	    pr_log_stdout "  WARNING: No program found to communicate to z/VM CP"
+	    pr_log_stdout "  WARNING: Skipping the collection of z/VM command output"
+	    pr_log_stdout " "
 	    return 1
 	fi
-	VMUSERID="$(${cp_command} q userid | sed -ne 's/^\([^[:space:]]*\).*$/\1/p')"
+	VMUSERID="`${cp_command} q userid 2>/dev/null | sed -ne 's/^\([^[:space:]]*\).*$/\1/p'`"
 
-	vm_cmds="$(echo ${VM_CMDS} | sed "s/VMUSERID/${VMUSERID}/g")"
+	vm_cmds="`echo ${VM_CMDS} | sed "s/VMUSERID/${VMUSERID}/g"`"
 
 	IFS=:
 	for vm_command in ${vm_cmds}; do
-	    IFS=${ifs_orig}
+	    IFS="${ifs_orig}"
 	    local cp_buffer_size=2
 	    local rc_buffer_size=2
 	    while test ${rc_buffer_size} -eq 2 && test ${cp_buffer_size} -lt 1024; do
@@ -419,10 +428,10 @@ collect_vmcmdsout() {
 	    rmmod vmcp
 	fi
     else
-	echo " 2 of ${COLLECTION_COUNT}: Running in LPAR, no z/VM command output collected"
+	pr_log_stdout " 2 of ${COLLECTION_COUNT}: Running in LPAR, no z/VM command output collected"
     fi
 
-    echo
+    pr_log_stdout " "
 }
 
 
@@ -430,13 +439,13 @@ collect_vmcmdsout() {
 collect_procfs() {
     local file_name
 
-    echo " 3 of ${COLLECTION_COUNT}: Collecting procfs"
+    pr_log_stdout " 3 of ${COLLECTION_COUNT}: Collecting procfs"
 
     for file_name in ${PROCFILES}; do
-	call_collect_file "${file_name}" "${LOGFILE}"
+	call_collect_file "${file_name}"
     done
 
-    echo
+    pr_log_stdout " "
 }
 
 
@@ -449,33 +458,41 @@ collect_sysfs() {
 
     # Requires kernel version newer then 2.4
     if test ${LINUX_SUPPORT_SYSFS} -eq 0; then
-	echo " 4 of ${COLLECTION_COUNT}: Collecting sysfs"
+	pr_log_stdout " 4 of ${COLLECTION_COUNT}: Collecting sysfs"
 	# Requires kernel version of 2.6.13 or newer
 	if test ${LINUX_SUPPORT_SYSFSDBF} -eq 0; then
-	    if ! grep -qE "${MOUNT_POINT_DEBUGFS}.*debugfs" /proc/mounts; then
-		if mount -t debugfs debugfs ${MOUNT_POINT_DEBUGFS} >/dev/null 2>&1; then
+	    if ! grep -qE "${MOUNT_POINT_DEBUGFS}.*debugfs" /proc/mounts 2>/dev/null; then
+		if mount -t debugfs debugfs "${MOUNT_POINT_DEBUGFS}" >/dev/null 2>&1; then
 		    sleep 2
 		    debugfs_mounted=1;
 		else
-		    echo "  WARNING: \"Unable to mount debugfs ${MOUNT_POINT_DEBUGFS}\""
+		    pr_log_stdout "  WARNING: \"Unable to mount debugfs ${MOUNT_POINT_DEBUGFS}\""
 		fi
 	    fi
 	fi
 
-	call_run_command "find /sys -print0 | sort -z | xargs -0 -n 10 ls -ld" ${OUTPUT_FILE_SYSFS}
+	call_run_command "find /sys -print0 | sort -z | xargs -0 -n 10 ls -ld" "${OUTPUT_FILE_SYSFS}"
 
-	find /sys -noleaf -type f -perm +444 -a -not -name '*trace_pipe' | while IFS= read -r file_name; do
-	    call_collect_file "${file_name}" "${LOGFILE}"
+	find /sys -noleaf -type d 2>/dev/null | while IFS= read -r dir_name; do
+	    mkdir -p "${WORKPATH}${dir_name}"
+	done
+
+	find /sys -noleaf -type f -perm /444 \
+	    -a -not -name "*trace_pipe" \
+	    -a -not -path "*debug/hid*/events" \
+	    -a -not -path "*debug/usb/usbmon/*" 2>/dev/null | while IFS= read -r file_name; do
+	    echo "  ${file_name}"
+	    cp -P --preserve=links -L --parents "${file_name}" "${WORKPATH}"
 	done
 
 	if test ${debugfs_mounted} -eq 1; then
-	    umount ${MOUNT_POINT_DEBUGFS}
+	    umount "${MOUNT_POINT_DEBUGFS}"
 	fi
     else
-	echo " 4 of ${COLLECTION_COUNT}: Collecting sysfs skipped. Kernel $(uname -r) must be newer than 2.4"
+	pr_log_stdout " 4 of ${COLLECTION_COUNT}: Collecting sysfs skipped. Kernel `uname -r` must be newer than 2.4"
     fi
 
-    echo
+    pr_log_stdout " "
 }
 
 
@@ -483,76 +500,79 @@ collect_sysfs() {
 collect_logfiles() {
     local file_name
 
-    echo " 5 of ${COLLECTION_COUNT}: Collecting log files"
+    pr_log_stdout " 5 of ${COLLECTION_COUNT}: Collecting log files"
 
     for file_name in ${LOGFILES}; do
-	call_collect_file "${file_name}" "${LOGFILE}"
+	call_collect_file "${file_name}"
     done
 
-    echo
+    pr_log_stdout " "
 }
 
 ########################################
 collect_configfiles() {
     local file_name
 
-    echo " 6 of ${COLLECTION_COUNT}: Collecting config files"
+    pr_log_stdout " 6 of ${COLLECTION_COUNT}: Collecting config files"
 
     for file_name in ${CONFIGFILES}; do
-	call_collect_file "${file_name}" "${LOGFILE}"
+	call_collect_file "${file_name}"
     done
 
-    echo
+    pr_log_stdout " "
 }
 
+
 ########################################
 collect_osaoat() {
-    local network_devices="$(lsqeth 2>&1 | grep "Device name" | sed 's/.*:[[:space:]]\+\(.*\)[[:space:]]\+/\1/g')"
+    local network_devices="`lsqeth 2>/dev/null | grep "Device name" | sed 's/.*:[[:space:]]\+\([^[:space:]]*\)[[:space:]]\+/\1/g'`"
     local network_device
 
     if which qethqoat >/dev/null 2>&1; then
 	if test -n "${network_devices}"; then
-	    echo " 7 of ${COLLECTION_COUNT}: Collecting osa oat output"
-	    for network_device in ${network_devices}; do
-		call_run_command "qethqoat ${network_device}" ${OUTPUT_FILE_OSAOAT}.out &&
-		call_run_command "qethqoat -r ${network_device}" ${OUTPUT_FILE_OSAOAT}_${network_device}.raw
+	    pr_log_stdout " 7 of ${COLLECTION_COUNT}: Collecting osa oat output"
+	    for network_device in "${network_devices}"; do
+		call_run_command "qethqoat ${network_device}" "${OUTPUT_FILE_OSAOAT}.out" &&
+		call_run_command "qethqoat -r ${network_device}" "${OUTPUT_FILE_OSAOAT}_${network_device}.raw"
 	    done
 	else
-	    echo " 7 of ${COLLECTION_COUNT}: Collecting osa oat output skipped - no devices"
+	    pr_log_stdout " 7 of ${COLLECTION_COUNT}: Collecting osa oat output skipped - no devices"
 	fi
     else
-	echo " 7 of ${COLLECTION_COUNT}: Collecting osa oat output skipped - not available"
+	pr_log_stdout " 7 of ${COLLECTION_COUNT}: Collecting osa oat output skipped - not available"
     fi
 
-    echo
+    pr_log_stdout " "
 }
 
 
 ########################################
+# Be aware that this output must be
+# redirected into a separate logfile
 call_run_command() {
     local cmd="${1}"
     local logfile="${2}"
-    local raw_cmd="$(echo ${cmd} | sed -ne 's/^\([^[:space:]]*\).*$/\1/p')"
+    local raw_cmd="`echo ${cmd} | sed -ne 's/^\([^[:space:]]*\).*$/\1/p'`"
 
-    echo "#######################################################" >> ${logfile}
-    echo "${USER}@${HOSTNAME}> ${cmd}" >> ${logfile}
+    echo "#######################################################" >> "${logfile}"
+    echo "${USER}@${HOSTNAME}> ${cmd}" >> "${logfile}"
 
     # check if command exists
-    if ! which ${raw_cmd} >/dev/null 2>&1; then
+    if ! which "${raw_cmd}" >/dev/null 2>&1; then
         # check if command is a builtin
-	if ! command -v ${raw_cmd} >/dev/null 2>&1; then
-	    echo "  WARNING: Command \"${raw_cmd}\" not available" >> ${logfile}
-	    echo "" >> ${logfile}
+	if ! command -v "${raw_cmd}" >/dev/null 2>&1; then
+	    echo "  WARNING: Command \"${raw_cmd}\" not available" >> "${logfile}"
+	    echo >> "${logfile}"
 	    return 1;
 	fi
     fi
 
-    if ! eval ${cmd} 1>>${logfile} 2>&1; then
-	echo "  WARNING: Command \"${cmd}\" failed" >> ${logfile}
-	echo "" >> ${logfile}
+    if ! eval "${cmd}" >> "${logfile}" 2>&1; then
+	echo "  WARNING: Command \"${cmd}\" failed" >> "${logfile}"
+	echo >> "${logfile}"
 	return 1
     else
-	echo "" >> ${logfile}
+	echo >> "${logfile}"
 	return 0
     fi
 }
@@ -562,26 +582,17 @@ call_run_command() {
 call_collect_file() {
     local directory_name
     local file_name="${1}"
-    local logfile="${2}"
 
-    echo "  ${file_name}" >> ${logfile}
-    if test ! -e "${file_name}"; then
-	echo "  WARNING: No such file: \"${file_name}\"" >> ${logfile}
-	return 1
-    elif test ! -r "${file_name}"; then
-	echo "  WARNING: Permission denied: \"${file_name}\"" >> ${logfile}
+    echo "  ${file_name}"
+
+    directory_name="`dirname \"${file_name}\" 2>/dev/null`"
+    if test ! -e "${WORKPATH}${directory_name}"; then
+	mkdir -p "${WORKPATH}${directory_name}" 2>&1
+    fi
+    if ! cp -r --preserve=mode,timestamps -d -L --parents "${file_name}" "${WORKPATH}" 2>&1; then
 	return 1
     else
-	directory_name=$(dirname "${file_name}")
-	if test ! -e "${WORKPATH}${directory_name}"; then
-	    mkdir -p "${WORKPATH}${directory_name}"
-	fi
-	if ! cp -r -d -L --parents "${file_name}" "${WORKPATH}" 2>> ${logfile}; then
-	    echo "  WARNING: cp failed for file: \"${file_name}\"" >> ${logfile}
-	    return 1
-	else
-	    return 0
-	fi
+	return 0
     fi
 }
 
@@ -594,7 +605,7 @@ call_collect_file() {
 print_version() {
     cat <<EOF
  ${SCRIPTNAME}: Debug information script version %S390_TOOLS_VERSION%
- Copyright IBM Corp. 2002, 2012
+ Copyright IBM Corp. 2002, 2013
 EOF
 }
 
@@ -618,11 +629,12 @@ print_usage()
 
  The collected information is written to a TAR archive named
 
-     /tmp/DBGINFO-[date]-[time]-[hostname].tgz
+     /tmp/DBGINFO-[date]-[time]-[hostname]-[processorid].tgz
 
  where [date] and [time] are the date and time when debug data is collected.
  [hostname] indicates the hostname of the system the data was collected from.
-
+ The [processorid] is taken from the processor 0 and indicates the processor
+ identification.
 
  Options:
 
@@ -659,9 +671,9 @@ commandline_parse()
     local cmdline_count=${#}
 
     if test ${cmdline_count} -eq 1; then
-	if test ${cmdline_arg1} = '-h' -o ${cmdline_arg1} = '--help'; then
+	if test ${cmdline_arg1} = '-h' || test ${cmdline_arg1} = '--help'; then
 	    print_usage
-	elif test ${cmdline_arg1} = '-v' -o ${cmdline_arg1} = '--version'; then
+	elif test ${cmdline_arg1} = '-v' || test ${cmdline_arg1} = '--version'; then
 	    print_version
 	else
 	    echo
@@ -685,20 +697,24 @@ commandline_parse()
 # Setup the environment
 environment_setup()
 {
-    if test -e ${WORKDIR_BASE}${SCRIPTNAME}.lock; then
+    if test ! -e "${WORKDIR_BASE}"; then
+	mkdir -p "${WORKDIR_BASE}"
+    elif test ! -d "${WORKDIR_BASE}"; then
+	echo " ERROR: ${WORKDIR_BASE} exists but this is a file!"
+	echo "        Please make sure ${WORKDIR_BASE} is a directory."
+	exit 1
+    fi
+
+    if test -e "${WORKDIR_BASE}${SCRIPTNAME}".lock; then
 	print_alreadyrunning
         exit 1
     else
-	touch ${WORKDIR_BASE}${SCRIPTNAME}.lock
+	touch "${WORKDIR_BASE}${SCRIPTNAME}".lock
     fi
 
-    # Generating a random delay up to 0.999 second
-    #sleep .$[ ( ${RANDOM} % 1000 ) + 1 ]s
-
-    mkdir -p ${WORKDIR_BASE}
-
-    if ! mkdir ${WORKPATH}; then
-	echo " ERROR: target directory ${WORKPATH} already exists or ${WORKDIR_BASE} does not exist!"
+    if ! mkdir "${WORKPATH}" 2>/dev/null; then
+	echo " ERROR: Target directory ${WORKPATH} already exists or"
+	echo "        ${WORKDIR_BASE} does not exist!"
 	exit 1
     fi
 }
@@ -708,19 +724,22 @@ environment_setup()
 # create gzip-ped tar file
 create_package()
 {
-    echo " Finalizing: Creating archive with collected data"
-    cd ${WORKDIR_BASE}
+    pr_stdout " Finalizing: Creating archive with collected data"
+    cd "${WORKDIR_BASE}"
 
-    if ! tar -czf ${WORKARCHIVE} ${WORKDIR_CURRENT}; then
-	echo " "
-	echo " ERROR: Collection of data failed!"
+    if ! tar -czf "${WORKARCHIVE}" "${WORKDIR_CURRENT}"; then
+	pr_stdout " "
+	pr_stdout " ERROR: Collection of data failed!"
+	pr_stdout "        The creation of ${WORKARCHIVE} was not successful."
+	pr_stdout "        Please check the directory ${WORKDIR_BASE}"
+	pr_stdout "        to provide enough free available space."
     else
-	echo " "
-	echo " Collected data was saved to:"
-	echo "   ${WORKARCHIVE}"
+	pr_stdout " "
+	pr_stdout " Collected data was saved to:"
+	pr_stdout " >>  ${WORKARCHIVE}  <<"
     fi
 
-    echo
+    pr_stdout " "
 }
 
 
@@ -728,8 +747,18 @@ create_package()
 # Cleaning up the prepared/collected information
 environment_cleanup()
 {
-    test -d ${WORKPATH} && rm -rf ${WORKPATH};
-    test -e ${WORKDIR_BASE}${SCRIPTNAME}.lock && rm -f ${WORKDIR_BASE}${SCRIPTNAME}.lock;
+    if ! rm -rf "${WORKPATH}" 2>/dev/null; then
+	pr_stdout " "
+	pr_stdout " WARNING: Deletion of ${WORKPATH} failed"
+	pr_stdout " Please remove the directory manually"
+	pr_stdout " "
+    fi
+    if ! rm -f "${WORKDIR_BASE}${SCRIPTNAME}".lock 2>/dev/null; then
+	pr_stdout " "
+	pr_stdout " WARNING: Deletion of ${WORKDIR_BASE}${SCRIPTNAME} failed"
+	pr_stdout " Please remove the file manually"
+	pr_stdout " "
+    fi
 }
 
 
@@ -737,52 +766,73 @@ environment_cleanup()
 # Function to perform a cleanup in case of a received signal
 emergency_exit()
 {
-    echo " INFO: Cleanup of temporary collected data"
+    pr_stdout " "
+    pr_stdout " INFO: Data collection has been interrupted"
+    pr_stdout " INFO: Cleanup of temporary collected data"
     environment_cleanup
+    pr_stdout " INFO: Emergency exit processed"
 
-    echo " INFO: Emergency exit processed"
-    echo " INFO: Data collection has been interrupted"
-    echo " "
+    pr_stdout " "
     exit;
 }
 
 
+########################################
+# Function to print to stdout when rediretion is active
+pr_stdout()
+{
+    echo "${@}" >&8
+}
+
+
+########################################
+# Function to print to stdout and into log file when rediretion is active
+pr_log_stdout()
+{
+    echo "$@"
+    echo "$@" >&8
+}
+
+
 ###############################################################################
 # Running the script
 
 commandline_parse ${*}
 environment_setup
+print_version
+
+# saving stdout/stderr and redirecting stdout/stderr into log file
+exec 8>&1 9>&2 >${LOGFILE} 2>&1
 
 # trap on SIGHUP SIGINT SIGTERM
 trap emergency_exit 1 2 15
 
-(
-    print_version
-    echo " "
-    echo " Kernel version        = ${KERNEL_VERSION}.${KERNEL_MAJOR_REVISION}.${KERNEL_MINOR_REVISION} ($(uname -r))"
-    echo " Runtime environment   = $(test ${LINUX_ON_ZVM} -eq 0 && echo 'z/VM' || echo 'LPAR')"
-    echo " "
-
-    collect_cmdsout
+pr_log_stdout ""
+pr_log_stdout " Hardware platform     = `uname -i`"
+pr_log_stdout " Kernel version        = ${KERNEL_VERSION}.${KERNEL_MAJOR_REVISION}.${KERNEL_MINOR_REVISION} (`uname -r 2>/dev/null`)"
+pr_log_stdout " Runtime environment   = `test ${LINUX_ON_ZVM} -eq 0 && echo 'z/VM' || echo 'LPAR'`"
+pr_log_stdout ""
 
-    collect_vmcmdsout
+collect_cmdsout
 
-    # Collecting the proc file system (content is specific based on kernel version)
-    collect_procfs
+collect_vmcmdsout
 
-    # Collecting sysfs in case we run on Kernel 2.4 or newer
-    collect_sysfs
+# Collecting the proc file system (content is specific based on kernel version)
+collect_procfs
 
-    collect_logfiles
+# Collecting sysfs in case we run on Kernel 2.4 or newer
+collect_sysfs
 
-    collect_configfiles
+collect_logfiles
 
-    collect_osaoat
+collect_configfiles
 
-) | tee -a ${LOGFILE}
+collect_osaoat
 
 create_package
-echo ""
+
 environment_cleanup
 
+exec 1>&8 2>&9 8>&- 9>&-
+
 #EOF
