l'idée est d'ajouter à la liste des paquets, uniquement(je tente...) les fichiers de configuration personnels. Nous obtenons donc une sauvegarde des plus légère mais très complète
script en version V0.000001 donc merci de tester ou d'apporter des idées ou critiques
La sauvegarde se fait dans
/tmp/arch-save/
, elle se fait en quelques étapes :-1) la liste des paquets (officiels et AUR) : juste une recopie de la commande dans trucs et astuces
-2) lister en fonction de la liste créée en no1 (officiels et non AUR) tous les fichiers dans /etc/. Si la date est différente de l'installation du paquet alors sauver le nom du fichier dans le fichier
/tmp/arch-save/etc.list
car c'est que nous l'avons modifié/personnalisé !-3) lister tous les fichiers dans les dossiers ".d" dans /etc/ et ajouter à la même liste ceux qui n'appartiennent à aucun paquet !
-4) lister une liste personnelle de fichiers ou dossiers que nous pouvons avoir dans
~/.config/arch-save.conf
. Tout fichier trouvé sera alors ajouté à notre liste dans /tmp/arch-save/etc.list
par exemple, des dossiers :
/etc/httpd/conf
/etc/apache2
/etc/nginx
ps: ~/.bashrc et d'autres dans $HOME sont déjà fait automatiquement
-5) avec ce fichier etc.list génération d"une archive dans /tmp/arch-save/ comprenant nos fichiers ainsi que la liste de nos paquets
-6) pas encore écrit possibilité de sauver dans le cloud (via git)
----------------------------------------
voir -h ou --help pour les options :
--help a écrit : -p --package : uniquement la liste packages et leurs configs si personnalisées
-l --local : uniquement les fichiers dans notre liste locale ~/.config/arch-save.conf
-d --dir : uniquement les fichiers complémentaire de config /etc/*.d/*
-z --gz : création d'une archive
-v --verbose : affichage de plus d'infos (pour debug...)
Notes,
- sans option cela peut-être un peu long car il fait la totale
- testé uniquement sans mode admin (sans sudo) donc aucun risque ! écriture uniquement dans /tmp/
Le script: arch-save.sh
#!/usr/bin/env bash
pkgname='arch-save'
version=0.1.0-1
# test in asset function
unset DEVELOPER PARAMS ADMIN CONFIG VERBOSE LOCAL DIR PACKAGES
#PARAMS=1
DEVELOPER=1
PACKAGES=1
DIR=1
LOCAL=1
#general install directories
declare -A DIRS=()
DIRS[local]="$HOME/.config/${pkgname}.conf"
DIRS[save]="/tmp/$pkgname"
error_file="/tmp/$pkgname.err"
#########################
function usage()
{
echo -e "Usage: $pkgname
-g --git : save in repo git
-z --gz : save in archive\n
-p --package : only packages
-l --local : only locale config ~/.config/${pkgname}.conf
-d --dir : only files /etc/*.d/*\n
-v --verbose : show more information\n"
echo -e "output in : ${DIRS[save]}/"
}
# je déclenche une erreur
#cp zozoleb 2> $error_file
#(( $? )) && error "oops"
function error()
{
local msg=$1
[[ -f "$error_file" ]] && {
msg="${msg}: $(head -n1 $error_file)"
rm $error_file
}
echo "${msg}" >&2
}
function asset()
{
local E_PARAM_ERR=98
local E_ASSERT_FAILED=99
((PARAMS)) && {
(( $# < 1 )) && {
error "expected argument"
usage
exit $E_PARAM_ERR
}
}
((ADMIN)) && {
(($EUID != 0)) && {
error "you cannot perform this operation unless you are root."
exit $E_ASSERT_FAILED
}
}
((CONFIG)) && {
[ -r "${DIRS[conf]}" ] || {
error "config file not found \"${DIRS[conf]}\""
exit $E_ASSERT_FAILED
}
}
}
function init_paths()
{
DIRS[local]="$HOME/.config/${pkgname}.conf"
DIRS[path]=''
DIRS[conf]="/etc/${pkgname}.conf"
DIRS[lib]="/usr/lib/${pkgname}"
DIRS[doc]="/usr/share/doc/${pkgname}"
local lg=$(locale 2>/dev/null | awk -F'=' '/^LANG/ {print $2}')
DIRS[conf.lang]=${lg:0:2}
DIRS[dico]="/usr/share/locale/${DIRS[conf.lang]}/LC_MESSAGES/$pkgname"
}
##########################################################
# PROJECT FUNCTIONS
##########################################################
function packages.save()
{
pacman -Qqen > "${DIRS[save]}/pkglist-repo.txt"
pacman -Qqem > "${DIRS[save]}/pkglist-aur.txt"
printf "enregistré dans %s\n" ${DIRS[save]}
}
function package.findconf()
{
#find all conf file in one package
local package="${1-:'pacman'}"
local f
date_p=$(date -d "$(LANG=C pacman -Qi ${package} | awk -F':' '/Install Date/ {print $2}')" +%s)
((VERBOSE)) && echo "package $package installé le : ${date_p} : $(LANG=C pacman -Qi ${package} | awk -F':' '/Install Date/ {print $2}')"
for f in $(pacman -Qlq "${package}" | grep "/etc/" | grep -v "/$"); do
[ -f "$f" ] || continue
#echo "get date de ${f}"
local date_m=$(stat -c %Y "${f}")
#date_f=$(/usr/bin/date -r "$f" +%s) fonctionne pas :(
if (( $date_m - $date_p > 600 )); then
echo -e "\t-- $f est à sauvegarder .... $date_p <> $date_m"
echo "$f" >> ${DIRS[save.diff]}
else
((VERBOSE)) && echo -e "\t-- $date_p == $date_m , $f est l'original !"
fi
done
}
function packages.findconf()
{
local pkg
echo "------------------------------"
echo "-- all packages"
while read pkg
do
package.findconf "$pkg"
done < "${DIRS[save]}/pkglist-repo.txt"
}
function add_diff() {
local f="$1"
if [ -f "$f" ]; then
echo "$f" >> ${DIRS[save.diff]}
echo -e "\t\t$f (ajout)"
fi
}
function d.findconf()
{
local dir="${1-:'/etc/systemd/journald.conf.d'}"
local f
((VERBOSE)) && echo -e "\t${dir} (DIR)"
for f in ${dir}/*; do
[ -d "$f" ] && continue
[ -f "$f" ] || continue
((VERBOSE)) && echo -e "\t\t$f"
#local pkg=$(pacman -Qoq "$f" 2>/dev/null)
# if file not in one package SAVE
if (! pacman -Qoq "$f" &>/dev/null); then
add_diff "$f"
fi
done
}
function ds.findconf()
{
echo "------------------------------"
echo "-- all .d directories"
for d in $(find /etc/ -type d -iname "*.d" -readable 2>/dev/null); do
d.findconf "$d"
done
}
function list.findconf()
{
local dir="${1-:'/etc/systemd/journald.conf.d'}"
local f
if [ -d "$dir" ]; then
((VERBOSE)) && echo -e "\t$dir DIR"
for f in ${dir}/*; do
[ -d "$f" ] && list.findconf "$f" # continue
[ -f "$f" ] || continue
add_diff "$f"
done
else
add_diff "$dir"
fi
}
function lists.findconf()
{
echo "------------------------------"
list.findconf "/etc/issue"
list.findconf "/etc/locale.conf"
list.findconf "/etc/pacman.conf"
list.findconf "$HOME/.bashrc"
list.findconf "$HOME/.bash_profile"
list.findconf "$HOME/.zshrc"
list.findconf "$HOME/.yaourtrc"
list.findconf "$HOME/.nanorc"
list.findconf "$HOME/.face.icon"
list.findconf "$HOME/.gitconfig"
list.findconf "$HOME/.config/user-dirs.dirs"
list.findconf "$HOME/.config/autostart"
echo "-- all files and directories in ~/.config/${pkgname}.conf"
while read f
do
list.findconf "$f"
done < "${DIRS[local]}"
}
function git.create()
{
local url=${1:-'https://gitlab.com/$LOGIN/arch-save.git'}
git init
git remote add origin $url
}
function git.save()
{
# git add, commit, git push
echo "------------------------------"
}
function save.create()
{
local f
# lire fichier "${DIRS[save]}/etc.list"
# copier les fichiers dans "${DIRS[save.diff]}"
echo "------------------------------"
#cat "${DIRS[save.diff]}"
echo "-- cp all files in ${DIRS[save.diff]}"
while read f
do
[ -f "$f" ] || continue
[ -r "$f" ] || continue # pas les droits en lecture !
((VERBOSE)) && echo "copie de $f dans\t${DIRS[save]}${f}"
install -pD "$f" "${DIRS[save]}$f"
done < "${DIRS[save.diff]}"
}
function save.gz()
{
# gzip le dossier "${DIRS[save]}"
echo "------------------------------"
echo "-- create archive in ${DIRS[save]}"
local namef="$(hostname -s)-$(lsb_release -i | awk '{print $3}')-$(date +%F).tar.gz"
namef=${namef,,}
cd "${DIRS[save]}"
rm "${DIRS[save]}/${namef}" 2>/dev/null
tar -czf "/tmp/${namef}" -C "${DIRS[save]}" "."
mv "/tmp/${namef}" "${DIRS[save]}/${namef}"
echo "archive: ${DIRS[save]}/${namef}"
}
##########################################################
# RUN
##########################################################
run()
{
[ -d "${DIRS[save]}" ] || mkdir "${DIRS[save]}"
DIRS[save.diff]="${DIRS[save]}/etc.list"
echo ''> "${DIRS[save.diff]}"
packages.save
((PACKAGES)) && packages.findconf
((DIR)) && ds.findconf
((LOCAL)) && lists.findconf
save.create
((GIT)) && git.save
((GZ)) && save.gz
}
main()
{
# load home conf
init_paths
SHORT=hvgzldpu:
LONG=help,verbose,git,gz,local,dir,packages,url
PARSED=$(getopt --options $SHORT --longoptions $LONG --name "$0" -- "$@")
(( $? != 0 )) && exit 1
eval set -- "$PARSED"
while true; do
case "$1" in
-g|--git)
GIT=1
shift
;;
-z|--gz)
GZ=1
shift
;;
-v|--verbose)
VERBOSE=1
shift
;;
-u|--url)
URL="$2"
shift
;;
-d|--dir)
unset PACKAGES LOCAL
shift
;;
-p|--package)
unset LOCAL DIR
shift
;;
-l|--local)
unset PACKAGES DIR
shift
;;
-h|--help)
usage
exit 0
;;
--)
shift
break
;;
*)
echo "Programming error"
exit 3
;;
esac
done
#ARGS=("$@")
unset LONG SHORT PARSED
# tests
asset "$@"
#run
run "$@"
}
if [ "${BASH_SOURCE[0]}" == "$0" ]; then
main "$@"
exit 0
else
export -f packages.save
fi