Version 3.4 released in Feb. 2013
#!/bin/bash
#
#Published under the MIT license terms:
#Copyright (c) 2010-2013 Teo Ramirez
#Permission is hereby granted, free of charge, to any person obtaining a copy
#of this software and associated documentation files (the "Software"), to deal
#in the Software without restriction, including without limitation the rights
#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#copies of the Software, and to permit persons to whom the Software is
#furnished to do so, subject to the following conditions:
#The above copyright notice and this permission notice shall be included in
#all copies or substantial portions of the Software.
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
#THE SOFTWARE.
# PURPOSE:
# HDfree is a Bash script that watches if any partition is about to run out
# of free space and warns the user using a pop-up window. This will happen
# each time a mounted partition:
# -Has got more than 80% of its capacity in use and it has just got increased.
# -Has got 0% free space left. In this case, the script will keep on warning.
# The name of the script was not chosen wisely, since it watches not only HDs
# but all kinds of storage devices.
# USAGE:
# Options: see some pages bellow (function prepare_i18n)
# Exit code values: see at the bottom of this text.
# How to get it started: It depends on what you might want. In general terms,
# I guess the best way is putting the script in any place where it will be run
# as each user starts a X sesion. For instance, running KDE 3, do this:
# -Go to /home/yourcoolusername/.kde/autostart
# -Put a copy of this script there and make it executable or, alternatively,
# use any simple text editor and make a short script like this:
# #!/bin/bash
# /usr/local/bin/hdfree.sh -t 2 -w 60 -p 85 -l /var/log/hdfree.log
# -Test it by logging in and out and seeing when hdfree.stamp is present.
# -These parameters are good for testing purposes: --percentage 0 --debug
#
# Starting a script for each user poses the following
# Pros: - It makes sense to get it started only for graphical sesions.
# - Every user will see the alerts, or only some users or none at all,
# it's up to you, admin, to decide.
# Cons: -You will be running as many copies of the script as logged-in users.
# -If you don't use different log files, the only one will end messed up.
# -On most systems, non root users will not get the partitions' labels.
#
# You can also get it started from Cron/Anacron using the --exit parameter.
# In this way, the script will check usage once and exit right after.
#
# Last, starting the script from rc.local or alike, seems to be not the best idea:
# (If you trust me, stop reading here and don't get bored)
# First, note that when started from any system-wide script, $HOME could be
# unreliable. In those cases, and provided you have specified a log file,
# you could use it for knowing where the hdfree.stamp file had been created.
# Therefore, you should replace rm -f $HOME/.hdfree.stamp by
# rm -f `cat put_here_path_to_log_file|grep "hdfree.stamp"|sed s'/(main program) //'|sed s'/ was set.//'`
# Of course, if you put this in /home/you/.kde/shutdown, it would make the script
# to stop as soon as any user logs out. Anyway, all this stuff has to do with
# not giving out zombie pop-ups after stopping the script. If you were running
# in single-user mode and the system is going down, who cares about that?.
# DEPENDENCIES:
# There are no special ones. This script uses df to gather info about currently
# mounted partitions, which should be already present in almost every linux box
# out there. On the other hand, partition's labels are read by blkid, but if not
# avaliable or forbidden to run, the scrit will do without it. It also needs one of
# kdialog (types 1 & 2), zenity (type 4) or xmessage (type 3), unless you want to
# use plain console output.
# ISSUES:
# * The script should be started as a superuser in most systems. Otherwise,
# you could expect to find some trouble, notably that blkid could not be run
# (thus not providing the partitions' labels) or even getting no warnings at all.
#
# * Localization can lead to garbage characters. The script will refuse to run using
# any language other than english when xmessage is selected with the --override 3
# option. Also, it is not recommended to use i18n in non-UTF8 systems.
#
# * Don't touch the first three lines of this script. For some weird reason, CygWin will
# find trouble if you add/remove a single CR/LF. Leave it as is.
#
# * If you kill the script while it is displaying an alert, it could happen that the
# alert becomes a zombie process and will stay on your desktop forever, although
# this has been partly addressed in version 3.4.
#
# * Not a true bug, but annoying: if you run hdfree remotely, let's say using SSH, you will
# get alerts on your local desktop (provided that the required widget is avaliable).
# HISTORY:
# v1.x Oct-2009
# - Irrelevant, neither released nor tested by someone else apart of me.
# v2.0 Dec -2009
# - Although based on some ideas from v1, it was a complete rebuild from scratch.
# v2.1 Jan-2010
# - Just a polished and documented v2.0.
# v2.2 Jan-2010
# - Added kdialog yes/no popups; "--xmessage" option replaced for "--type".
# - Some i18n implemented (en, es and gl)
# - New parameter: --override (system language)
# - "--wait" now defaults to 10 seconds (formerly was 60).
# - "--log" now defaults to /dev/null (formerly was /var/log/hdfree.log).
# v2.3 Jan-2010
# - Tested under several distributions I found trouble with non UTF-8 systems and i18n.
# Partly fixed, but added it as an issue in the documentation.
# v2.4 Feb-2010
# - After some testing, I found that some distributions make weird devices that
# were seen as partitions. Same was happening with CDs and DVDs, so now the script
# only minds /dev/sd*, /dev/hd* and /dev/shm devices.
# - Now parameters are read and parsed in a more accurate way
# (previously the script tended to behave differently depending on their order).
# v2.5 Feb-2010
# - First released version.
# - Added CygWin support and further testing.
# - "Shebang" changed to #!/bin/bash
# v3.0 Mar-2010
# - Blkid now it is run only when any partition is mounted/unmounted, thus not forcing
# storage units to spin up for this script alone any more.
# - Fixed a confusing typo in the "usage" text (default idle time is 10 seconds, not 60)
# - Added a new parameter: --percentage. It works as a threshold: the script will only alert
# about partitions whose % in use has gone above its value. Nevertheless, alerts will still
# pop-up when any partition will be 100% full. Use --percentage 0 for testing purposes:
# the script will display an initial one-time pop-up for every mounted partition.
# - Some improvements made in order to make log files tinier. Even so, they can still get big.
# - The script now checks wether it is being run as a superuser or not.
# - Implemented some checking with the given parameters in order to assure they are valid.
# - It is possible to stop the script in a cleaner and safer way by deleting a special
# "flag file" (hdfree.stamp) in the user home folder.
# - Corrected a bug that could make the script not to be aware of invalid parameters.
# v3.1 Mar-2010
# - Added $PATH_TO_STAMP_FILE, usually = $HOME but uncertain for all cases. For instance, getting
# the script started by adding it to /etc/rc.d/rc.local in PCLOS, $HOME seemed not to have been
# set yet and took the / value. This behaviour could still remain but now we are sure that $HOME
# has not changed since the script started. Please, read further above these lines:
# "Usage" > "How to get it started"
# - Documentation has been extended a bit, mainly in the "Usage" and "Issues" sections.
# - Minor bug corrected: "PERCENTAGE_THRESHOLD=80 # 0 FORCES POP-UPS..." (changed the wrong 1 for the 0)
# v3.2 Jul-2010
# - Changes in get_partitions function in order to get definetively get rid of CDs and DVDs.
# - Some tweeks seen in http://www.cyberciti.biz/tips/shell-script-to-watch-the-disk-space.html
# - New parameter: --exit. When used, the script checks usage once and exits right after done.
#
# v3.3 Jul-2010
# - Fixed an issue with Ubuntu and auto-detected language.
#
# v3.4 Feb-2013
# - Added support for Zenity widgets and plain console output.
# - Default values changed: the script should run fine in most systems using no parameters.
# - Most alerts' processes will be properly terminated when the script exits.
# - Improved logging, either as own log or using the system logger.
# WHAT'S NEXT?:
# - Make the script autoinstallable as well as some TODOs that you can find throughout the code.
# - Eyecandy for console output: dialog (ncurses) and whiptail(newt).
# UPDATE March 2013: Surely replacing most of that stuff for EasyBashGUI
# - Other assorted improvements (see the mejoras-tweeks.txt document)
# - What do you propose??
# FEEDBACK:
# Please report bugs, improvements, translations, testings...
# Also, I would love to have the script packaged for some distributions. Anyone?
VERSION="3.4" # LET'S INITIALIZE SOME VARS.
LANG_IN_USE="en" # DEFAULT IN CASE LOCALE IS NOT PROPERLY DETECTED AND --override IS NOT USED.
DEBUGGING=0 # 1 FOR VERBOSE OUTPUT (ALL OUTPUT WILL BE DUMPED IN THE LOG, ANYWAY).
PERCENTAGE_THRESHOLD=80 # SAME THAN --percentage. 0 FORCES POPUPS TO SHOW UP IN ALL CASES (FOR TESTING)
WAIT_FOR_SECONDS=20 # SAME THAN --wait. IDLE WHILE WAITING FOR THE NEXT PARTITIONS INFO UPDATE.
SECONDS_ON_SCREEN=3 # DEPENDING ON THE TYPE OF ALERT, THEY WILL BE AUTOCLOSED IN A FEW SECONDS
WINDOW_TYPE=1 # THIS IS THE --type PARAMETER
# VALUE OF | WIDGET AND TYPE | ALERTS AUTOCLOSE| PROMPT "SHALL I STOP | OTHER INFO
# -t PARAM. | OF ALERT USED | IN SOME SECONDS | WATCHING THIS PART.?"|
# ----------+------------------+-----------------+----------------------+---------------------------
# 1 | KDialog passive | yes | no |
# 2 | Kdialog yes/no | no | yes |
# 3 | Xmessage | yes | yes | faulty in i18n'ed systems
# 4 | Zenity warning | yes | no |
# 5 | Console output | yes | yes |
#
# If --type is not defined or not avaliable in that system, the script will try 1, 4, 3 and, lastly, 5.
LOG='/dev/null' # SAME THAN --log PARAMETER
# GOT ENOUGH PERMISSIONS? YOU COULD USE /var/log/hdfree.log OR /tmp/hdfree.log, FOR INSTANCE.
# THE DEFAULT IS /dev/null THAT EQUALS TO NO LOGGING AT ALL. WARNING: LOG FILE CAN GROW FAST.
PATH_TO_STAMP_FILE=$HOME
function prepare_i18n { # NO PARAMETERS. IT SETS ALL i18n_ VARS.
case "$LANG_IN_USE" in
# IF YOU WANT TO CONTRIBUTE A TRANSLATION, USE THE LINES BELLOW AS TEMPLATE:
#---------------------------------------------------------------->8-- START OF TEMPLATE
en|en_US|en_UK) #ENGLISH
LANG_IN_USE="en" #PLEASE CHECK IF ANY CONFLICT WITH OTHER LANGUAGES COULD ARISE FOR USING ONLY 2 CHARS.
i18n_VERSION="HDfree $VERSION released under the MIT license terms.
(c) 2010-2013 teoramirez(a)gmail.com www.galinux.myftp.org"
i18n_USAGE="
HDfree is a bash script that watches if any partition is about to
run out of free space and warns the user using a pop-up window.
Usage:
hdfree [-v] [-h] [-d] [-l LOGFILE] [-w SECS] [-t TYPE] [-p INTEGER] [-e] [-o]
--version -v Print the version of this script and exit.
--help -h Print this help and exit.
--debug -d Dump debug info while running.
--log LOGFILE -l Log's path and name (default = use no log file at all).
Use the special token 'logger' (without quotes) to redirect
all info to /var/log/messages.
--wait SECONDS -w Wait for SECONDS (10-86400) until next check (default = 20)
--type TYPE -t Prefered type of window (default = kdialog passive):
1:kdialog passive 2:kdialog y/n 3:xmessage y/n (eng. only)
4:zenity warning 5:console. Fallback: 1>4>3>5
With 2, 3 & 5, the user can disable watching a partition.
--percentage -p Threshold: from 0 (testing purposes) to 100, that means
warning only when a partition is 100% full (default = 80)
--exit -e Check usage once, warn if needed and exit.
--override -o Override autodetected language and use instead:
en en_US en_UK
es es_ES
gl gl_ES
Example: ./hdfree.sh -o es -t 2 -w 200 -p 90 -d "
#Strings for 'passive kdialog' type windows:
#Example: "HD_LABEL" (hda2 mounted in /mnt/win) is 90% full."
i18n_MOUNTED_ON="mounted on";i18n_IS=" is ";i18n_FULL="% full.";i18n_WARNING="Warning"
#Strings for 'yes/no-kdialog' type windows:
i18n_WAIT_FOR_YES_NO="Stop watching this partition?"
#Strings for 'xmessage' type windows and console:
i18n_CLOSE="Close";i18n_STOP_WATCHING="Stop watching this partition";i18n_TIMEOUT="time out"
i18n_STOP_WATCHING_CONSOLE="Press <Enter> now to stop watching this partition"
# Strings for errors
i18n_UNKNOWN_OPTION="unknown option."
i18n_INVALID_WINDOW_TYPE="invalid window type: it must be 1, 2, 3, 4 or 5."
i18n_INVALID_PERCENTAGE="invalid percentage: it must be an integer from 0 to 100."
i18n_INVALID_PAUSE="invalid pause: it must be an integer from 4 to 86400 (one day)."
#--------------------------------------------------------------->8-- END OF TEMPLATE
;;
es|es_ES) # SPANISH/CASTILLIAN
LANG_IN_USE="es"
i18n_VERSION="HDfree $VERSION publicado bajo los términos de la licencia MIT.
(c) 2010-2013 teoramirez(a)gmail.com www.galinux.myftp.org"
i18n_USAGE="
HDfree es un guión de consola que vigila el espacio libre disponible en cada
partición, avisando al usuario mediante ventanas emergentes cuando proceda.
Uso:
hdfree [-v] [-h] [-d] [-l REGISTRO] [-w SEGNDS] [-t TIPO] [-p ENTERO] [-e] [-o]
--version -v Muestra la versión del guión y acaba.
--ayuda -h Muestra esta ayuda y acaba.
--depuracion -d Información de depuración en tiempo de ejecución.
--log REGISTRO -l Ruta completa del registro (ninguno por omisión).
Use la palabra 'logger' (sin comillas) para redirigir
toda la información a /var/log/messages.
--wait SEGUNDOS -w Espera entre comprobaciones (10-86400, 20 por omisión)
--tipo TIPO -t Tipo de ventana preferido (kdialog emergente por omisión):
1:kdialog emerg. 2:kdialog s/n 3:xmessage s/n (sólo inglés)
4:zenity aviso 5:consola. Orden de preferencia: 1>4>3>5
Con 2, 3 y 5, el usuario puede deshabilitar la supervisión.
--porcentaje -p Límite: desde 0 (para pruebas) hasta 100, para avisar sólo
en caso particiones llenas al 100% (80 por omisión)
--exit -e Comprobar una sola vez, avisar si es necesario y terminar.
--override -o Usar un idioma distinto al autodetectado:
en en_US en_UK
es es_ES
gl gl_ES
Example: ./hdfree.sh -o es -t 2 -w 200 -p 90 -d "
#Cadenas para ventanas tipo kdialog-pasivo:
#Ejemplo: "HD_LABEL" (hda2 mounted in /mnt/win) is 90% full."
i18n_MOUNTED_ON="montado en";i18n_IS=" está usando el ";i18n_FULL="% de su capacidad.";i18n_WARNING="Aviso"
#Cadenas para ventanas kdialog si/no:
i18n_WAIT_FOR_YES_NO="¿Dejar de vigilar esta partición?"
#Cadenas para ventanas xmessage y consola:
i18n_CLOSE="Cerrar";i18n_STOP_WATCHING="No vigilar más esta partición";i18n_TIMEOUT="tiempo agotado"
i18n_STOP_WATCHING_CONSOLE="Pulse <Entrar> ahora para dejar de vigilar esta partición"
#Cadenas para errores
i18n_UNKNOWN_OPTION="opción desconocida."
i18n_INVALID_WINDOW_TYPE="tipo de ventana no válido: debe ser 1, 2, 3, 4 o 5."
i18n_INVALID_PERCENTAGE="porcentaje no válido: debe ser un entero entre 0 y 100."
i18n_INVALID_PAUSE="pausa no válida: debe ser un entero entre 4 y 86400 (un día)."
;;
gl|gl_ES) # GALICIAN (SPAIN)
LANG_IN_USE="gl"
i18n_VERSION="HDfree $VERSION publicado baixo os termos da licenza MIT.
(c) 2010-2013 teoramirez(a)gmail.com www.galinux.myftp.org"
i18n_USAGE="
HDfree é un guión de consola que vixía o espazo libre dispoñible en cada
partición e advirte ao usuario con mensaxes emerxentes cando é necesario.
Uso:
hdfree [-v] [-h] [-d] [-l REXISTRO] [-w SEGS] [-t TIPO] [-p ENTEIRO] [-e] [-o]
--version -v Amosa a versión do guión e remata.
--axuda -h Amosa esta axuda e remata.
--depuracion -d Información de depuración en tempo de execución.
--log REXISTRO -l Ruta completa do rexistro (ningún por omisión).
Use o termo 'logger' (sen comillas) para redirixir
toda a información a /var/log/messages.
--wait SEGUNDOS -w Agardar entre comprobacions (10-86400, 20 por omisión)
--tipo TIPO -t Tipo de fiestra preferido (kdialog emerxente por omisión):
1:kdialog emerx. 2:kdialog s/n 3:xmessage s/n (só inglés)
4:zenity aviso 5:consola. Orde de preferencia: 1>4>3>5
Con 2, 3 e 5, o usuario pode deshabilitar a supervisión.
--porcentaxe -p Límite: dende 0 (para probas) ata 100, para avisar só
cando unha partición estea chea ao 100% (80 por omisión)
--exit -e Comprobar unha vez só, avisar se é necesario e saír.
--override -o Trocar a linguaxe autodetectada por unha das seguintes:
en en_US en_UK
es es_ES
gl gl_ES
Example: ./hdfree.sh -o es -t 2 -w 200 -p 90 -d "
#Mensaxes para fiestras tipo kdialog-pasivo.
#Exemplo: "HD_LABEL" (hda2 mounted in /mnt/win) is 90% full."
i18n_MOUNTED_ON="montado en";i18n_IS=" está a empregar o ";i18n_FULL="% da capacidade.";i18n_WARNING="Aviso"
#Mensaxes para fiestras kdialog si/non
i18n_WAIT_FOR_YES_NO="¿Deixar de vixiar esta partición?"
#Mensaxes para fiestras xmessage e consola
i18n_CLOSE="Pechar";i18n_STOP_WATCHING="Non vixiar máis esta partición";i18n_TIMEOUT="tempo esgotado"
i18n_STOP_WATCHING_CONSOLE="Prema <Entrar> agora para deixar de vixiar esta partición"
#Mensaxes para erros
i18n_UNKNOWN_OPTION="opción descoñecida."
i18n_INVALID_WINDOW_TYPE="tipo de fiestra non válido: cómpre empregar 1, 2, 3, 4 ou 5."
i18n_INVALID_PERCENTAGE="porcentaxe non válida: cómpre empregar un enteiro entre 0 e 100."
i18n_INVALID_PAUSE="pausa non válida: cómpre empregar un enteiro entre 4 e 86400 (un día)."
;;
*) #ANY OTHER LANGUAGE WILL DEFAULT INTO ENGLISH WITHOUT PREVENTING THE SCRIPT TO RUN.
LANG_IN_USE="en";show "(main program) unkwnown language: defaulting to english."
prepare_i18n # RE-RUN THIS FUNCTION
;;
esac
# LET'S SHOW "VERSION" BELOW "USAGE".
i18n_USAGE=$i18n_USAGE"
$i18n_VERSION
"
}
function show { # PARAMETERS: $1=string ; $2="important"... OR NOT.
# IT SENDS $1 TO STDOUT IF "DEBUGGING" IS "ON" OR IN CASE OF $2 SAYING THAT $1 IS AN "IMPORTANT" MESSAGE.
# IF WINDOW_TYPE IS 5, DISPLAY $1 ONLY WHEN DEBBUGING. ALSO, SEND $1 TO THE LOG FILE IN ALL CASES.
if [ "$LOG" != "logger" ];then
echo $1 >> $LOG
else
logger -t hdfree $1 2>/dev/null # IN CASE LOGGER IS NOT AVALIABLE, DON'T MESS THE OUTPUT WITH ERRORS
fi
if [ $DEBUGGING -eq 0 ];then
[ "$2" != "important" ] && return 0
[ $WINDOW_TYPE -eq 5 ] && return 0
fi
echo $1
}
function get_labels { #NO PARAMETERS. GIVES OUT PARTITIONS' LABELS IN VAR $ALL_LABELS.
# THIS FUNCTION IS CALLED ONLY IN THE EVENT OF CHANGES IN THE NUMBER OF MOUNTED PARTITIONS.
blkid -c /dev/null &>/dev/null
local AUX_RESULT=$? # IS BLKID AVALIABLE?
if [ $AUX_RESULT -eq 0 ];then
show "(fnc. get_labels) blkid is avaliable."
ALL_LABELS=`blkid -c /dev/null 2>/dev/null`
if [ "$ALL_LABELS" == "" ];then
show "(fnc. get_labels) blkid has reported no labels."
#THIS HAPPENED WITH PCLOS WHEN A NON ROOT USER STARTS THE SCRIPT.
fi
else
show "(fnc. get_labels) blkid is missing, not avaliable or faulty."
ALL_LABELS=""
fi
}
function get_partitions { #NO PARAMETERS
# (RE)READS MOUNTED PARTITIONS AND POPULATES A LOT OF VARS.
READ_PARTITIONS=`df --print-type --local -h -P 2>/dev/null|grep "\/dev\/[hs]d"` # LOOK FOR /DEV/HD* OR /DEV/SD*
READ_PARTITIONS=`echo "$READ_PARTITIONS";df -T --local -h -P 2>/dev/null|grep "\/dev\/shm"` # ADD /DEV/SHM
READ_PARTITIONS=`echo "$READ_PARTITIONS";df -T --local -h -P 2>/dev/null|grep ": "` # ADD CYGWIN DRIVES
READ_PARTITIONS=`echo "$READ_PARTITIONS"|grep -v "udf"` # EXCLUDE DVDs
READ_PARTITIONS=`echo "$READ_PARTITIONS"|grep -v "iso"` # EXCLUDE CDs
READ_PARTITIONS=`echo "$READ_PARTITIONS"|sed '/^$/d'` # REMOVE BLANK LINES (ISSUE WITH CYGDRIVE)
#I'M ONLY INTERESTED IN /DEV/HD OR /DEV/SD. I HOPE TO GET RID OF CDs, DVDs AND WEIRD DEVICES SEEN IN UBUNTU.
for LOOPING in `seq 1 100`;do
PARTITION_INFO=`echo "$READ_PARTITIONS"|sed -n "${LOOPING}p"` # CHOOSE THE #LOOPING LINE
if [ "$PARTITION_INFO" == "" ];then # NO MORE MOUNTED PARTITIONS?
LOOPING=$(( $LOOPING - 1 ))
show "(fnc. get_part.) $LOOPING partitions mounted."
return $LOOPING
fi
PARTITION[$LOOPING]=$PARTITION_INFO
PARTITION_DEV[$LOOPING]=`echo $PARTITION_INFO|cut -f1 -d\ |sed 's/[/]dev[/]//'`
# DESPITE NOT BEING ACCURATE, I PREFER /dev/shm TO BE DESCRIBED AS "ramdisk" INSTEAD OF "none".
if [ "`echo $PARTITION_INFO|grep "tmpfs"`" != "" ];then
PARTITION_DEV[$LOOPING]="RAMDISK"
fi
# SAME HERE: REPLACE "fuseblk" BY "ntfs" AND "vfat" BY "fat".
PARTITION_TYPE[$LOOPING]=`echo $PARTITION_INFO|cut -f2 -d\ |sed 's/fuseblk/ntfs/g'|sed 's/vfat/fat/g'`
PARTITION_PREVIOUS_FREE[$LOOPING]=${PARTITION_FREE[$LOOPING]}
PARTITION_FREE[$LOOPING]=`echo $PARTITION_INFO|cut -f6 -d\ |sed 's/%//'`
PARTITION_MOUNTED_ON[$LOOPING]=`echo $PARTITION_INFO|cut -f7 -d\ `
PARTITION_LABEL[$LOOPING]=`echo "$ALL_LABELS"|grep "${PARTITION_DEV[$LOOPING]}"|grep "LABEL"|sed 's/.*LABEL="//'|sed 's/".*//'`
# "BLKID" PROGRAM IS NOT A TRUE DEPENDENCY CAUSE I CAN DO WITHOUT IT.
# ONLY DRAWBACK IS THAT I WILL NOT DISPLAY THE LABELS (IF EVEN SET).
if [ "${PARTITION_LABEL[$LOOPING]}" == "" ];then
show "(fnc. get_part.) no label found for ${PARTITION_DEV[$LOOPING]}."
fi
done
}
function display_status { # NO PARAMETERS.
if [ $DEBUGGING -eq 1 ];then
show "(fnc. display_Status) current values:"
for LOOPING in `seq 1 $NUMBER_OF_PARTITIONS`;do
show "PART_INFO${LOOPING}=${PARTITION[$LOOPING]}"
# show "PART_DEV${LOOPING}=${PARTITION_DEV[$LOOPING]}"
# show "PART_TYPE${LOOPING}=${PARTITION_TYPE[$LOOPING]}"
# show "PART_FREE${LOOPING}=${PARTITION_FREE[$LOOPING]}"
# show "PART_PREVIOUS_FREE${LOOPING}=${PARTITION_PREVIOUS_FREE[$LOOPING]}"
# show "PART_MOUNTED_ON${LOOPING}=${PARTITION_MOUNTED_ON[$LOOPING]}"
show "PART_LABEL${LOOPING}=${PARTITION_LABEL[$LOOPING]} PART_WATCH${LOOPING}=${PARTITION_WATCH[$LOOPING]}"
done
fi
}
function popup { # ONLY ONE PARAMETER MUST BE A PARTITION NUMBER. IT BUILDS AND DISPLAYS A POP-UP THAT WARNS THE USER WHEN NECESSARY.
AUX=$1 #COMPOSE THE TEXT TO BE SHOWN; IF NO LABEL OR BLKID IS NOT AVALIABLE, THE MESSAGE WILL BE FORMATED SLIGHTLY DIFFERENT.
if [ "${PARTITION_LABEL[$AUX]}" != "" ];then
POPUP_TEXT=`echo "\"${PARTITION_LABEL[$AUX]}\" (${PARTITION_DEV[$AUX]} ${i18n_MOUNTED_ON} ${PARTITION_MOUNTED_ON[$AUX]})$i18n_IS${PARTITION_FREE[$AUX]}${i18n_FULL}"`
else
POPUP_TEXT=`echo "${PARTITION_DEV[$AUX]} ${i18n_MOUNTED_ON} ${PARTITION_MOUNTED_ON[$AUX]}$i18n_IS${PARTITION_FREE[$AUX]}${i18n_FULL}"|sed 's/ [/] / \/ (root) /'`
fi
# SHALL I USE 1=KDIALOG-PASSIVE, 2=KDIALOG-YES/NO OR 3=XMESSAGE? (... AND NO NEED TO CHECK FOR INVALID VALUES, IT WAS ALREADY DONE)
case $WINDOW_TYPE in
1)
# WHEN "PASSIVEPOPUP KDIALOG" IS PREFERED, USER CAN NOT DISABLE WATCHING PARTITIONS.
(kdialog --passivepopup "$POPUP_TEXT" "$SECONDS_ON_SCREEN")& # VISIBLE FOR SOME SECONDS.
ALERT_PID=$!;sleep 1;sleep $SECONDS_ON_SCREEN
;;
2)
kdialog --title "$i18n_WARNING" --caption "$i18n_WARNING" --warningyesno "$POPUP_TEXT\n $i18n_WAIT_FOR_YES_NO"
# NOTE THAT TYPE 2 HALTS THE SCRIPT UNTIL THE ALERT IS CLOSED
if [ $? -eq 0 ]; then
return 0 # 0 MEANS THAT USER WANTS ME TO STOP WATCHING
fi
;;
3)
xmessage -center -timeout $SECONDS_ON_SCREEN -default "$i18n_CLOSE" -buttons "$i18n_CLOSE","$i18n_STOP_WATCHING" "$POPUP_TEXT"
if [ $? -eq 102 ]; then
return 0 # 0 MEANS THAT USER WANTS ME TO STOP WATCHING
fi
;;
4)
#v34 added support for zenity
(zenity --title "$i18n_WARNING" --warning --text "$POPUP_TEXT" --timeout "$SECONDS_ON_SCREEN")&
ALERT_PID=$!;sleep 1;sleep $SECONDS_ON_SCREEN
;;
5)
#v34 added support for plain console output
echo "$i18n_WARNING: $POPUP_TEXT"
read -t "$SECONDS_ON_SCREEN" -p "${i18n_STOP_WATCHING_CONSOLE}... " AUX
# PRESSING ENTER BEFORE TIMEOUT MEANS "STOP WATCHING"
[ $? -eq 0 -a "$AUX" == '' ] && echo "${i18n_STOP_WATCHING}." && return 0
echo "$i18n_TIMEOUT"
;;
esac
return 1 #1 MEANS TO KEEP ON WATCHING THE PARTITION
}
function check_free { # NO PARAMETERS. IT CHECKS WETHER IT IS NECCESARY TO SHOW SOME WARNING POP-UPS OR NOT.
ALERT_PID='[not set]' # reset PIDs of alerts
[ $WINDOW_TYPE -eq 5 -a $DEBUGGING -eq 0 ] && clear 2>/dev/null # CLEAR CONSOLE BEFORE NEXT CHECK
for LOOPING in `seq 1 $NUMBER_OF_PARTITIONS`;do
AUX1=${PARTITION_PREVIOUS_FREE[$LOOPING]}
AUX2=${PARTITION_FREE[$LOOPING]}
AUX3=${PARTITION_WATCH[$LOOPING]}
show "(fnc. check_free) ${PARTITION_DEV[$LOOPING]} had $AUX1% in use and now is $AUX2%."
if [ $AUX3 -eq 1 ];then # IF THAT PARTITION MUST BE WATCHED...
# ...SEE IF % USED HAS RAISED AND THE NEW VALUE IS GREATER THAN $PERCENTAGE_THRESHOLD,
# ALTHOUGH NOT REACHING 100$ YET.
if [ $AUX1 -lt $AUX2 -a $AUX2 -gt $PERCENTAGE_THRESHOLD -a $AUX2 -ne 100 ];then
show "(fnc. check_free) pop-up: ${PARTITION_DEV[$LOOPING]} is currently ${PARTITION_FREE[$LOOPING]}% full." "important"
popup $LOOPING
PARTITION_WATCH[$LOOPING]=$?
show "(fnc. check_free) new alert's PID is $ALERT_PID."
fi
if [ $AUX2 -eq 100 ];then # SEE IF % USED IS 100%
show "(fnc. check_free) pop-up: ${PARTITION_DEV[$LOOPING]} used capacity is 100%!" "important"
# YOU MAY WISH TO PUT HERE ANY COMMAND TO AUTOMATICALLY GET SOME FREE ROOM IN YOUR PARTITION, LIKE CLEANING /TMP FOR
# INSTANCE. PERSONALLY, I FIND USEFUL TO PERFORM A find $HOME -name 'core.[0-9][0-9]*' -size +10000k -type f -delete
# FOR DELETING HUGE ERROR DUMP FILES WHEN RUNNING PCLOS.
popup $LOOPING
PARTITION_WATCH[$LOOPING]=$?
show "(fnc. check_free) new alert's PID is $ALERT_PID."
fi
if [ ${PARTITION_WATCH[$LOOPING]} -eq 0 ];then
show "(fnc. check_free) user has just disabled alerts for ${PARTITION_DEV[$LOOPING]}." "important"
fi # IF LOGGING IN A REAL FILE, I DON'T WANT TO POPULATE IT WITH THOUSANDS "DISABLED XXX PARTITION" LINES.
# THAT'S WHY THE ONE-TIME WARNING ABOVE IS "IMPORTANT" AND, ON THE CONTRARY, NOT THE ONE BELLOW (JUST REMINDING).
else
show "(fnc. check_free) alerts for ${PARTITION_DEV[$LOOPING]} are disabled."
fi
done
}
function initialize_watch_partition_flags { # NO PARAMETERS. FILLS UP THE ARRAY WITH FLAGS MEANING "Yes, keep on checking this partition, please".
for LOOPING in `seq 1 $NUMBER_OF_PARTITIONS`;do
PARTITION_WATCH[$LOOPING]=1 # 1=PLEASE, WATCH THIS PARTITION; 0=DON'T.
done
}
function validate_integer_var { # TEST IF AN INTEGER ($1) IS IN THE GIVEN RANGE ($2-$3). IT GIVES BACK 0 IF IT IS TRUE, OTHERWISE 1.
if ! [ $1 -eq $1 2> /dev/null ]; then # BASH RETURNS FALSE WHEN FAILING IN THE COMPARISON. THEREFORE, FALSE MEANS $1 IS NOT AN INTEGER.
return 1 # NOT A INTEGER, PERHAPS EVEN A NON NUMERIC DATA.
fi
if [ $1 -ge $2 -a $1 -le $3 ];then # SEE IF $2<=$1<=$3
return 0 # YES, $1 FALLS INTO THE $2-$3 RANGE.
fi
return 1 # $1 IS AN INTEGER BUT OUT OF THE GIVEN RANGE.
}
# ---------------- MAIN PROGRAM ---------------------------
trap 'show "(trap) killing alert(s) with PID $ALERT_PID";kill $ALERT_PID 2>/dev/null ;exit 3' 2 15
# This kills every type 1 or 4 popup after Ctrl-C (SIGINT) or Term signal (SIGTERM)
# TODO: try to nicely close types 2 & 3 with sort of
# [ $WINDOW_TYPE -eq 2 ] && ALERT_PID=`pidof kdialog`
# [ $WINDOW_TYPE -eq 3 ] && ALERT_PID=`pidof xmessage`
KDIALOG_IS_AVALIABLE="no"
ZENITY_IS_AVALIABLE="no"
XMESSAGE_IS_AVALIABLE="no"
# 'Which' should be avaliable on most boxes but just in case, we try alternative methods.
kdialog -v &>/dev/null && KDIALOG_IS_AVALIABLE="yes" # RUNNING KDE?
which kdialog &>/dev/null; [ $? -eq 0 ] && KDIALOG_IS_AVALIABLE="yes"
zenity --version &>/dev/null && ZENITY_IS_AVALIABLE="yes" # RUNNING GNOME?
which zenity &>/dev/null; [ $? -eq 0 ] && ZENITY_IS_AVALIABLE="yes"
xmessage &>/dev/null; [ $? -eq 1 ] && XMESSAGE_IS_AVALIABLE="yes"
which xmessage &>/dev/null; [ $? -eq 0 ] && XMESSAGE_IS_AVALIABLE="yes"
AUTODETECTED_LANG="`env | grep LANG= | cut -d "=" -f 2 | cut -b 1-2 | head -n 1`" # FIND OUT THE LOCALE LANGUAGE AND PICK ONLY THE 2 INITIAL CHARS.
LANG_IN_USE=$AUTODETECTED_LANG # USER COULD OVERRIDE THE AUTODETECTED LANG WITH THE -o OPTION.
LOOP_ONCE_AND_EXIT=0 # BY DEFAULT, THE SCRIPT WILL LOOP ENDLESSLY
PARAM="" # IN CASE OF ERROR, IT CONTAINS A PARAMETER TO BE DISPLAYED IN SOME ERROR DESCRIPTIONS.
TASK_TO_DO="run the script" # BY DEFAULT, THIS IS WHAT I'M SUPPOSED TO DO.
PREFERED_LANG="[not set]" # SAME VALUE THAN --override PARAM
while [ $# -gt 0 ] # PROCCESS PARAMETERS, IF ANY.
do # THE SCRIPT WILL GIVE OUT AN EXIT CODE (SEE IN THE BOTTOM)
case $1 in
--debug|-D|-d|--depuracion) # "DEPURACION" IS BOTH A SPANISH AND GALICIAN TERM.
DEBUGGING=1
;;
--override|-O|-o)
PREFERED_LANG=$2
LANG_IN_USE=$PREFERED_LANG
shift
;; # QUITE WIERD BUT I'M TRANSLATING A FEW OPTIONS IN THE LINES BELLOW:
--percentage|-P|-p|--porcentaje|--porcentaxe) # "PORCENTAJE" IS SPANISH; "PORCENTAXE" IS GALICIAN.
PERCENTAGE_THRESHOLD=$2
shift
;;
--type|-T|-t|--tipo) # "TIPO" IS BOTH A SPANISH AND GALICIAN TERM.
PARAM=$1
WINDOW_TYPE=$2
shift
;;
--wait|-W|-w)
WAIT_FOR_SECONDS=$2
shift
;;
--exit|-E|-e)
LOOP_ONCE_AND_EXIT=1
;;
--log|-L|-l|--registro|--rexistro) # "REGISTRO" IS SPANISH; "REXISTRO" IS GALICIAN
LOG=$2
shift
;;
--version|-V|-v)
TASK_TO_DO="display version"
;;
--help|-H|-h|--ayuda|--axuda) # "AYUDA" IS SPANISH; "AXUDA" IS GALICIAN.
TASK_TO_DO="display usage"
;;
*)
TASK_TO_DO="display error"
PARAM=$1
;;
#*) break ;; # string
esac
shift
done
# EXITING WITH 0 MEANS THAT PARAMETERS HAVE BEEN SUCCESSFULLY PARSED.
[ "$LOG" != "logger" ] && date>$LOG # START A NEW LOG FILE ( I COULDN'T HAVE DONE IT UP BEFORE CAUSE I NEEDED FIRST TO READ THE "--log" PARAMETER)
show "(main program) language in -o parameter is $PREFERED_LANG."
AUX=$?
prepare_i18n #GET EVERYTHING TRANSLATED.
if [ $AUX -ne 0 ];then
PARAM=`echo "$PARAM $i18n_UNKNOWN_OPTION";echo "$i18n_USAGE"`
echo "$PARAM"
exit 1
fi
if [ "$TASK_TO_DO" == "display error" ];then
PARAM=`echo "$PARAM $i18n_UNKNOWN_OPTION";echo "$i18n_USAGE"`
echo "$PARAM"
exit 1
fi
if [ "$TASK_TO_DO" == "display usage" ];then
PARAM=`echo "$i18n_USAGE"`
echo "$PARAM"
exit 0
fi
if [ "$TASK_TO_DO" == "display version" ];then
PARAM=`echo "$i18n_VERSION"`
echo "$PARAM"
exit 0
fi
validate_integer_var $WINDOW_TYPE 1 5
if [ $? -ne 0 ];then
PARAM=`echo "$PARAM $WINDOW_TYPE $i18n_INVALID_WINDOW_TYPE";echo "$i18n_USAGE"`
echo "$PARAM"
exit 2
fi
if [ $WINDOW_TYPE -le 2 -a "$KDIALOG_IS_AVALIABLE" == "no" ];then
#v34: window type will not halt the program
#PARAM=`echo "$i18n_KDIALOG_NOT_AVALIABLE";echo "$i18n_USAGE"`
#echo "$PARAM"
#exit 3
show "(main program) window type $WINDOW_TYPE not avaliable: trying with 4 (zenity)"
WINDOW_TYPE=4
fi
if [ $WINDOW_TYPE -eq 4 -a "$ZENITY_IS_AVALIABLE" == "no" ];then
#v34: window type will not halt the program
#PARAM=`echo "$i18n_KDIALOG_NOT_AVALIABLE";echo "$i18n_USAGE"`
#echo "$PARAM"
#exit 3
show "(main program) window type 4 (zenity) not avaliable: trying with 3 (xdialog)"
WINDOW_TYPE=3
fi
if [ $WINDOW_TYPE -eq 3 -a "$XMESSAGE_IS_AVALIABLE" == "no" ];then
show "(main program) window type 3 (xmessage) not avaliable: using 5 (console output)"
WINDOW_TYPE=5
fi
if [ $WINDOW_TYPE -eq 3 -a "$LANG_IN_USE" != "en" ];then # XMESSAGE SEEMS CAN NOT DEAL WITH i18n IN UTF-8
show "(main program) window type 3 (xmessage) only avaliable in english: changing language"
LANG_IN_USE="en";prepare_i18n #GET EVERYTHING TRANSLATED... AGAIN
fi
validate_integer_var $PERCENTAGE_THRESHOLD 0 100 # PARAMS: VAR TO BE TESTED AND RANGE OF VALID VALUES
if [ $? -ne 0 ];then
PARAM=`echo "$i18n_INVALID_PERCENTAGE";echo "$i18n_USAGE"`
echo "$PARAM"
exit 5
fi
validate_integer_var $WAIT_FOR_SECONDS 10 86400 # 86400 EQUALS A DAY
if [ $? -ne 0 ];then
PARAM=`echo "$i18n_INVALID_PAUSE";echo "$i18n_USAGE"`
echo "$PARAM"
exit 6
fi
# IF I'M HERE, THAT MEANS THAT THE PROGRAM SHALL RUN AND ENTER IN THE ENDLESS LOOP
show "(main program) autodetected language is $AUTODETECTED_LANG."
show "(main program) lang. actually in use is $LANG_IN_USE."
if [ $LOOP_ONCE_AND_EXIT -eq 0 ];then # IF NOT RUNNING IN ONE-SHOT MODE THEN CREATE hdfree.stamp
echo "Delete this file for stopping hdfree." > $PATH_TO_STAMP_FILE/.hdfree.stamp 2>/dev/null # IF IT DOES NOT EXIST, THE SCRIPT WILL EXIT.
else
show "(main program) --exit invoked: I will not create hdfree.stamp."
fi
if ! [ -e "$PATH_TO_STAMP_FILE/.hdfree.stamp" ];then # HDFREE IS A FLAG: IF MISSING, THE SCRIPT WILL STOP AND EXIT.
show "(main program) $PATH_TO_STAMP_FILE/.hdfree.stamp not set: stop after 1 loop." "important"
else
show "(main program) $PATH_TO_STAMP_FILE/.hdfree.stamp was succesfully set." # <<< ADDED IN VERSION 3.1
fi
show "(main program) kdialog avaliable: $KDIALOG_IS_AVALIABLE."
show "(main program) zenity avaliable: $ZENITY_IS_AVALIABLE."
show "(main program) xmessage avaliable: $XMESSAGE_IS_AVALIABLE."
show "(main program) threshold of alerts is $PERCENTAGE_THRESHOLD%."
# IF "PERCENTAGE"=0, THE USER WANTS A TESTING POPUP FOR EACH PARTITION BUT IT COULD HAPPEN THAT SOME OF THEM REPORT 0% USED SPACE.
# IN THAT CASE, FUNCTION "CHECK_FREE" WOULD NEVER DISPLAY A POP-UP, SO I NEED "PERCENTAGE" TO BE LESSER.
if [ $PERCENTAGE_THRESHOLD -eq 0 ];then
PERCENTAGE_THRESHOLD=-1
fi
#BLKID MAY NOT WORK FOR A NORMAL USER. AL LEAST, WE WILL BE WARNED.
[[ "$(id -u)" != "0" ]] && show "(main program) hdfree is NOT running as superuser." "important"||show "(main program) hdfree is running as superuser."
get_labels
get_partitions
NUMBER_OF_PARTITIONS=$? # FUNCTION "GET_PARTITIONS" GIVES OUT ITS NUMBER.
# SETTING THINGS FOR AN INITIAL ONE-TIME WARNING IF ANY PARTITION IS ALREADY ABOVE $PERCENTAGE_THRESHOLD WHEN THE SCRIPT STARTS.
for LOOPING in `seq 1 $NUMBER_OF_PARTITIONS`;do
PARTITION_FREE[$LOOPING]=-1 # I NEED ITS VALUE BELLOW ZERO, OTHERWISE THE TESTING INITIAL WARNING WOULD NOT OCCUR IF PARTITION IS 0% USED.
done
# FILLS UP THE ARRAY WITH FLAGS MEANING "Yes, keep on checking this partition, please".
initialize_watch_partition_flags # AT FIRST I WANT ALL PARTITIONS TO BE WATCHED. LATER ON, THE USER COULD BE ASKED ABOUT IT.
show "(main program) hdfree has started watching."
ALERT_PID='' # Used for killing alerts when exiting
# THIS IS THE MAIN LOOP
for (( ; ; ));do
# HAS "NUMBER_OF_PARTITIONS" CHANGED? (MAYBE A REMOVABLE DEVICE WAS PLUGGED, FOR INSTANCE)
PREVIOUS_NUMBER_OF_PARTITIONS=$NUMBER_OF_PARTITIONS
get_partitions
NUMBER_OF_PARTITIONS=$?
# IS IT THE SAME AMOUNT OF MOUNTED PARTITIONS THAN PREVIOUSLY?
if [ $PREVIOUS_NUMBER_OF_PARTITIONS -eq $NUMBER_OF_PARTITIONS ];then
display_status # EVERYTHING WILL BE LOGGED IN ANY CASE BUT NOT ACTUALLY DISPLAYED UNLESS -d PARAMETER HAS BEEN SET.
check_free # IT CAN CALL IN TURN THE "POPUP" FUNCTION.
if [ $LOOP_ONCE_AND_EXIT -eq 1 ];then # RUNNING IN ONE-SHOT MODE?
show "(main program) --exit parameter was invoked: will stop now."
#show "(main program) killing alert(s) with PID $ALERT_PID"
#kill $ALERT_PID 2>/dev/null
exit 0
fi
if ! [ -e "$PATH_TO_STAMP_FILE/.hdfree.stamp" ];then # IF YOU WANT TO STOP THE SCRIPT IN A SAFE WAY, JUST DELETE HDFREE.STAMP
show "(main program) $PATH_TO_STAMP_FILE/.hdfree.stamp not present: stopping now." "important"
#show "(main program) killing alert(s) with PID $ALERT_PID"
#kill $ALERT_PID 2>/dev/null
exit 0
fi
sleep $WAIT_FOR_SECONDS
else
get_labels
#get_partitions
# ON "N_OF_PARTITIONS" CHANGES, VARS GET MESSED UP, SO I DON'T RUN "CHECK_FREE".
initialize_watch_partition_flags
# TODO: I FORGOT ABOUT THE PREVIOUS ZEROES, SO I WILL CHECK ALL PARTITIONS AGAIN,
# REGARDLESS USER HAD DISABLED CHECKING ANY OF THEM. IN OTHER WORDS: EACH TIME THE TABLE OF PARTITIONS CHANGES,
# I WILL WARN ABOUT ALL OF THEM, LIKE IN THE BEGINNING. NO MATTER IF THE USER WANTED ANY NOT TO BE SUPERVISED.
show "(main program) number of partitions was $PREVIOUS_NUMBER_OF_PARTITIONS and now is $NUMBER_OF_PARTITIONS." "important"
fi
done
# NO NEED FOR A FINAL "exit" BECAUSE THE SCRIPT SHOULD BE TRAPPED IN THE ENDLESS LOOP. IF NOT THE CASE, POSSIBLE RETURN VALUES ARE:
# 0=SCRIPT HAS STOPPED BECAUSE --help, --version or --exit HAVE BEEN INVOKED OR hdfree.stamp IS MISSING.
# In all cases, 0 means "the ending was expected".
# 1=UNKOWN OPTION FOUND IN PARAMETERS.
# 2=INVALID TYPE OF WINDOW (--type MUST BE 1, 2, 3 OR 4)
# 3=EXITED THROUGH THE TRAP FUNCIONT, WETHER FOR CTRL-C PRESSED OR A TERM SIGNAL.
# Until version 3.4, the 3 exit code was "3=KDIALOG IS NOT AVALIABLE: MUST USE --type 3 (XMESSAGE)"
# 4 NOT USED. Until version 3.4 meant "CAN'T USE --type 3 AND ANY LANGUAGE OTHER THAN ENGLISH."
# 5=INVALID DATA SUPPLIED FOR --percentage (MUST BE AN INTEGER FROM 0 TO 100)
# 6=INVALID DATA SUPPLIED FOR --wait (MUST BE AN INTEGER FROM 1 TO 86400)
Version 3.3, Pop-up (type 1), KDE4, PClinuxOS
 |
Version 2.5, Warning (type 2), KDE, PClinuxOS
 |
Version 2.5, Xmessage (type 3), KDE, PClinuxOS
 |
Version 3.0, Pop-up (type 1), KDE, Galinux-Slax
 |
Version 3.0, Warning (type 2), KDE, OpenSuse
 |
Version 2.5, Pop-up (type 1), Fluxbox+KDE, Galinux-Slax
 |
Version 2.5, Xmessage (type 3), Gnome, Ubuntu
 |
Version 3.0, Xmessage (type 3), Fluxbox, Cygwin |