Compare commits
4 Commits
bfb46f8c31
...
c4e251eeda
Author | SHA1 | Date | |
---|---|---|---|
c4e251eeda | |||
a52a184617 | |||
3b4b6a38d9 | |||
695cb2e9f5 |
365
check_systemd.sh
Executable file
365
check_systemd.sh
Executable file
@ -0,0 +1,365 @@
|
||||
#!/bin/bash
|
||||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
#~ Nom : check_systemd
|
||||
#~ Description : Plugin Nagios pour tester si un service est démarré/activé/arrété
|
||||
#~ Auteur : Etienne Girault <etienne.girault@gmail.com>
|
||||
#~
|
||||
#~ Usage : [-h] [-D] [-V]
|
||||
#~
|
||||
#~ Options : -h, --help ; Affiche l'aide
|
||||
#~ Options : -V, --version ; Affiche la version
|
||||
#~ Options : -D, --debug ; Mode debug
|
||||
#~ Options : -n ; Nom de l'ensemble de service
|
||||
#~ Options : -c ; Service critique, retour critique si service stop, warning si disable
|
||||
#~ Options : -w ; Service warning, retour warning si service stop
|
||||
#~ Options : -s ; Service non nécessaire, retourne toujours ok
|
||||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
# Déclaration des variables
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
script_name="$(grep '^#~ Nom' "$0" | sed 's/^.*: //')"
|
||||
script_version="$(grep '^#~ v' "$0" | tail -1 | sed -e 's/^#~ //' -e 's/ *\-.*$//')"
|
||||
|
||||
PLUGINDIR=/usr/local/nagios/libexec
|
||||
. $PLUGINDIR/utils.sh
|
||||
|
||||
compteur_service=0
|
||||
declare -A services_status
|
||||
declare -A critical_report
|
||||
declare -A warning_report
|
||||
declare -A silent_report
|
||||
declare -A running_report
|
||||
|
||||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
# Déclaraition des fonctions
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
print_script_name_version() { echo "$script_name $script_version" && sed -n '/^#~ Version/,$p' "$0" | grep '^#~' | sed 's/^#~ //'; }
|
||||
print_script_description() { grep '^#~ Description' "$0" | sed 's/^.*: //'; }
|
||||
print_script_usage() { grep '^#~ Usage' "$0" | sed -e 's/^.*: //' -e '1 s/^/Usage: '"$script_name"' /' -e '2,$ s/^/'"$(printf '%*s' "$(echo "Usage: $script_name" | wc -c)")"'/'; }
|
||||
print_script_options() { echo "Options" && grep '^#~ Options' "$0" | sed -e 's/^.*://' -e 's/^ --/ --/' | column -ts \;; }
|
||||
print_script_help() { echo "$script_name $script_version" && print_script_description && print_script_usage && print_script_options; }
|
||||
|
||||
# Vérifie l'état actuel, ne peut qu'agraver l'état
|
||||
# $1 : Etat
|
||||
change_state() {
|
||||
case $1 in
|
||||
$STATE_CRITICAL) current_state=$1;;
|
||||
$STATE_WARNING) [[ "$current_state" = "$STATE_CRITICAL" ]] && return || current_state=$1;;
|
||||
$STATE_UNKNOWN) [[ "$current_state" = "$STATE_CRITICAL" || "$current_state" = "$STATE_WARNING" ]] && return || current_state=$1;;
|
||||
$STATE_OK) [[ "$current_state" = "$STATE_CRITICAL" || "$current_state" = "$STATE_WARNING" || "$current_state" = "$STATE_UNKNOWN" ]] && return || current_state=$1;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Ajoute l'etat du service dans le tableau de la liste des service
|
||||
# $1 : numéro du service
|
||||
# $2 : nom du service
|
||||
# $3 : criticité du service
|
||||
# $4 : etat du service (0=running, 1=not running, 2=disable, 3=does not exist)
|
||||
service_report () {
|
||||
services_status[$1]=$2
|
||||
case $3 in
|
||||
"critical")
|
||||
case $4 in
|
||||
0) running_report[$1]=$2
|
||||
change_state $STATE_OK;;
|
||||
1|3) critical_report[$1,0]=$2
|
||||
critical_report[$1,1]=$4
|
||||
change_state $STATE_CRITICAL;;
|
||||
2) warning_report[$1,0]=$2
|
||||
warning_report[$1,1]=$4
|
||||
change_state $STATE_WARNING;;
|
||||
esac;;
|
||||
"warning")
|
||||
case $4 in
|
||||
0|2) running_report[$1]=$2
|
||||
change_state $STATE_OK;;
|
||||
1|3) warning_report[$1,0]=$2
|
||||
warning_report[$1,1]=$4
|
||||
change_state $STATE_WARNING;;
|
||||
esac;;
|
||||
"silent")
|
||||
if [ $4 = 0 ]; then
|
||||
running_report[$1]=$2
|
||||
else
|
||||
silent_report[$1,0]=$2
|
||||
silent_report[$1,1]=$4
|
||||
fi
|
||||
change_state $STATE_OK;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Reception de signaux d'interruptions
|
||||
trap 'exit 1' INT TERM
|
||||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
# Gestion des options
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
while getopts ":-:hVDn:c:w:s:" OPTION; do
|
||||
case $OPTION in
|
||||
h) print_script_help; exit;;
|
||||
V) print_script_name_version; exit;;
|
||||
D) set -x;;
|
||||
n) namegroup=$OPTARG;;
|
||||
c) critical_service="${critical_service} $OPTARG";;
|
||||
w) warning_service="${warning_service} $OPTARG";;
|
||||
s) silent_service="${silent_service} $OPTARG";;
|
||||
:) ;;
|
||||
-) case $OPTARG in
|
||||
help) print_script_help; exit;;
|
||||
version) print_script_name_version; exit;;
|
||||
debug) set -x;;
|
||||
esac ;;
|
||||
*) ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
# Début du script
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
|
||||
# if [[ $# -ne 1 ]]; then
|
||||
# echo "Usage: ${0##*/} <service name>"
|
||||
# exit $STATE_UNKNOWN
|
||||
# fi
|
||||
|
||||
if [[ "$critical_service" ]]; then
|
||||
|
||||
for service in $critical_service; do
|
||||
|
||||
status=$(systemctl is-enabled $service 2>/dev/null)
|
||||
return_code=$?
|
||||
|
||||
if [[ -z "$status" ]]; then
|
||||
service_report "$compteur_service" "$service" "critical" 3
|
||||
else
|
||||
if systemctl --quiet is-active $service; then
|
||||
if [[ $return_code -ne 0 ]]; then
|
||||
service_report "$compteur_service" "$service" "critical" 2
|
||||
else
|
||||
service_report "$compteur_service" "$service" "critical" 0
|
||||
fi
|
||||
else
|
||||
service_report "$compteur_service" "$service" "critical" 1
|
||||
fi
|
||||
fi
|
||||
((compteur_service++))
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ "$warning_service" ]]; then
|
||||
|
||||
for service in $warning_service; do
|
||||
status=$(systemctl is-enabled $service 2>/dev/null)
|
||||
return_code=$?
|
||||
|
||||
if [[ -z "$status" ]]; then
|
||||
service_report "$compteur_service" "$service" "warning" 3
|
||||
else
|
||||
if systemctl --quiet is-active $service; then
|
||||
if [[ $return_code -ne 0 ]]; then
|
||||
service_report "$compteur_service" "$service" "warning" 2
|
||||
else
|
||||
service_report "$compteur_service" "$service" "warning" 0
|
||||
fi
|
||||
else
|
||||
service_report "$compteur_service" "$service" "warning" 1
|
||||
fi
|
||||
fi
|
||||
((compteur_service++))
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ "$silent_service" ]]; then
|
||||
|
||||
for service in $silent_service; do
|
||||
status=$(systemctl is-enabled $service 2>/dev/null)
|
||||
return_code=$?
|
||||
|
||||
if [[ -z "$status" ]]; then
|
||||
service_report "$compteur_service" "$service" "silent" 3
|
||||
else
|
||||
if systemctl --quiet is-active $service; then
|
||||
if [[ $return_code -ne 0 ]]; then
|
||||
service_report "$compteur_service" "$service" "silent" 2
|
||||
else
|
||||
service_report "$compteur_service" "$service" "silent" 0
|
||||
fi
|
||||
else
|
||||
service_report "$compteur_service" "$service" "silent" 1
|
||||
fi
|
||||
fi
|
||||
((compteur_service++))
|
||||
done
|
||||
fi
|
||||
|
||||
case $current_state in
|
||||
$STATE_CRITICAL)
|
||||
for (( service_number=0; service_number<=$compteur_service-1; service_number++ )); do
|
||||
if [[ ${critical_report[$service_number,0]} != "" ]]; then
|
||||
case ${critical_report[$service_number,1]} in
|
||||
1) case $crit_not_running in
|
||||
"") crit_not_running_information="${critical_report[$service_number,0]}";;
|
||||
1) crit_not_running_information="$crit_not_running_information and ${critical_report[$service_number,0]}";;
|
||||
*) crit_not_running_information="${critical_report[$service_number,0]}, $crit_not_running_information";;
|
||||
esac
|
||||
((crit_not_running++));; # crit not running
|
||||
3) case $crit_not_exist in
|
||||
"") crit_not_exist_information="${critical_report[$service_number,0]}";;
|
||||
1) crit_not_exist_information="$crit_not_exist_information and ${critical_report[$service_number,0]}";;
|
||||
*) crit_not_exist_information="${critical_report[$service_number,0]}, $crit_not_exist_information";;
|
||||
esac
|
||||
((crit_not_exist++));; # crit not exist
|
||||
esac
|
||||
fi
|
||||
done
|
||||
if [[ $crit_not_running ]]; then
|
||||
if [[ $crit_not_running = 1 ]]; then
|
||||
crit_not_running_information="$crit_not_running_information service is not running"
|
||||
else
|
||||
crit_not_running_information="$crit_not_running_information services are not running"
|
||||
fi
|
||||
status_information="- $crit_not_running_information"
|
||||
fi
|
||||
if [[ $crit_not_exist ]]; then
|
||||
if [[ $crit_not_exist = 1 ]]; then
|
||||
crit_not_exist_information="$crit_not_exist_information service does not exist"
|
||||
else
|
||||
crit_not_exist_information="$crit_not_exist_information services do not exist"
|
||||
fi
|
||||
status_information="- $crit_not_exist_information $status_information"
|
||||
fi
|
||||
status_information="ERROR $status_information";;
|
||||
$STATE_WARNING)
|
||||
for (( service_number=0; service_number<=$compteur_service-1; service_number++ )); do
|
||||
if [[ ${warning_report[$service_number,0]} != "" ]]; then
|
||||
case ${warning_report[$service_number,1]} in
|
||||
1) case $warn_not_running in
|
||||
"") warn_not_running_information="${warning_report[$service_number,0]}";;
|
||||
1) warn_not_running_information="$warn_not_running_information and ${warning_report[$service_number,0]}";;
|
||||
*) warn_not_running_information="${warning_report[$service_number,0]}, $warn_not_running_information";;
|
||||
esac
|
||||
((warn_not_running++));; # warn not running
|
||||
2) case $crit_disable in
|
||||
"") crit_disable_information="${warning_report[$service_number,0]}";;
|
||||
1) crit_disable_information="$crit_disable_information and ${warning_report[$service_number,0]}";;
|
||||
*) crit_disable_information="${warning_report[$service_number,0]}, $crit_disable_information";;
|
||||
esac
|
||||
((crit_disable++));; # crit disable
|
||||
3) case $warn_not_exist in
|
||||
"") warn_not_exist_information="${warning_report[$service_number,0]}";;
|
||||
1) warn_not_exist_information="$warn_not_exist_information and ${warning_report[$service_number,0]}";;
|
||||
*) warn_not_exist_information="${warning_report[$service_number,0]}, $warn_not_exist_information";;
|
||||
esac
|
||||
((warn_not_exist++));; # warn not exist
|
||||
esac
|
||||
fi
|
||||
done
|
||||
if [[ $warn_not_running ]]; then
|
||||
if [[ $warn_not_running = 1 ]]; then
|
||||
warn_not_running_information="$warn_not_running_information service is not running"
|
||||
else
|
||||
warn_not_running_information="$warn_not_running_information services are not running"
|
||||
fi
|
||||
status_information="- $warn_not_running_information"
|
||||
fi
|
||||
if [[ $crit_disable ]]; then
|
||||
if [[ $crit_disable = 1 ]]; then
|
||||
crit_disable_information="$crit_disable_information service is disabled"
|
||||
else
|
||||
crit_disable_information="$crit_disable_information services are disabled"
|
||||
fi
|
||||
status_information="- $crit_disable_information $status_information"
|
||||
fi
|
||||
if [[ $warn_not_exist ]]; then
|
||||
if [[ $warn_not_exist = 1 ]]; then
|
||||
warn_not_exist_information="$warn_not_exist_information service does not exist"
|
||||
else
|
||||
warn_not_exist_information="$warn_not_exist_information services do not exist"
|
||||
fi
|
||||
status_information="- $warn_not_exist_information $status_information"
|
||||
fi
|
||||
status_information="WARN $status_information";;
|
||||
$STATE_OK)
|
||||
for (( service_number=0; service_number<=$compteur_service-1; service_number++ )); do
|
||||
if [[ ${silent_report[$service_number,0]} != "" ]]; then
|
||||
case ${silent_report[$service_number,1]} in
|
||||
1) case $silent_not_running in
|
||||
"") silent_not_running_information="${silent_report[$service_number,0]}";;
|
||||
1) silent_not_running_information="$silent_not_running_information and ${silent_report[$service_number,0]}";;
|
||||
*) silent_not_running_information="${silent_report[$service_number,0]}, $silent_not_running_information";;
|
||||
esac
|
||||
((silent_not_running++));; # silent not running
|
||||
2) case $silent_disable in
|
||||
"") silent_disable_information="${silent_report[$service_number,0]}";;
|
||||
1) silent_disable_information="$silent_disable_information and ${silent_report[$service_number,0]}";;
|
||||
*) silent_disable_information="${silent_report[$service_number,0]}, $silent_disable_information";;
|
||||
esac
|
||||
((silent_disable++));; # silent disable
|
||||
3) case $silent_not_exist in
|
||||
"") silent_not_exist_information="${silent_report[$service_number,0]}";;
|
||||
1) silent_not_exist_information="$silent_not_exist_information and ${silent_report[$service_number,0]}";;
|
||||
*) silent_not_exist_information="${silent_report[$service_number,0]}, $silent_not_exist_information";;
|
||||
esac
|
||||
((silent_not_exist++));; # silent not exist
|
||||
esac
|
||||
fi
|
||||
if [[ ${running_report[$service_number]} != "" ]]; then
|
||||
case $running_service in
|
||||
"") running_service_information="${running_report[$service_number]}";;
|
||||
1) running_service_information="$running_service_information and ${running_report[$service_number]}";;
|
||||
*) running_service_information="${running_report[$service_number]}, $running_service_information";;
|
||||
esac
|
||||
((running_service++))
|
||||
fi
|
||||
done
|
||||
if [[ $silent_not_running ]]; then
|
||||
if [[ $silent_not_running = 1 ]]; then
|
||||
silent_not_running_information="$silent_not_running_information service is not running"
|
||||
else
|
||||
silent_not_running_information="$silent_not_running_information services are not running"
|
||||
fi
|
||||
status_information="- $silent_not_running_information"
|
||||
fi
|
||||
if [[ $silent_disable ]]; then
|
||||
if [[ $silent_disable = 1 ]]; then
|
||||
silent_disable_information="$silent_disable_information service is disabled"
|
||||
else
|
||||
silent_disable_information="$silent_disable_information services are disabled"
|
||||
fi
|
||||
status_information="- $silent_disable_information $status_information"
|
||||
fi
|
||||
if [[ $silent_not_exist ]]; then
|
||||
if [[ $silent_not_exist = 1 ]]; then
|
||||
silent_not_exist_information="$silent_not_exist_information service does not exist"
|
||||
else
|
||||
silent_not_exist_information="$silent_not_exist_information services do not exist"
|
||||
fi
|
||||
status_information="- $silent_not_exist_information $status_information"
|
||||
fi
|
||||
if [[ $running_service ]]; then
|
||||
if [[ $running_service = 1 ]]; then
|
||||
running_service_information="$running_service_information service is running"
|
||||
else
|
||||
running_service_information="$running_service_information services are running"
|
||||
fi
|
||||
status_information="- $running_service_information $status_information"
|
||||
fi
|
||||
|
||||
status_information="OK $status_information";;
|
||||
esac
|
||||
|
||||
echo $status_information
|
||||
exit $current_state
|
||||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
# Fin du script
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
|
||||
#~ Version changelog
|
||||
#~ v0.1 - Basé sur check_systemd_service.sh de Mohamed El Morabity <melmorabity@fedoraproject.com>
|
||||
#~ v0.2 - Possibilité de gérer plusieurs services avec differents niveaux de criticité
|
||||
|
||||
|
149
ebook-zip.sh
Executable file
149
ebook-zip.sh
Executable file
@ -0,0 +1,149 @@
|
||||
#!/bin/bash
|
||||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
#~ Nom : nom_du_script
|
||||
#~ Description : Ceci est la description du script
|
||||
#~ Auteur : Etienne Girault <etienne.girault@gmail.com>
|
||||
#~
|
||||
#~ Usage : [-h] [-D] [-V]
|
||||
#~
|
||||
#~ Options : -h, --help ; Affiche l'aide
|
||||
#~ Options : -V, --version ; Affiche la version
|
||||
#~ Options : -D, --debug ; Mode debug
|
||||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
# Déclaration des variables
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
script_name="$(grep '^#~ Nom' "$0" | sed 's/^.*: //')"
|
||||
script_version="$(grep '^#~ v' "$0" | tail -1 | sed -e 's/^#~ //' -e 's/ *\-.*$//')"
|
||||
|
||||
ebook_download_dir=/data/download
|
||||
ebook_dest_dir=/srv/owncloud/data/Ebook/files
|
||||
|
||||
user_used=www-data
|
||||
occ_bin=/srv/owncloud/occ
|
||||
|
||||
mode_verbose=0
|
||||
new_ebook=0
|
||||
sudoing=""
|
||||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
# Déclaraition des fonctions
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
print_script_name_version() { echo "$script_name $script_version" && sed -n '/^#~ Version/,$p' "$0" | grep '^#~' | sed 's/^#~ //'; }
|
||||
print_script_description() { grep '^#~ Description' "$0" | sed 's/^.*: //'; }
|
||||
print_script_usage() { grep '^#~ Usage' "$0" | sed -e 's/^.*: //' -e '1 s/^/Usage: '"$script_name"' /' -e '2,$ s/^/'"$(printf '%*s' "$(echo "Usage: $script_name" | wc -c)")"'/'; }
|
||||
print_script_options() { echo "Options" && grep '^#~ Options' "$0" | sed -e 's/^.*://' -e 's/^ --/ --/' | column -ts \;; }
|
||||
print_script_help() { echo "$script_name $script_version" && print_script_description && print_script_usage && print_script_options; }
|
||||
|
||||
exit_msg() { echo $1; exit $2; }
|
||||
|
||||
prerunning_test() {
|
||||
# Test si l'utilsateur n'est pas $user_used
|
||||
if [[ $(whoami) != $user_used ]]; then
|
||||
# Test si l'utilisateur peut lancer des commandes en tant que $user_used
|
||||
if sudo -u $user_used -n true 2> /dev/null; then
|
||||
# Active le mode sudo
|
||||
sudoing="sudo -u $user_used"
|
||||
else
|
||||
exit_msg "Impossible de lancer des commandes en tant que $user_used"
|
||||
fi
|
||||
fi
|
||||
|
||||
[ -d $ebook_download_dir ] || exit_msg "Le répertoire de téléchargement ($ebook_download_dir) est inaccessible" 1
|
||||
[ -d $ebook_dest_dir ] || exit_msg "Le répertoire de destination ($ebook_dest_dir) est inaccessible" 1
|
||||
# [ ! -w $EBOOK_DEST_DIR ] && exit_msg "Impossible d'écrire dans le répertoire de destination ($EBOOK_DEST_DIR)" 1
|
||||
}
|
||||
|
||||
list_directories() {
|
||||
download_directories=$(mktemp)
|
||||
find "$ebook_download_dir" -type d > $download_directories
|
||||
}
|
||||
|
||||
directory_is_ebook() {
|
||||
if $(ls -1 "$1" | grep -q '\.mp3$'); then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
its_new_ebook() {
|
||||
ebook_name_uncleaned="${1##*/}"
|
||||
ebook_name="${ebook_name_uncleaned%% \[*}"
|
||||
messenger "nom du livre : $ebook_name"
|
||||
if [[ -f "${ebook_dest_dir}/${ebook_name}.zip" ]]; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
proceed_ebook() {
|
||||
cd "$1"
|
||||
$sudoing zip -r "${ebook_dest_dir}/${ebook_name}.zip" .
|
||||
new_ebook=1
|
||||
cd -
|
||||
}
|
||||
|
||||
owncloud_scan() { [[ $new_ebook = 1 ]] && $sudoing $occ_bin files:scan --all; }
|
||||
|
||||
messenger() { [[ $mode_verbose = 1 ]] && echo "$1"; }
|
||||
|
||||
# Reception de signaux d'interruptions
|
||||
trap 'exit 1' INT TERM
|
||||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
# Gestion des options
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
while getopts ":-:hVDv" OPTION; do
|
||||
case $OPTION in
|
||||
h) print_script_help; exit;;
|
||||
V) print_script_name_version; exit;;
|
||||
D) set -x;;
|
||||
v) mode_verbose=1;;
|
||||
:) ;;
|
||||
-) case $OPTARG in
|
||||
help) print_script_help; exit;;
|
||||
version) print_script_name_version; exit;;
|
||||
debug) set -x;;
|
||||
esac ;;
|
||||
*) ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND-1))
|
||||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
# Début du script
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
|
||||
prerunning_test
|
||||
|
||||
# Liste tout les répertoires du $ebook_download_dir dans le fichier temporaire $download_directories
|
||||
list_directories
|
||||
|
||||
# Pour chaque répertoire du $ebook_download_dir
|
||||
while read directory; do
|
||||
# Test si le répertoire contient un fichier mp3
|
||||
if directory_is_ebook "$directory"; then
|
||||
# Si le répertoire contient un fichier mp3, il est considéré comme un livre
|
||||
messenger "le répertoire ($directory) est un livre"
|
||||
# Test si le livre a déjà été traité
|
||||
if its_new_ebook "$directory"; then
|
||||
# Si le livre n'a pas déjà été traité, il est traité
|
||||
messenger "le répertoire ($directory) doit etre zippé"
|
||||
proceed_ebook "$directory"
|
||||
fi
|
||||
fi
|
||||
|
||||
done < $download_directories
|
||||
|
||||
owncloud_scan
|
||||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
# Fin du script
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
|
||||
#~ Version changelog
|
||||
#~ v0.1 - Création du script
|
||||
|
467
rpi-backup.sh
Executable file
467
rpi-backup.sh
Executable file
@ -0,0 +1,467 @@
|
||||
#!/bin/bash
|
||||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
#~ Nom : rpi-backup
|
||||
#~ Description : Sauvegarde le contenu d'un Raspberry pi
|
||||
#~ Auteur : Etienne Girault <etienne.girault@gmail.com>
|
||||
#~
|
||||
#~ Usage : [-h] [-D] [-V] [-t] [-q] [-o] [-b] [-v] [-c]
|
||||
#~ Usage : [-f [<filename>]
|
||||
#~ Usage : [-l "DIR1 DIR2 DIR3"...] or [-l DIR1,DIR2,DIR3...]
|
||||
#~
|
||||
#~ Options : -h, --help ; Affiche l'aide
|
||||
#~ Options : -V, --version ; Affiche la version
|
||||
#~ Options : -D, --debug ; Mode debug
|
||||
#~ Options : -f, --file=[FILE] ; Détermine le chemin de la sauvegarde
|
||||
#~ Options : -t, --test ; Mode test
|
||||
#~ Options : -q, --quiet ; Mode silencieux
|
||||
#~ Options : -l, --list ; Spécifie les répertoires à sauvegarder
|
||||
#~ Options : -p, --print ; Affiche la taille et le chemin de la dernière sauvegarde
|
||||
#~ Options : -b, --background ; Lancement du script en arrière-plan
|
||||
#~ Options : -v, --view ; Affiche les derniers logs
|
||||
#~ Options : -c, --configure ; Configure les variables du script
|
||||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
# Déclaration des variables
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
script_name="$(grep '^#~ Nom' "$0" | sed 's/^.*: //')"
|
||||
script_version="$(grep '^#~ v' "$0" | tail -1 | sed -e 's/^#~ //' -e 's/ *\-.*$//')"
|
||||
|
||||
backup_user=backup
|
||||
host_name=$(hostname -s)
|
||||
|
||||
# Répertoire où la sauvegarde sera déposée
|
||||
backup_dir=/backup
|
||||
# Nom et chemin de la sauvegarde
|
||||
backup_name=backup_${host_name}_$(date +"%Y%m%d")
|
||||
backup_path="${backup_dir}/${backup_name}"
|
||||
|
||||
# Répertoire où les listes des exports sera déposée
|
||||
export_dir=${backup_dir}/export
|
||||
# Localisation des fichiers config des repo git (dans un tableau pour prendre en compte '*')
|
||||
git_configs=(/appli/source/*/.git/config)
|
||||
|
||||
# Répertoires depuis la racine à sauvegarder
|
||||
saved_dir="appli/data backup/export boot etc home root seedbox srv"
|
||||
|
||||
# Répertoire d'archive
|
||||
archive_dir=/data/backup
|
||||
# Répertoire des anciennes archives
|
||||
old_archive_dir=${archive_dir}/old
|
||||
|
||||
# Fichier de log
|
||||
log_file=/var/log/${script_name}.log
|
||||
|
||||
# Variables configurables
|
||||
configurable_vars="backup_user backup_dir export_dir archive_dir old_archive_dir saved_dir git_configs log_file"
|
||||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
# Déclaraition des fonctions
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
print_script_name_version() { echo "$script_name $script_version" && sed -n '/^#~ Version/,$p' "$0" | grep '^#~' | sed 's/^#~ //'; }
|
||||
print_script_description() { grep '^#~ Description' "$0" | sed 's/^.*: //'; }
|
||||
print_script_usage() { grep '^#~ Usage' "$0" | sed -e 's/^.*: //' -e '1 s/^/Usage: '"$script_name"' /' -e '2,$ s/^/'"$(printf '%*s' "$(echo "Usage: $script_name" | wc -c)")"'/'; }
|
||||
print_script_options() { echo "Options" && grep '^#~ Options' "$0" | sed -e 's/^.*://' -e 's/^ --/ --/' | column -ts \;; }
|
||||
print_script_help() { echo "$script_name $script_version" && print_script_description && print_script_usage && print_script_options; }
|
||||
|
||||
# Séquence de test avant le lancement du script
|
||||
prelaunch_test() {
|
||||
# Relance le script avec droits sudo si pas deja fait
|
||||
[[ "$(whoami)" = root ]] || { sudo "$0" "$@"; exit; }
|
||||
|
||||
# Détection du mode interactif ou silencieux
|
||||
[[ ! "$mode_quiet" && -t 0 && -t 1 ]] && mode_interactive=0
|
||||
|
||||
# Décalage des arguments en fonction du nombre d'options choisies
|
||||
shift $((OPTIND-1))
|
||||
# Si un argument reste en fin de chaîne, c'est qu'il y a un problème sur le nombre d'argument
|
||||
[[ "$1" ]] && argument_error="$1"
|
||||
# Si une erreur d'argument a été trouvée, l'affiche et sort du script
|
||||
if [[ "$argument_error" ]]; then
|
||||
msg_log 3 "Argument incompris: $argument_error"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test si l'utilisateur de backup existe, active le mode standalone sinon
|
||||
if ! id "$backup_user" &>/dev/null; then
|
||||
msg_log 3 "utilisateur $backup_user absent sur le système"
|
||||
mode_standalone=0
|
||||
fi
|
||||
|
||||
# Vérifie si un chemin de sauvegarde personnalisé a été demandé
|
||||
custom_backup_path 1
|
||||
|
||||
# Test la présence du répertoire de sauvegarde (création si besoin)
|
||||
test_directory "$backup_dir" 0
|
||||
# Test la présence du répertoire d'export (création si besoin)
|
||||
test_directory "$export_dir" 0
|
||||
# Test la présence du répertoire d'archive, active le mode standalone sinon
|
||||
test_directory "$archive_dir" || mode_standalone=0
|
||||
test_directory "$old_archive_dir" 0
|
||||
|
||||
# Test de la présence des répertoires à sauvegarder, les supprime de la liste si absent
|
||||
for directory in $saved_dir; do
|
||||
test_directory "/${directory}" || saved_dir="${saved_dir/$directory/}"
|
||||
done
|
||||
|
||||
# Si le dossier de log n'existe pas, active le flag no_logging
|
||||
test_directory "$(dirname $log_file)" || no_logging=0
|
||||
|
||||
# Test des commandes d'export, affiche son absence si c'est le cas
|
||||
test_command dpkg || msg_log 3 "l'outil dpkg est introuvable"
|
||||
test_command pip2 || msg_log 3 "l'outil pip2 est introuvable"
|
||||
test_command pip3 || msg_log 3 "l'outil pip3 est introuvable"
|
||||
|
||||
# Mode test pour dev
|
||||
[[ "$mode_test" ]] && fonction_test "$@"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Test la présence d'une commande, retourne 1 si elle n'existe pas
|
||||
# $1 : Commande testée
|
||||
test_command() { type "$1" &>/dev/null && return 0 || return 1; }
|
||||
|
||||
# Test la présence d'un réperoire, la possiblité de le créer, retourne 1 si pas présent/créé
|
||||
# $1 : Répertoire testé
|
||||
# [$2] : Si initialisée, le répertoire sera créé si possible
|
||||
test_directory() {
|
||||
# si le répertoire n'existe pas
|
||||
[[ -d "$1" ]] && return
|
||||
# si $2 est initialisée et si le répertoire parent existe
|
||||
if [[ "$2" && -d "$(dirname $1)" ]]; then
|
||||
# demande de creation du répertoire
|
||||
if ask_question "Répertoire $1 absent, dois-je le créer ?"; then
|
||||
msg_log 1 "Création du répertoire $1"
|
||||
msg_log 2 "mkdir $1"
|
||||
return 0
|
||||
# si l'utilisateur répond non, retourne 1
|
||||
else return 1; fi
|
||||
# sinon, $2 n'est pas initialisée ou le répertoire parent n'existe pas, retourne 1
|
||||
else return 1; fi
|
||||
}
|
||||
|
||||
# Pose une question à l'utilisateur, si pas intéractif, la réponse est oui par défaut
|
||||
# $1 : Question posée
|
||||
ask_question() {
|
||||
[[ ! "$mode_interactive" ]] && return 0
|
||||
echo -e "$1 \c"
|
||||
read -r -n 1 question_answer < /dev/tty
|
||||
echo ""
|
||||
case $question_answer in
|
||||
o|O|y|Y) return 0;;
|
||||
*) return 1;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Affiche les étapes du script sur la sortie standard en mode interactif ou le fichier de log en mode silencieux
|
||||
# $1 : Mode (0=message, 1=début de tâche, 2=fin de tache, 3=message sur le stderr, 4=debut/fin de script)
|
||||
# $2 : Message à afficher ou code retour de la précédente commande
|
||||
msg_log() {
|
||||
# Si mode interactif, affichage des messages sur la console
|
||||
|
||||
if [[ "$mode_interactive" ]]; then
|
||||
case $1 in
|
||||
0) echo "$2";;
|
||||
1) echo -e "${2} \c";;
|
||||
2) if eval "$2" &> /dev/null; then
|
||||
echo -e "\033[32;1mOK\033[0m"
|
||||
else
|
||||
echo -e "\033[31;1mErreur\033[0m"
|
||||
fi;;
|
||||
3) echo "$2" >&2;;
|
||||
esac
|
||||
# Sinon, mode non interactif, affichage des messages sur le fichier de log
|
||||
else
|
||||
[[ "$no_logging" ]] && return 0
|
||||
format_date="$(date "+%h %d %T") ${host_name}:"
|
||||
case $1 in
|
||||
0|3) echo "$format_date $2" >> "$log_file";;
|
||||
1) echo -e "$format_date ${2} \c" >> "$log_file";;
|
||||
2) if eval "$2" &> /dev/null; then
|
||||
echo -e "\033[32;1mOK\033[0m" >> "$log_file"
|
||||
else
|
||||
echo -e "\033[31;1mErreur\033[0m" >> "$log_file"
|
||||
fi;;
|
||||
4) echo "$format_date --- $2" >> "$log_file";;
|
||||
esac
|
||||
fi
|
||||
}
|
||||
|
||||
# Export des listes de paquets/librairies/repos installés dans le dossier d'export
|
||||
export_lists() {
|
||||
msg_log 1 "Export des listes de paquets/librairies/repos"
|
||||
# Export de la liste des paquets apt
|
||||
test_command dpkg && dpkg --get-selections > "${export_dir}/apt.list"
|
||||
# Export de la liste des librairies python2
|
||||
test_command pip2 && pip2 freeze > "${export_dir}/pip2.list"
|
||||
# Export de la liste des librairies python3
|
||||
test_command pip3 && pip3 freeze > "${export_dir}/pip3.list"
|
||||
# Extraction des URLs des repos github
|
||||
ls ${git_configs[*]} >/dev/null 2>&1 && sed -n '/url/p' ${git_configs[*]} | sed 's/^.*= //' > "${export_dir}/appli.list"
|
||||
msg_log 2
|
||||
return 0
|
||||
}
|
||||
|
||||
# Création de la sauvegarde
|
||||
create_backup() {
|
||||
# Suppression d'éventuel reliquat d'archive
|
||||
[[ -f "$backup_path".tar ]] && rm -f "$backup_path".tar
|
||||
# Création du fichier de sauvegarde et application du user de backup
|
||||
touch "$backup_path".tar
|
||||
[[ ! "$mode_standalone" ]] && chown "${backup_user}:${backup_user}" "$backup_path".tar
|
||||
|
||||
# Sauvegarde de la liste des répertoires dans backup_name.tar dans le backup_dir
|
||||
cd / || exit
|
||||
for directory in $saved_dir; do
|
||||
msg_log 1 "Sauvegarde du dossier /$directory"
|
||||
msg_log 2 'tar --append --warning=no-file-ignored --file "$backup_path".tar "$directory"'
|
||||
done
|
||||
|
||||
msg_log 1 "Compression de la sauvegarde"
|
||||
# Compression de l'archive tar en tar.gz
|
||||
[[ -f "$backup_path".tar ]] && msg_log 2 'gzip -1 "$backup_path".tar'
|
||||
[[ -f "$backup_path".tar.gz ]] && mv "$backup_path".t{ar.gz,gz}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Supprime les précédentes sauvegardes du dossier de sauvegarde
|
||||
clear_backup() {
|
||||
[[ "$mode_standalone" ]] && return
|
||||
msg_log 1 "Suppression des précédentes sauvegardes du dossier $backup_dir"
|
||||
msg_log 2 'find "$backup_dir" -maxdepth 1 ! -name "$backup_name".tgz -user "$backup_user" -print0 | xargs -r0 rm'
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
# Rotations des sauvegardes réalisées par le user backup
|
||||
rotate_backup() {
|
||||
# Si le répertoire d'archive est injoignable, retour
|
||||
[[ "$mode_standalone" ]] && return
|
||||
msg_log 1 "Rotations des sauvegardes dans les archives $archive_dir"
|
||||
for day in 01 10 20; do
|
||||
# Déplace les sauvegardes de ce serveur datant du 01, 10 et 20 du mois, qui ont plus de 3 jours, du dossier archives vers les anciennes archives
|
||||
su "$backup_user" -s /bin/bash -c "find $archive_dir -maxdepth 1 -name *${host_name}*${day}.tgz -type f -mtime +1 -print0 | xargs -r0 mv -t $old_archive_dir"
|
||||
# Supprime les sauvegardes de ce serveur qui ont plus de 30 jours du dossier des anciennes archives
|
||||
[[ ! "$day" = 01 ]] && su "$backup_user" -s /bin/bash -c "find $old_archive_dir -maxdepth 1 -name *${host_name}*${day}.tgz -mtime +30 -type f -print0 | xargs -r0 rm"
|
||||
done
|
||||
# Supprime les sauvegardes de ce serveur de plus de 5 jours du dossier d'archive
|
||||
msg_log 2 'su "$backup_user" -s /bin/bash -c "find $archive_dir -maxdepth 1 -name *${host_name}* -type f -mtime +1 -print0 | xargs -r0 rm"'
|
||||
|
||||
msg_log 1 "Copie la sauvegarde $backup_name dans le dossier d'archive $archive_dir"
|
||||
# Copie la sauvegarde dans le dossier d'archive
|
||||
msg_log 2 'su "$backup_user" -s /bin/bash -c "cp $backup_path.tgz $archive_dir"'
|
||||
return 0
|
||||
}
|
||||
|
||||
test_nextarg() {
|
||||
[[ "${1::1}" = "-" ]] && argument_error="$1"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Spécifie au script un chemin de sauvegarde personnalisé
|
||||
# $1 : Mode (0=Initialise la variable backup_path avec $2, 1=Vérifie l'état)
|
||||
# $2 : valeur du backup_path demandé
|
||||
custom_backup_path() {
|
||||
# Si la fonction est appelé avec un argument
|
||||
case $1 in
|
||||
0) # $1 = 0, le backup_path est associé à $2
|
||||
backup_path="$2"
|
||||
# Le drapeau custom_backup_path_set est levé
|
||||
custom_backup_path_set=0;;
|
||||
1) # $1 = 1, on vérifie l'état des drapeaux, si custom_backup_path_flag pas levé, on retourne 0
|
||||
[[ ! "$custom_backup_path_flag" ]] && return 0
|
||||
# Si mode interactif
|
||||
if [[ "$mode_interactive" ]]; then
|
||||
# Si custom_backup_path_set n'est pas levé, on demande a l'utilisateur la valeur de backup_path
|
||||
if [[ ! "$custom_backup_path_set" ]]; then
|
||||
echo -e "Chemin de la sauvegarde ? \c"
|
||||
read -r backup_path < /dev/tty;
|
||||
fi
|
||||
# Si mode interactif
|
||||
# Tant que le répertoire de la valeur de backup_path n'existe pas, on redemande la valeur de backup_set à l'utilisateur
|
||||
until test_directory "$(dirname $backup_path)"; do
|
||||
echo -e "Chemin de sauvegarde invalide, réessaye :\c"
|
||||
read -r backup_path < /dev/tty;
|
||||
done
|
||||
# Sinon, mode silencieux
|
||||
else
|
||||
# Si le drapeau custom_backup_path_set est levé
|
||||
if [[ "$custom_backup_path_set" ]]; then
|
||||
# Si le répertoire de la valeur de backup_path n'existe pas, affiche l'erreur sur les logs et quitte le script
|
||||
test_directory "$(dirname $backup_path)" || { msg_log 3 "Le chemin de la sauvegarde $backup_path n'est pas valable"; exit 1;}
|
||||
# Sinon, le drapeau custom_backup_path_set n'est pas levé, incompatible en mode silencieux, affiche l'erreur sur les logs et quitte le script
|
||||
else
|
||||
msg_log 3 "Le chemin de la sauvegarde $backup_path n'est pas spécifié"
|
||||
exit 1;
|
||||
fi
|
||||
fi
|
||||
# Si le backup_path est donné en relatif, transformation en chemin absolu
|
||||
[[ ! "${backup_path::1}" = "/" ]] && backup_path="$(pwd)/$backup_path"
|
||||
return 0;;
|
||||
esac
|
||||
# Le drapeau custom_backup_path_path est levé
|
||||
custom_backup_path_flag=0
|
||||
mode_standalone=0
|
||||
return 0
|
||||
}
|
||||
|
||||
# Sauvegarde les bases MySQL/MariaDB si le service est lancé
|
||||
save_mysql() {
|
||||
# Test si le service MySQL est démarré, retourne 0 sinon
|
||||
systemctl is-active mysql --quiet || return 0
|
||||
msg_log 1 "Sauvegarde des bases MySQL"
|
||||
# Dump des bases de données dans le répertoire d'export
|
||||
msg_log 2 'mysqldump --all-databases > "${export_dir}/mysql-dump.sql"'
|
||||
return 0
|
||||
}
|
||||
|
||||
# Affiche la taille et le nom de la dernière sauvegarde
|
||||
print_backup_name() { ls -lth "$backup_dir"/*.tgz | head -1 | awk '{printf "%-6s %s\n", $5, $9}'; }
|
||||
|
||||
# Lance un éditeur de texte avec les variables configurables
|
||||
configure_variable() {
|
||||
mode_interactive=0
|
||||
# Crée un fichier de configuration temporaire
|
||||
conf_file=$(mktemp)
|
||||
# Affiche chaque variable dans le fichier de configuration
|
||||
for each_variable in $configurable_vars; do
|
||||
sed -n "/^${each_variable}=/p" "$0" >> "$conf_file"
|
||||
done
|
||||
# Edite le fichier de configuration
|
||||
vi "$conf_file"
|
||||
# Changement de l'IFS pour la lecture du fichier de configuration
|
||||
IFS='='
|
||||
# Pour chaque ligne du fichier de configuration
|
||||
while read -r the_variable new_value; do
|
||||
# Vérifie si la variable écrite sur le fichier est modifiable
|
||||
if echo "$configurable_vars" | grep -q "$the_variable"; then
|
||||
# Si la valeur de la variable a été modifiée
|
||||
if ! grep -q -F "$the_variable=$new_value" "$0"; then
|
||||
# Demande confirmation à l'utilisateur pour modifier la variable
|
||||
if ask_question "Modifier la variable '$the_variable=$new_value' ?"; then
|
||||
# script_path=$(readlink -f "$0")
|
||||
msg_log 1 "Modification de la variable '$the_variable'"
|
||||
# Modifie la valeur de la variable directement dans le script
|
||||
msg_log 2 'sed -i "s#^$the_variable=.*#$the_variable=$new_value#" "$(readlink -f $0)"'
|
||||
fi
|
||||
fi
|
||||
else
|
||||
msg_log 0 "Impossible de changer la variable '$the_variable'"
|
||||
fi
|
||||
done < "$conf_file"
|
||||
# Supprime le fichier de configuration temporaire
|
||||
rm "$conf_file"
|
||||
}
|
||||
|
||||
# Affiche les derniers logs
|
||||
view_log() {
|
||||
# Cherche le motif '--- Début', le stock quand il le trouve et ajoute au stock, si
|
||||
sed -n '/--- Début/h;/--- Début/!H;$!b;x;p' "$log_file"
|
||||
}
|
||||
|
||||
# Fonction de test pour le developpement
|
||||
fonction_test() {
|
||||
|
||||
sed -n '/url/p' ${git_configs[*]} | sed 's/^.*= //'
|
||||
msg_log 0 "test ok"
|
||||
exit 0
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
# Début du script
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
|
||||
main() {
|
||||
prelaunch_test "$@"
|
||||
|
||||
msg_log 4 "Début de la sauvegarde"
|
||||
|
||||
export_lists
|
||||
save_mysql
|
||||
create_backup
|
||||
clear_backup
|
||||
rotate_backup
|
||||
|
||||
msg_log 4 "Fin de la sauvegarde"
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
# Gestion des options
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
while getopts ":-:hVDf:tql:pbvc" OPTION; do
|
||||
case $OPTION in
|
||||
h) print_script_help; exit;;
|
||||
V) print_script_name_version; exit;;
|
||||
D) set -x;;
|
||||
f) test_nextarg "$OPTARG" && custom_backup_path 0 "$OPTARG";;
|
||||
t) mode_test=0;;
|
||||
q) mode_quiet=0;;
|
||||
l) test_nextarg "$OPTARG" && saved_dir="${OPTARG//,/ }"; custom_backup_path;;
|
||||
p) print_backup_name; exit;;
|
||||
b) nohup "$script_name" "-q" "${@/-b/}" &> /dev/null & exit;;
|
||||
v) view_log; exit;;
|
||||
c) configure_variable; exit;;
|
||||
:) [ "$OPTARG" = "f" ] && custom_backup_path;;
|
||||
\?) echo "-$OPTARG: option invalide" && print_script_usage; exit;;
|
||||
-) case $OPTARG in
|
||||
help) print_script_help; exit;;
|
||||
version) print_script_name_version; exit;;
|
||||
debug) set -x;;
|
||||
file) custom_backup_path 0 "$OPTARG";; # VERIF
|
||||
test) mode_test=0;;
|
||||
quiet) mode_quiet=0;;
|
||||
list) saved_dir="${OPTARG//,/ }"; custom_backup_path;;
|
||||
print) print_backup_name; exit;;
|
||||
background) nohup "$script_name" "-q" "${@/-b/}" &> /dev/null & exit;;
|
||||
view) view_log; exit;;
|
||||
configure) configure_variable; exit;;
|
||||
*) echo "--$OPTARG: option invalide" && print_script_usage; exit;;
|
||||
esac ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Reception de signaux d'interruptions
|
||||
trap 'exit 1' INT TERM
|
||||
|
||||
set -o errexit
|
||||
|
||||
main "$@"
|
||||
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
# Fin du script
|
||||
#----------------------------------------------------------------------------------------------------
|
||||
|
||||
#~ Version changelog
|
||||
#~ v0.1 - Création du script
|
||||
#~ v0.2 - Sauvegarde totale de la carte SD (~25min)
|
||||
#~ v0.2.1 - Sauvegarde uniquement les répertoires utiles à la restauration (~2min)
|
||||
#~ v0.2.2 - Nommage de la sauvegarde en fonction de la date
|
||||
#~ v0.2.3 - Ajout des exports des listes de paquets/librairies/URLs github
|
||||
#~ v0.2.4 - Ajout de l'option file pour définir un chemin à la sauvegarde
|
||||
#~ v0.3 - Réécriture du script suivant les best practice bash
|
||||
#~ v0.4 - Ajout des fonctions test_command et test_directory
|
||||
#~ v0.4.1 - Ajout de la fonction ask_question
|
||||
#~ v0.4.2 - Ajout du mode verbeux et interactif
|
||||
#~ v0.4.3 - Ajout du mode standalone et la creation des répertoires nécessaires au script
|
||||
#~ v0.5 - Utilisable multi serveur
|
||||
#~ v0.5.1 - Mode verbeux par défaut en interactif, ajout du mode silencieux
|
||||
#~ v0.5.2 - Refonte de la fonction msg_log
|
||||
#~ v0.5.3 - Ajout du logging en mode non interactif
|
||||
#~ v0.6 - Ajout de l'option list pour spécifier les répertoires à sauvegarder, à associer à l'option file
|
||||
#~ v0.6.1 - Ajout de la fonction custom_backup_path pour gérer les erreurs d'un backup_path personnalisé
|
||||
#~ v0.6.2 - Ajout de la fonction test_nextarg pour gérer les problèmes d'argument
|
||||
#~ v1.0 - Publication pour mise en fonctionnement
|
||||
#~ v1.1 - Ajout de la sauvegarde des bases MySQL/MariaDB
|
||||
#~ v1.1.1 - Modification de la fonction msg_log pour la prise en compte du code retour
|
||||
#~ v1.2 - Ajout de l'option print pour l'affichage de la taille et du nom de la dernière sauvegarde
|
||||
#~ v1.3 - Ajout de l'option background pour le lancement en arriere plan
|
||||
#~ v1.4 - Ajout de l'option view pour le l'affichage des derniers logs
|
||||
#~ v1.5 - Ajout de l'option configure pour la reconfiguration des variables
|
||||
#~ v1.5.1 - Améliorations de synthaxe
|
||||
#~ v1.5.2 - Correction de l'utilisation de la variable git_config
|
||||
|
||||
|
||||
# TODO - Restauration
|
209
sd-backup.sh
Executable file
209
sd-backup.sh
Executable file
@ -0,0 +1,209 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Importation des fonctions externes
|
||||
. /home/vezpi/.local/lib/V_init_function
|
||||
|
||||
# Déclaration des variables
|
||||
LOG=/var/log/sd-backup.log
|
||||
VERSION=1.9.2
|
||||
|
||||
# Répertoire local des sauvegardes
|
||||
SAVEDIR=/backup
|
||||
# Répertoire cible des sauvegardes
|
||||
ARCHDIR=/media/HDDUSB/sd-backup
|
||||
# Base du nom des archives
|
||||
ARCHBASE="backup_"
|
||||
# Nom de l'archive final
|
||||
ARCHNAME="$ARCHBASE$(date +"%d%m%Y")"
|
||||
# Suffixe temporaire de l'archive
|
||||
TIMESTAMP=`date +"%d%m%Y_%H%M%S"`
|
||||
# Fichiers temporaires
|
||||
FTMP=/tmp/paquets
|
||||
FTMP[1]="$SAVEDIR/$ARCHBASE$TIMESTAMP.tar"
|
||||
# Liste des fichiers/répertoires à sauvegarder
|
||||
LIST=/home/vezpi/script/sd-backup/file_to_save
|
||||
# Compteur d'erreur
|
||||
FAIL=0
|
||||
|
||||
# Déclaraition des fonctions
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
# Sauvegarde $TOSAVE en une archive ${FTMP[1]} ($SAVEDIR/$ARCHBASE$TIMESTAMP.tar)
|
||||
#--------------------------------------------------------------------------------
|
||||
function Sauvegarde {
|
||||
V_log -t "Sauvegarde $LOGGING... \c"
|
||||
cd "${TOSAVE%/*}/" # Se déplace dans le répertoire parent du répertoire à sauvegarder
|
||||
if [[ -f "${FTMP[1]}" ]]; then # Crée l'archive temporaire si elle n'existe pas, sinon l'ajoute à l'achive
|
||||
tar rf "${FTMP[1]}" --exclude='*.log*' "${TOSAVE##*/}" || return 1
|
||||
else
|
||||
tar cf "${FTMP[1]}" --exclude='*.log*' "${TOSAVE##*/}" || return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
# Préparation à recevoir des signaux d'interruption
|
||||
trap 'V_log "\033[31;1mInterruption\033[0m"; V_log -t -q "==== Interruption du processus de sauvegarde $TYPE_SAVE ===="; V_exit 1' INT TERM
|
||||
|
||||
# Test de l'utilisateur
|
||||
[ $(whoami) = 'root' ] || V_exit -e "Permission non accordée, à lancer en root." 1
|
||||
|
||||
# Gestion des options
|
||||
while getopts ":DhVven:l:t:aofb" OPTION; do
|
||||
# Message de mauvaise option
|
||||
VV_OPTION=""
|
||||
V_option "$0"
|
||||
case $OPTION in
|
||||
# Edite la liste des répertoires à sauvegarder
|
||||
e) vi $LIST
|
||||
V_exit $?
|
||||
;;
|
||||
# Change le nom de la sauvegarde (et empêche la rotation des sauvegardes)
|
||||
n) ARCHNAME=$OPTARG
|
||||
NO_SUPPRESSION=0
|
||||
;;
|
||||
# Affiche les <n> dernières logs
|
||||
l) tac $LOG | grep '#\{10\}' -m $OPTARG -B 20 | tac | sed -e '1d' -e 's/#\{10\}/ /g'
|
||||
V_exit $?
|
||||
;;
|
||||
# Change le dossier cible de la sauvegarde
|
||||
t) SAVEDIR="$OPTARG"
|
||||
FTMP[1]="$SAVEDIR/$ARCHBASE$TIMESTAMP.tar"
|
||||
NO_SUPPRESSION=0
|
||||
;;
|
||||
# Affiche l'arborescence du fichier de sauvegarde
|
||||
a) tree $ARCHDIR
|
||||
V_exit $?
|
||||
;;
|
||||
# Affiche la taille et le nom de la sauvegarde
|
||||
o) ls -lth $SAVEDIR | head -2 | tail -1 | awk '{print $5,$9}'
|
||||
V_exit $?
|
||||
;;
|
||||
# Force la sauvegarde
|
||||
f) FORCE=0
|
||||
;;
|
||||
# Lance en arrière-plan
|
||||
b) PREVOPT="$(echo "$@" | sed 's/ -b//')"
|
||||
nohup sd-backup -f $PREVOPT > /dev/null 2>&1 &
|
||||
V_exit -k
|
||||
;;
|
||||
:) # Si -n n'a pas d'argument associe, demande le nom de l'archive
|
||||
[ $OPTARG = "n" ] && { echo "Nom de l'archive ?"; read ARCHNAME < /dev/tty;}
|
||||
# Si -l n'a pas d'argument associe, affiche uniquement la dernière sauvegarde
|
||||
[ $OPTARG = "l" ] && { tac $LOG | grep '#\{10\}' -m 1 -B 20 | tac | sed '1d'; V_exit $?;}
|
||||
# Si -t n'a pas d'argument associe, sort du script
|
||||
[ $OPTARG = "t" ] && { echo "Destination manquante, annulation."; V_exit 1;}
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Type de sauvegarde
|
||||
if [ "$0" = "/home/vezpi/bin/sd-backup" ]; then # Si la sauvegarde a été lancé manuellement, intéraction avec l'utilisateur
|
||||
TYPE_SAVE=manuelle
|
||||
if [ ! $FORCE ]; then
|
||||
echo -e "Voulez-vous lancer la sauvegarde ? (o/n) \c"
|
||||
read -n 1 CHOIX < /dev/tty
|
||||
case $CHOIX in
|
||||
o|O|y|Y) echo ""
|
||||
;;
|
||||
* ) V_exit -e "\nAbandon."
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
[ ! $VERBOSE ] && echo -e "Sauvegarde en cours \c"
|
||||
else # Sinon automatique
|
||||
TYPE_SAVE=automatique
|
||||
fi
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
# Début du script
|
||||
#--------------------------------------------------------------------------------
|
||||
|
||||
V_log -q "##########"
|
||||
V_log -t -q "==== Début du processus de sauvegarde $TYPE_SAVE du $(date +"%d/%m/%y") ===="
|
||||
|
||||
# Test du répertoire de destination de l'archive
|
||||
[[ -d $SAVEDIR ]] || { V_log -t "Dossier de destination $SAVEDIR introuvable."; V_exit -l "[$(date +"%T")] ==== Fin du processus de sauvegarde $TYPE_SAVE ====" 1;}
|
||||
|
||||
|
||||
# Récupération de la liste des paquets
|
||||
dpkg --get-selections > $FTMP || V_exit -e "Sauvegarde de la liste des paquets impossible." 1
|
||||
|
||||
# Dump de la base de données des mots de passes
|
||||
/root/bin/pw -s
|
||||
|
||||
# Sauvegarde de la liste des fichiers/répertoires définis dans la liste
|
||||
while read TOSAVE LOGGING; do
|
||||
if Sauvegarde; then
|
||||
V_log "\033[32;1mOK\033[0m."
|
||||
[ $TYPE_SAVE = "manuelle" ] && [ ! $VERBOSE ] && echo -e ".\c"
|
||||
else
|
||||
((FAIL++))
|
||||
V_log "\033[31;1mErreur\033[0m."
|
||||
[ $TYPE_SAVE = "manuelle" ] && [ ! $VERBOSE ] && echo -e "!\c"
|
||||
fi
|
||||
done < $LIST
|
||||
|
||||
# Compression de l'archive en gzip
|
||||
V_log -t "Compression de l'archive... \c"
|
||||
if gzip -1 "${FTMP[1]}"; then
|
||||
V_log "\033[32;1mOK\033[0m."
|
||||
else
|
||||
V_log "\033[31;1mErreur\033[0m."
|
||||
((FAIL++))
|
||||
fi
|
||||
|
||||
# Nommage de l'archive en .tgz
|
||||
V_log -t "Renommage de l'archive... \c"
|
||||
if mv "${FTMP[1]}".gz "$SAVEDIR/$ARCHNAME".tgz; then
|
||||
V_log "\033[32;1mOK\033[0m."
|
||||
else
|
||||
V_log "\033[31;1mErreur\033[0m."
|
||||
((FAIL++))
|
||||
fi
|
||||
|
||||
# Nettoyage du dossier de sauvegarde temporaire des anciennes sauvegardes
|
||||
if [[ $FAIL -eq 0 ]]; then
|
||||
find $SAVEDIR -maxdepth 1 ! -name "$ARCHNAME.tgz" -type f | xargs rm 2> /dev/null
|
||||
fi
|
||||
|
||||
if [ -d $ARCHDIR ]; then
|
||||
# Rotation des anciennes sauvegardes si pas d'erreurs lors des sauvegardes
|
||||
if [[ $FAIL -eq 0 ]]; then
|
||||
# Rotations des sauvegardes
|
||||
if [ ! $NO_SUPPRESSION ]; then
|
||||
V_log -t "Rotation des anciennes archives... \c"
|
||||
for DAY in 01 05 10 15 20 25 30; do
|
||||
# Déplace les sauvegardes du 01 05 10 15 20 25 30 du mois qui ont plus de 5 jours dans le dossier oldbackup
|
||||
find $ARCHDIR -maxdepth 1 ! -name "*$TIMESTAMP*" -name "$ARCHBASE$DAY*" -type f -mtime +4 | xargs mv -t $ARCHDIR/oldbackup 2> /dev/null
|
||||
# Supprime les sauvegardes du 05 10 15 20 25 30 du mois qui ont plus de 30 jours du dossier oldbackup
|
||||
[ ! $DAY = 01 ] && find $ARCHDIR/oldbackup -maxdepth 1 -name "$ARCHBASE$DAY*" -mtime +30 -type f | xargs rm 2> /dev/null
|
||||
done
|
||||
# Supprime les sauvegardes de plus de 5 jours
|
||||
find $ARCHDIR -maxdepth 1 ! -name "*$TIMESTAMP*" -name "$ARCHBASE*" -type f -mtime +4 | xargs rm 2> /dev/null
|
||||
V_log "\033[32;1mOK\033[0m."
|
||||
fi
|
||||
else
|
||||
V_log -t "Une erreur est survenue lors d'une sauvegarde, pas de rotation des anciennes archives."
|
||||
fi
|
||||
|
||||
# Copie de l'archive sur un disque externe
|
||||
V_log -t "Copie de l'archive sur le disque externe... \c"
|
||||
if cp "$SAVEDIR/$ARCHNAME.tgz" "$ARCHDIR"; then
|
||||
V_log "\033[32;1mOK\033[0m."
|
||||
else
|
||||
V_log "\033[31;1mErreur\033[0m."
|
||||
fi
|
||||
else
|
||||
V_log -t "\033[31;1mAttention !\033[0m Dossier de destination $ARCHDIR introuvable."
|
||||
fi
|
||||
|
||||
[ $TYPE_SAVE = "manuelle" ] && [ ! $VERBOSE ] && echo -e "\033[32;1m OK\033[0m."
|
||||
V_log -t -q "==== Fin du processus de sauvegarde $TYPE_SAVE ===="
|
||||
|
||||
V_exit
|
||||
|
||||
#--------------------------------------------------------------------------------
|
||||
# Fin du script
|
||||
#--------------------------------------------------------------------------------
|
Loading…
x
Reference in New Issue
Block a user