diff --git a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/conffiles/etc/cron.d/univention-mrtg b/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/conffiles/etc/cron.d/univention-mrtg index 1b9c9d4..2ff08d4 100644 --- a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/conffiles/etc/cron.d/univention-mrtg +++ b/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/conffiles/etc/cron.d/univention-mrtg @@ -4,9 +4,8 @@ PATH=/usr/sbin:/usr/bin:/sbin:/bin # Create mrtg statistics @!@ -if baseConfig.has_key('mrtg/cron') and not baseConfig['mrtg/cron'] == '': - print '@%@mrtg/cron@%@ root /usr/sbin/univention-mrtg' +if configRegistry.get('mrtg/cron'): + print configRegistry['mrtg/cron'] root /usr/sbin/univention-mrtg' else: print '#* * * * * root /usr/sbin/univention-mrtg' @!@ - diff --git a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/control b/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/control index 55f0d45..563aa08 100644 --- a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/control +++ b/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/control @@ -9,16 +9,13 @@ Build-Depends: debhelper, Package: univention-maintenance Architecture: all Depends: ${misc:Depends}, - bc, - ldap-utils, httpd, - nmap, mrtg, - netcat, - mail-transport-agent, cron, univention-config-registry, python-univention-lib (>= 1.0.25-1) +Suggests: samba, + lm-sensors, Description: UCS - maintenance tools This package monitors the server root's homedir and produces HTML statistics about filesystem usage and diff --git a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/copyright b/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/copyright index 285f1b4..c5cb6a4 100644 --- a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/copyright +++ b/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/copyright @@ -25,5 +25,3 @@ You should have received a copy of the GNU Affero General Public License with the Debian GNU/Linux or Univention distribution in file /usr/share/common-licenses/AGPL-3; if not, see . - - diff --git a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/dirs b/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/dirs deleted file mode 100644 index d0d360c..0000000 --- a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/dirs +++ /dev/null @@ -1,6 +0,0 @@ -etc/univention -usr/sbin -var/log/univention -var/univention-backup/etc -var/www/statistik -var/www/mrtg diff --git a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/docs b/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/docs deleted file mode 100644 index 8b13789..0000000 --- a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/docs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/postinst b/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/postinst deleted file mode 100644 index 4918e28..0000000 --- a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/postinst +++ /dev/null @@ -1,71 +0,0 @@ -#! /bin/sh -# -# Univention Maintenance -# postinst script -# -# Copyright 2004-2013 Univention GmbH -# -# http://www.univention.de/ -# -# All rights reserved. -# -# The source code of this program is made available -# under the terms of the GNU Affero General Public License version 3 -# (GNU AGPL V3) as published by the Free Software Foundation. -# -# Binary versions of this program provided by Univention to you as -# well as other copyrighted, protected or trademarked materials like -# Logos, graphics, fonts, specific documentations and configurations, -# cryptographic keys etc. are subject to a license agreement between -# you and Univention and not subject to the GNU AGPL V3. -# -# In the case you use this program under the terms of the GNU AGPL V3, -# the program is provided in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public -# License with the Debian GNU/Linux or Univention distribution in file -# /usr/share/common-licenses/AGPL-3; if not, see -# . - - -case "$1" in - configure) - if [ ! -e /var/www/statistik/index.htm ]; then - echo "" >>/var/www/statistik/index.htm - echo "" >>/var/www/statistik/index.htm - echo "" >>/var/www/statistik/index.htm - echo "" >>/var/www/statistik/index.htm - echo "" >>/var/www/statistik/index.htm - echo "No data available.

" >>/var/www/statistik/index.htm - echo "" >>/var/www/statistik/index.htm - echo "Start \"/usr/sbin/univention-maintenance\" manually" >>/var/www/statistik/index.htm - echo "" >>/var/www/statistik/index.htm - echo "" >>/var/www/statistik/index.htm - fi - - if [ -z "$2" ]; then - #run script every 15 minutes - univention-config-registry set mrtg/cron?"*/15 * * * *" \ - system/stats?yes \ - system/stats/cron?'0,30 * * * * ' - fi - ;; - - abort-upgrade|abort-remove|abort-deconfigure) - - ;; - - *) - echo "postinst called with unknown argument \`$1'" >&2 - exit 1 - ;; -esac - -#DEBHELPER# - -exit 0 - - diff --git a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/univention-maintenance.dirs b/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/univention-maintenance.dirs new file mode 100644 index 0000000..0a6216d --- /dev/null +++ b/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/univention-maintenance.dirs @@ -0,0 +1,2 @@ +var/www/statistik +var/www/mrtg diff --git a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/univention-maintenance.postinst b/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/univention-maintenance.postinst new file mode 100644 index 0000000..6983fb1 --- /dev/null +++ b/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/debian/univention-maintenance.postinst @@ -0,0 +1,67 @@ +#! /bin/sh +# +# Univention Maintenance +# postinst script +# +# Copyright 2004-2013 Univention GmbH +# +# http://www.univention.de/ +# +# All rights reserved. +# +# The source code of this program is made available +# under the terms of the GNU Affero General Public License version 3 +# (GNU AGPL V3) as published by the Free Software Foundation. +# +# Binary versions of this program provided by Univention to you as +# well as other copyrighted, protected or trademarked materials like +# Logos, graphics, fonts, specific documentations and configurations, +# cryptographic keys etc. are subject to a license agreement between +# you and Univention and not subject to the GNU AGPL V3. +# +# In the case you use this program under the terms of the GNU AGPL V3, +# the program is provided in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License with the Debian GNU/Linux or Univention distribution in file +# /usr/share/common-licenses/AGPL-3; if not, see +# . + + +case "$1" in + configure) + if [ ! -e /var/www/statistik/index.htm ]; then + echo '' + echo '' + echo '' + echo '' + echo 'No data available.

' + echo 'Start "/usr/sbin/univention-maintenance" manually' + echo '' + echo '' + fi >>/var/www/statistik/index.htm + + if [ -z "$2" ]; then + #run script every 15 minutes + univention-config-registry set mrtg/cron?"*/15 * * * *" \ + system/stats?yes \ + system/stats/cron?'0,30 * * * * ' + fi + ;; + + abort-upgrade|abort-remove|abort-deconfigure) + + ;; + + *) + echo "postinst called with unknown argument \`$1'" >&2 + exit 1 + ;; +esac + +#DEBHELPER# + +exit 0 diff --git a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/univention-maintenance.conf b/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/univention-maintenance.conf index 61c905d..8b78c98 100644 --- a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/univention-maintenance.conf +++ b/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/univention-maintenance.conf @@ -1,4 +1,3 @@ - # Configuration for univention-maintenance # tempfile for the mrtg config @@ -9,4 +8,3 @@ wwwdir="/var/www/statistik" # Index file indexhtm="index.htm" - diff --git a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/univention-mrtg b/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/univention-mrtg index 83f1154..11863f5 100755 --- a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/univention-mrtg +++ b/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/univention-mrtg @@ -34,158 +34,152 @@ # LANG is set to UTF-8. export LANG=C + +die () { echo "$*" >&2 ; exit 2 ; } # Name of config file configfile="/etc/univention/univention-maintenance.conf" # Search config file and check values -test -e $configfile || { - echo - echo "ERROR: Config file \"$configfile\" was not found!" - echo - exit 2; -} +test -e "$configfile" || + die "ERROR: Config file \"$configfile\" was not found!" -. $configfile +. "$configfile" -test -z "$mrtg_config" && touch "$mrtg_config" 2>/dev/null && { - echo - echo "ERROR: \"\$mrtg_config\" is not valid." - echo - exit 2; -} -test -z "$wwwdir" && mkdir -p "$wwwdir" 2>/dev/null && { - echo - echo "ERROR: Missing \"\$wwwdir\" in $configfile" - echo - exit 2; -} -test -z $indexhtm && { - echo - echo "ERROR: Missing \"\$indexhtm\" in $configfile" - echo - exit 2; -} +test -n "$mrtg_config" && + touch "$mrtg_config" 2>/dev/null || + die "ERROR: \"\$mrtg_config\" is not valid." +test -n "$wwwdir" && + mkdir -p "$wwwdir" 2>/dev/null || + die "ERROR: Missing \"\$wwwdir\" in $configfile" +test -n $indexhtm || + die "ERROR: Missing \"\$indexhtm\" in $configfile" # Delete old mrtg files -rm -f $wwwdir/ucs_*.png $wwwdir/ucs_*.txt -rm -f $wwwdir/uds_*.png $wwwdir/uds_*.txt -for i in $(ls $wwwdir/uds_*.log 2>/dev/null); do - new=$(echo $i | sed 's/\/uds/\/ucs/') - mv $i $new +rm -f "$wwwdir"/ucs_*.png "$wwwdir"/ucs_*.txt +rm -f "$wwwdir"/uds_*.png "$wwwdir"/uds_*.txt +for uds in "$wwwdir"/uds_*.log +do + mv "$uds" "$wwwdir/ucs_${uds#$wwwdir/uds_}" done # memory -freemem=$(more /proc/meminfo | grep ^MemFree: | awk {'print $2'}) -buffers=$(more /proc/meminfo | grep ^Buffers: | awk {'print $2'}) -cached=$(more /proc/meminfo | grep ^Cached: | awk {'print $2'}) -memtotal=$(more /proc/meminfo | grep ^MemTotal: | awk {'print $2'}) +freemem=$(awk '/^MemFree:/{print $2}' $mrtg_config -echo "Language: german" >> $mrtg_config -echo "Interval: 15" >> $mrtg_config -echo "Target[$mrtgname]: \`echo -e \"$prctmem\n0\nunused\nunused\"\`" >> $mrtg_config -echo "Options[$mrtgname]: growright,noo,gauge,nobanner,noborder,nolegend,noinfo" >> $mrtg_config -echo "Unscaled[$mrtgname]: dwmy" >> $mrtg_config -echo "MaxBytes[$mrtgname]: 100" >> $mrtg_config -echo "AbsMax[$mrtgname]: 99999" >> $mrtg_config -echo "Title[$mrtgname]: " >> $mrtg_config -echo "Ylegend[$mrtgname]: % " >> $mrtg_config -echo "Colours[$mrtgname]: blau#6666ff,unused#000000,unused#000000,unused#000000" >> $mrtg_config -echo "Background[$mrtgname]: #ffffff" >> $mrtg_config -echo "PageTop[$mrtgname]:

Speicherauslastung

" >> $mrtg_config +( + echo "WorkDir: $wwwdir" + echo "Language: german" + echo "Interval: 15" + echo "Target[$mrtgname]: \`echo -e \"$prctmem\n0\nunused\nunused\"\`" + echo "Options[$mrtgname]: growright,noo,gauge,nobanner,noborder,nolegend,noinfo" + echo "Unscaled[$mrtgname]: dwmy" + echo "MaxBytes[$mrtgname]: 100" + echo "AbsMax[$mrtgname]: 99999" + echo "Title[$mrtgname]: " + echo "Ylegend[$mrtgname]: %" + echo "Colours[$mrtgname]: blau#6666ff,unused#000000,unused#000000,unused#000000" + echo "Background[$mrtgname]: #ffffff" + echo "PageTop[$mrtgname]:

Speicherauslastung

" +) >"$mrtg_config" mrtg "$mrtg_config" 2>/dev/null -rm -f $mrtg_config $wwwdir/ucs_*.htm* -echo "Auslastung des Hauptspeichers: $prctmem%" >$wwwdir/$mrtgname.txt +rm -f "$mrtg_config" "$wwwdir"/ucs_*.htm* +echo "Auslastung des Hauptspeichers: $prctmem%" >"$wwwdir/$mrtgname.txt" # swap -swaptotal=$(more /proc/meminfo | grep ^SwapTotal: | awk {'print $2'}) -swapfree=$(more /proc/meminfo | grep ^SwapFree: | awk {'print $2'}) +swaptotal=$(awk '/^SwapTotal:/{print $2}' $mrtg_config -echo "Language: german" >> $mrtg_config -echo "Interval: 15" >> $mrtg_config -echo "Target[$mrtgname]: \`echo -e \"$prctswap\n0\nunused\nunused\"\`" >> $mrtg_config -echo "Options[$mrtgname]: growright,noo,gauge,nobanner,noborder,nolegend,noinfo" >> $mrtg_config -echo "Unscaled[$mrtgname]: dwmy" >> $mrtg_config -echo "MaxBytes[$mrtgname]: 100" >> $mrtg_config -echo "AbsMax[$mrtgname]: 99999" >> $mrtg_config -echo "Title[$mrtgname]: " >> $mrtg_config -echo "Ylegend[$mrtgname]: %" >> $mrtg_config -echo "Colours[$mrtgname]: blau#6666ff,unused#000000,unused#000000,unused#000000" >> $mrtg_config -echo "Background[$mrtgname]: #ffffff" >> $mrtg_config -echo "PageTop[$mrtgname]:

Swapauslastung

" >> $mrtg_config +( + echo "WorkDir: $wwwdir" + echo "Language: german" + echo "Interval: 15" + echo "Target[$mrtgname]: \`echo -e \"$prctswap\n0\nunused\nunused\"\`" + echo "Options[$mrtgname]: growright,noo,gauge,nobanner,noborder,nolegend,noinfo" + echo "Unscaled[$mrtgname]: dwmy" + echo "MaxBytes[$mrtgname]: 100" + echo "AbsMax[$mrtgname]: 99999" + echo "Title[$mrtgname]: " + echo "Ylegend[$mrtgname]: %" + echo "Colours[$mrtgname]: blau#6666ff,unused#000000,unused#000000,unused#000000" + echo "Background[$mrtgname]: #ffffff" + echo "PageTop[$mrtgname]:

Swapauslastung

" +) >"$mrtg_config" mrtg "$mrtg_config" 2>/dev/null -rm -f $mrtg_config $wwwdir/ucs_*.htm* -echo "Auslastung des Auslagerungsspeicher: $prctswap%" >$wwwdir/$mrtgname.txt +rm -f "$mrtg_config" "$wwwdir"/ucs_*.htm* +echo "Auslastung des Auslagerungsspeicher: $prctswap%" >"$wwwdir/$mrtgname.txt" # CPU usage of last 15 minutes -loadavg="`echo \`cat /proc/loadavg |awk '{print $3}'\`*100 | bc | cut -f1 -d"."`" +loadavg=$(awk '{print int($3*100)}' $mrtg_config -echo "Language: german" >> $mrtg_config -echo "Interval: 15" >> $mrtg_config -echo "Target[$mrtgname]: \`echo -e \"$loadavg\n0\nunused\nunused\"\`" >> $mrtg_config -echo "Options[$mrtgname]: growright,noo,gauge,nobanner,noborder,nolegend,noinfo" >> $mrtg_config -echo "Unscaled[$mrtgname]: dwmy" >> $mrtg_config -echo "MaxBytes[$mrtgname]: 100" >> $mrtg_config -echo "AbsMax[$mrtgname]: 99999" >> $mrtg_config -echo "Title[$mrtgname]: " >> $mrtg_config -echo "Ylegend[$mrtgname]: %" >> $mrtg_config -echo "Colours[$mrtgname]: blau#6666ff,unused#000000,unused#000000,unused#000000" >> $mrtg_config -echo "Background[$mrtgname]: #ffffff" >> $mrtg_config -echo "PageTop[$mrtgname]:

Systemlast

" >> $mrtg_config +( + echo "WorkDir: $wwwdir" + echo "Language: german" + echo "Interval: 15" + echo "Target[$mrtgname]: \`echo -e \"$loadavg\n0\nunused\nunused\"\`" + echo "Options[$mrtgname]: growright,noo,gauge,nobanner,noborder,nolegend,noinfo" + echo "Unscaled[$mrtgname]: dwmy" + echo "MaxBytes[$mrtgname]: 100" + echo "AbsMax[$mrtgname]: 99999" + echo "Title[$mrtgname]: " + echo "Ylegend[$mrtgname]: %" + echo "Colours[$mrtgname]: blau#6666ff,unused#000000,unused#000000,unused#000000" + echo "Background[$mrtgname]: #ffffff" + echo "PageTop[$mrtgname]:

Systemlast

" +) >"$mrtg_config" mrtg "$mrtg_config" 2>/dev/null -rm -f $mrtg_config $wwwdir/ucs_*.htm* -echo "Systemlast: $loadavg%" >$wwwdir/$mrtgname.txt +rm -f "$mrtg_config" "$wwwdir"/ucs_*.htm* +echo "Systemlast: $loadavg%" >"$wwwdir/$mrtgname.txt" # Session count -nrsessions="`ps -C univention-sess | grep -ic univention-sess`" +nrsessions=$(pgrep -c univention-sess) mrtgname="ucs_1sessions" -echo "WorkDir: $wwwdir" > $mrtg_config -echo "Language: german" >> $mrtg_config -echo "Interval: 15" >> $mrtg_config -echo "Target[$mrtgname]: \`echo -e \"$nrsessions\n0\nunused\nunused\"\`" >> $mrtg_config -echo "Options[$mrtgname]: growright,noo,gauge,nobanner,noborder,nolegend,noinfo" >> $mrtg_config -echo "Unscaled[$mrtgname]: dwmy" >> $mrtg_config -echo "MaxBytes[$mrtgname]: 10" >> $mrtg_config -echo "AbsMax[$mrtgname]: 99999" >> $mrtg_config -echo "Title[$mrtgname]: " >> $mrtg_config -echo "Ylegend[$mrtgname]: Total" >> $mrtg_config -echo "Colours[$mrtgname]: blau#6666ff,unused#000000,unused#000000,unused#000000" >> $mrtg_config -echo "Background[$mrtgname]: #ffffff" >> $mrtg_config -echo "PageTop[$mrtgname]:

Sessions

" >> $mrtg_config +( + echo "WorkDir: $wwwdir" + echo "Language: german" + echo "Interval: 15" + echo "Target[$mrtgname]: \`echo -e \"$nrsessions\n0\nunused\nunused\"\`" + echo "Options[$mrtgname]: growright,noo,gauge,nobanner,noborder,nolegend,noinfo" + echo "Unscaled[$mrtgname]: dwmy" + echo "MaxBytes[$mrtgname]: 10" + echo "AbsMax[$mrtgname]: 99999" + echo "Title[$mrtgname]: " + echo "Ylegend[$mrtgname]: Total" + echo "Colours[$mrtgname]: blau#6666ff,unused#000000,unused#000000,unused#000000" + echo "Background[$mrtgname]: #ffffff" + echo "PageTop[$mrtgname]:

Sessions

" +) >"$mrtg_config" mrtg "$mrtg_config" 2>/dev/null -rm -f $mrtg_config $wwwdir/ucs_*.htm* -echo "Session(s): $nrsessions" >$wwwdir/$mrtgname.txt +rm -f "$mrtg_config" "$wwwdir"/ucs_*.htm* +echo "Session(s): $nrsessions" >"$wwwdir/$mrtgname.txt" # Write HTML file -cat <<__EOT__ >$wwwdir/$indexhtm - - - - -__EOT__ -for file in $wwwdir/*-day.png; do - echo "

" >>$wwwdir/$indexhtm - cat "`echo \"$file\" | sed \"s/-day.png/.txt/\"`" >>$wwwdir/$indexhtm - echo "
" >>$wwwdir/$indexhtm - echo "
" >>$wwwdir/$indexhtm - echo "
" >>$wwwdir/$indexhtm - echo "
" >>$wwwdir/$indexhtm - echo "
" >>$wwwdir/$indexhtm - echo "

" >>$wwwdir/$indexhtm -done -cat <<__EOT__ >>$wwwdir/$indexhtm - - -__EOT__ - +( + echo '' + echo '' + echo '' + echo '' + for file in "$wwwdir"/*-day.png + do + echo '

' + cat "${file%-day.png}.txt" + echo '
' + echo "
" + echo "
" + echo "
" + echo "
" + echo '

' + done + echo '' + echo '' +) >"$wwwdir/$indexhtm" diff --git a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/univention-system-stats b/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/univention-system-stats old mode 100644 new mode 100755 index 128f1fa..3597439 --- a/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/univention-system-stats +++ b/branches/ucs-3.2/ucs-3.2-0/base/univention-maintenance/univention-system-stats @@ -32,17 +32,19 @@ date=$(date) log="/var/log/univention/system-stats.log" -cmds[0]="$(which df) -lhT" -cmds[1]="$(which ps) auxf" -cmds[2]="$(which top) -b -n2" -cmds[3]="$(which free)" -cmds[4]="$(which uptime)" -cmds[5]="$(which sensors)" -cmds[6]="$(which smbstatus)" +cmds=( + "df -lhT" + "ps auxf" + "top -b -n2" + "free" + "uptime" + "sensors" + "smbstatus" +) # print usage -function usage () { - echo usage: $(basename $0) [-h] +usage () { + echo usage: $(basename "$0") [-h] echo "This script logs some systems stats (df, free, ...) in \"$log\"." exit 0 @@ -59,23 +61,23 @@ done if [ ! -e "$log" ]; then : > "$log" fi -chmod 640 $log -chgrp adm $log +chmod 640 "$log" +chgrp adm "$log" # redirect output -exec 1>>"$log" -exec 2>/dev/null +exec >>"$log" 2>/dev/null echo "--- system stats for $date" -echo +echo -for cmd in "${cmds[@]}"; do - tool=${cmd/ */} - if [ -x "$tool" ]; then - echo "-> $cmd" - $cmd - echo - fi +for cmd in "${cmds[@]}" +do + set -- $cmd # IFS + tool=$(which "$1") || continue + [ -x "$tool" ] || continue + echo "-> $cmd" + $cmd # IFS + echo done echo "--- end system stats for $date"