dernière version: 0.2b (toujours utiliser la dernière version).v.0.2b plus bas. La version 0.1 ainsi que la version 0.2 dans une moindre mesure sont affectées d'un bug dans la fonction f_updatecache, ne pas les utiliser et supprimer le cache s'il y a eu des mises à jour ou en cas de doute.Bonjour à tous !
j'ai eu un peu de temps ces dernières semaines (la crise toussa) et j'en ai profité pour faire un script qui je pense peut être utile à pas mal de monde. Peut-être découvrirez-vous des choses sur votre système...
J'ai fait ce script d'abord pour me perfectionner en bash (ce qui explique certains choix et certains "amusements"), donc si vous avez des remarques, des conseils, des améliorations,... n'hésitez pas. Je dois dire que j'ai sauté sur l'occasion d'avoir une idée qui me paraissait intéressante: je crois que le plus dur en programmation c'est d'avoir une idée :)
Pour ce qui est des fonctionnalités d'apt-diag c'est pareil: n'hésitez pas à proposer des améliorations/ajouts ou à les coder et à nous en faire profiter. Essayez juste si possible de rester dans l'esprit du script.
Il y a une description générale en commentaire au début, donc j'en ajoute pas plus.
Vous pourrez trouver un système de test
ici, à placer dans ~/.apt-diag. Il rassemble les cas traités par apt-diag pour permettre d'en tester les fonctionnalités.
Voilà. J'ai deux souhaits: que apt-diag vous soit utile et que peut-être il inspire un vrai programmeur Debian pour qu'une application de ce type soit intégrée au système.
#!/bin/bash
############ #########
# apt-diag # # v.0.1 #
################################################################################
# author: (C)2009 nofun_AT_laposte_DOT_net ## bug report, suggestion, wishlist #
####################################################### are welcome ############
# GNU General Public License v.3 or later http://www.gnu.org/copyleft/gpl.html #
################################################################################
# apt-diag: pour que claires les sources demeurent
# apt-diag cherche a donner une vue d'ensemble des paquets installes sur un
# systeme utilisant apt (Advanced Packaging Tool du projet Debian).
# Il aide en particulier a determiner de quelle source peut provenir un paquet,
# indique quand c'est le cas la presence d'un meme paquet dans de multiples
# sources et dresse la liste des paquets n'appartenant plus a aucune source
# (ensemble des paquets obsoletes et des paquets de source inconnue).
# C'est un bon complement a 'apt-cache policy nom_du_paquet'.
# De plus, apt-diag maintient un cache personnel des paquets par source, ce qui
# lui permet d'etablir la liste des paquets obsoletes en provenance de chaque
# source, information sinon indisponible. Les sources supprimees sont egalement
# archivees. Le degre d'information que fournit apt-diag est donc dependant de
# la date d'initialisation du cache.
# apt-diag n'agit pas sur le systeme de gestion des paquets, il est donc su^r
# pour le systeme hote. Le seul appel au systeme de gestion des paquets est du
# type 'dpkg -l' ou 'dpkg --get-selections'. De ce fait, apt-diag peut analyser
# un systeme autre que le systeme hote si on lui fournit les repertoires
# /var/lib/apt/lists/ et /var/lib/dpkg/ d'un syteme alternatif et fonctionne
# parfaitement en simple utilisateur.
# Limitations:
# tout diagnostic est faillible et sujet a des erreurs d'interpretation. Il
# appartient a l'administrateur d'evaluer les informations fournies par apt-diag
# en particulier en confrontant les resultats obtenus avec ceux que pourront lui
# procurer les outils systeme a sa disposition. La licence GNU GPL sous laquelle
# apt-diag est delivre n'offre aucune garantie de bon fonctionnement.
# apt-diag n'a pas (encore) ete teste en presence de downgrade ou d'apt-pinning
# et plus generalement demande a etre teste davantage.
# apt-diag n'est pas integre au systeme de gestion des paquets, de ce fait la
# mise a jour du cache n'est pas automatique lors de la mise a jour du systeme.
# apt-diag evalue les paquets par leur nom, l'evaluation par numero de version
# est embryonnaire et demanderait d'autres techniques de programmation.
# Si un paquet a ete installe depuis une source par la suite supprimee et que ce
# paquet apparait toujours dans une autre source avec une version inferieure,
# rien de particulier n'est signale au sujet de ce paquet par apt-diag.
# Merci de distribuer apt-diag avec le texte ci-dessus.
# Bonne utilisation.
################################################################################
PROGNAME=$(basename $0)
f_conv()
{
#TestCharSet: aéèêîïà¿»×x
grep -m 1 "TestCharSet:" $0 > /tmp/testcharset
PRGCHARSET=`file -bi /tmp/testcharset|mawk -F "charset=" '{print $2}'|tr [a-z] [A-Z]`
SYSCHARSET=$(locale charmap)
! echo $SYSCHARSET|grep -q $PRGCHARSET && echo -e "\n [>] Conversion de $PROGNAME de $PRGCHARSET vers $SYSCHARSET...\c"\
&& { iconv -f "$PRGCHARSET" -t "$SYSCHARSET"//TRANSLIT $0 -o /tmp/$PROGNAME && chmod +x /tmp/$PROGNAME\
&& grep -m 1 "TestCharSet:" /tmp/$PROGNAME > /tmp/testcharset && PRGCHARSETR=`file -bi /tmp/testcharset|mawk -F "charset=" '{print $2}'`\
&& { [ "$PRGCHARSET" = "$(echo $PRGCHARSETR|tr [a-z] [A-Z])" ] && echo " ok" || echo; } && rm -f /tmp/testcharset\
&& echo -e " [*] la version $PRGCHARSETR de $PROGNAME est disponible dans /tmp/$PROGNAME\n" && exit\
|| { echo -e "\a\n [!] un probleme est survenu pendant la conversion, sortie\n"; exit 1; }; }
}
[ -d ~/.$PROGNAME ] || { f_conv; [ -d /var/lib/apt/lists/ ] && [[ $(dpkg -l 2>/dev/null) ]]\
|| { echo -e "\a\n [!] $PROGNAME n'est pas compatible avec le système hôte, sortie\n"; exit 1; }; }
which bc &>/dev/null|| { echo -e "\a\n [>] $PROGNAME\n [!] Ce script nécessite bc pour fonctionner, veuillez l'installer:\n"
aptitude show bc; echo -e "\n [*] aptitude -(s)v install bc\n"; exit 1; }
[ "$1" = "-c" ] && ECHO=echo || CLEAR=clear ; hash grep mawk
grep -q "Ratio $(uname -n):" ~/.$PROGNAME/ratio 2&>/dev/null && RATIO=`grep "Ratio $(uname -n):" ~/.$PROGNAME/ratio|cut -d " " -f3`
################################################################################
f_clearline()
{
[[ $1 = [br] ]] && [ -n "$3" ] && echo $2$3|grep -qx [0-9]* || return 1
while true
do
local COUNTER; let COUNTER++ ; echo -ne "\\$1"
[ $COUNTER = $2 ] && unset -v COUNTER && break
done
while true
do
let COUNTER++ ; echo -ne " "
[ $COUNTER = $3 ] && unset -v COUNTER && break
done
while true
do
let COUNTER++ ; [ $1 = r ] && COUNTER=$3
echo -ne "\\$1" ; [ $COUNTER = $3 ] && return
done
}
f_exit() { read -s -n 1 -p " [¿] Quitter $PROGNAME ? <O/n>: " EXIT; [ "$EXIT" = n ] && f_clearline r 1 45 && return; echo; echo; exit; }
f_init()
{
for (( s=1; s <= TSOURCES; s++ )); do unset -v RESULTF$s OBSOLETES$s; done
unset -v DEL INEWS ISUPR NOPURGEP NOSOURCEDP OBSOLETES OBSOLETEST OBSOLETESTC OBSOLETESTR
unset -v RESULTF RESULTFT SINGLE SOURCEDP SOURCESG SOURCESGC SOURCESN SOURCESNG TSOURCES TWIN TWINP
CACHEDIR=~/.$PROGNAME/$MACHINE/cache ; RECFILE=~/$PROGNAME\_$MACHINE\-$(date +%Y%m%d-%H%M%S).txt
[ -d $CACHEDIR ] || { mkdir -p $CACHEDIR/.old/sources/.deleted/ $CACHEDIR/sources/
echo "$MACHINE $(date "+%F %T") initialisation du cache" >> ~/.$PROGNAME/$MACHINE/history.txt; }
[ -d ~/.$PROGNAME/_alternate/lists/ -a -d ~/.$PROGNAME/_alternate/dpkg/ ]\
&& mv -f ~/.$PROGNAME/_alternate/lists/ ~/.$PROGNAME/_alternate/dpkg/ ~/.$PROGNAME/$MACHINE/
[ "$MACHINE" = "$(uname -n)" ] && SOURCESDIR=/var/lib/apt/lists/ INSTALLDIR=/var/lib/dpkg/\
|| SOURCESDIR=~/.$PROGNAME/$MACHINE/lists/ INSTALLDIR=~/.$PROGNAME/$MACHINE/dpkg/
## extraction de la liste des paquets installes sur le systeme
INSTALLED=$(dpkg --admindir=$INSTALLDIR --get-selections |grep -w "install$" |mawk '{print $1}' |sort -d)
NINSTALLED=$(echo $INSTALLED | wc -w)
## extraction et nettoyage des sources
SOURCES=$(ls $SOURCESDIR |grep -vx lock |grep -vx partial)
for a in _source_Sources i18n_Translation .ed$
do
SOURCES=$(printf '%b\n' $SOURCES | grep -v $a)
done
for s in $SOURCES
do
grep -qm 1 "^Package: " $SOURCESDIR$s || continue
SOURCESC="$SOURCESC $s" ; let TSOURCES++
done
SOURCES="$SOURCESC"; unset -v SOURCESC
echo " [»] Paquets installés: $INSTALLDIR Paquets disponibles: $SOURCESDIR"
echo " [»] $NINSTALLED paquets installés sur $MACHINE"
}
f_progress()
{
let PROGRESS++
[ $PROGRESS = $ALPHAPROGRESS ] && echo -ne "\b-" && return
[ $PROGRESS = $ALPHAPROGRESS2 ] && echo -ne "\b\\" && return
[ $PROGRESS = $ALPHAPROGRESS3 ] && echo -ne "\b|" && return
[ $PROGRESS = $ALPHAPROGRESS4 ] && echo -ne "\b/" && PROGRESS=0
}
f_benchmachine()
{
local ALPHAPROGRESS ALPHAPROGRESS2 ALPHAPROGRESS3 ALPHAPROGRESS4 BURN COUNTER PROGRESS SAMPLE SAMPLEb TEMPS TEMPS1 TEMPS2
ALPHAPROGRESS=60 SAMPLE="sourceinstalled" # ! la taille du mot est importante ! ne pas modifier ! SAMPLE="sourceinstalled"
ALPHAPROGRESS2=$(($ALPHAPROGRESS*2)) ALPHAPROGRESS3=$(($ALPHAPROGRESS*3)) ALPHAPROGRESS4=$(($ALPHAPROGRESS*4))
f_burn()
{
CLOCKD=$(date +%s%N)
while true
do
let COUNTER++; f_progress
while true
do
let COUNTERb++; f_progress
SAMPLEb="$SAMPLEb $(echo "$SAMPLE ")"
[ $COUNTERb = 100 ] && break
done
unset -v COUNTERb
echo $SAMPLEb|grep $SAMPLE|wc -w &>/dev/null
[ $COUNTER = 10 ] && break
done
CLOCKF=$(date +%s%N)
let BURN++
}
[ "$BURN" = "" ] && echo -n " [>] Benchmarking machine... " && f_burn
[ "$BURN" = "1" ] && unset -v COUNTER SAMPLEb && f_burn
[ "$BURN" = "2" ] && TEMPS1=$(($CLOCKF-$CLOCKD)) && unset -v COUNTER SAMPLEb && f_burn
TEMPS2=$(($CLOCKF-$CLOCKD)) TEMPS=$(($TEMPS1+$TEMPS2))
RATIO=$(echo "scale=20;$TEMPS/2/$COUNTER/240000000"|bc|mawk '{printf "%0.1f\n",$1}')
## ($RATIO=1 est obtenu sur mon portable Core2Duo T7250 2GHz 2Go RAM, $RATIO>1 sur une machine plus lente)
## le resultat peut etre faux sur un portable non branche ou si une autre application prend de la ressource
echo "Ratio $(uname -n): $RATIO" > ~/.$PROGNAME/ratio
f_clearline r 1 35
}
f_benchmark()
{
[ -z "$RATIO" ] && f_benchmachine; echo -n " [>] Benchmarking... "; local RESULTF PROGRESS COUNTER
## ALPHACOUNTER: determine un nombre de boucles proportionnellement inverse au nombre de paquets dans la source pondere par le ratio machine
## destine a adapter le temps de bench en prenant en compte $NPA et la vitesse de la machine
PREALPHACOUNT=`echo "scale=20;1/$NPA*150000*1/(1/$NPA*(300+$NPA/2))*1.8"|bc`
ALPHACOUNTER=`echo "scale=20;$PREALPHACOUNT/$RATIO"|bc|mawk '{printf "%0.0f\n",$1}'`
[ `echo "scale=0; $ALPHACOUNTER<2"|bc` -eq 1 ] && ALPHACOUNTER=2
CLOCKD=$(date +%s%N)
for i in $INSTALLED
do
let COUNTER++; f_progress
RESULTF="$RESULTF $(echo "$PRERESULT"|grep -xm 1 $i)"
[ $COUNTER -eq $ALPHACOUNTER ] && break
done
CLOCKF=$(date +%s%N)
TEMPS=$(($CLOCKF-$CLOCKD)) BENCHMASS=$(($NPA*$COUNTER)) BENCH=$(echo "scale=10;$TEMPS/$BENCHMASS"|bc)
f_clearline r 1 30
}
f_estimate()
{
ESTIMATE=$(echo "scale=10;$BENCH*$COMPUTEMASS"|bc)
ESTIMATEHS=$(echo "scale=0;$ESTIMATE/1000000000"|bc)
ESTIMATEHSBC=$(echo "scale=3;$ESTIMATE/1000000000"|bc)
mn=0 ss=$ESTIMATEHS ms=$(echo "$ESTIMATEHSBC-$ss"|bc|cut -d '.' -f2)
[ $ESTIMATEHS -gt 59 ] && mn=$(($ESTIMATEHS/60)) && ss=$(($ss-$mn*60))
[ $ss -lt 10 ] && ss="0$ss"
ESTIMATE=$(echo ""$mn"m"$ss"s"$ms"ms")
}
f_mkcache()
{
trap 'echo -e "\a\n$PROGNAME > WARNING! The disk cache might be left in an inconsistent state!"; f_exit' 2 3 9 15
## determine s'il y a des nouvelles sources a traiter:
for s in $SOURCES; do [ -f $CACHEDIR/sources/$s ] && continue; SOURCESNEWS="$SOURCESNEWS $s"; let TSOURCESM++; done
## determine si des sources ont ete desactivees, dans ce cas les archive:
## NB: les depots designes par les noms de code des versions (ex. lenny) seront archives au changement de version,
## ceux utilisant la terminologie stable, testing, unstable,... seront traites par f_updatecache
for s in $(ls $CACHEDIR/sources/)
do
printf '%b\n' $SOURCES|grep -qxm 1 $s &>/dev/null || { mv -f $CACHEDIR/sources/$s $CACHEDIR/.old/sources/.deleted/$s; DEL="$DEL $s"; }
done
[ -n "$DEL" ] && echo && for d in $DEL; do echo " [>] Archivage de la source supprimée $d";\
echo "$MACHINE $(date "+%F %T") source supprimée $d archivée" >> ~/.$PROGNAME/$MACHINE/history.txt; done
[ -z "$TSOURCESM" -a -n "$DEL" ] && { unset -v DEL; echo; echo >> ~/.$PROGNAME/$MACHINE/history.txt
read -s -n 1 -p " [-] valider pour continuer... "; f_clearline r 1 35; $CLEAR; return; }; [ -z "$TSOURCESM" ] && return
echo
echo " [>] Création du cache initial de paquets installés pour les nouvelles sources:"; echo
time\
for a in $SOURCESNEWS
do
## supprime la source du repertoire .deleted si elle a ete reactivee
[ -f $CACHEDIR/.old/sources/.deleted/$a ] && rm -f $CACHEDIR/.old/sources/.deleted/$a
## ecrit dans $CACHEDIR/sources/$a les noms des paquets installes qui ont une occurrence dans $SOURCESDIR$a
local TIMEFORMAT=" »»» réelle: %lR" PROGRESS CSOURCES; let CSOURCES++
echo " [»] Traitement de la source ($CSOURCES/$TSOURCESM) $a"
PRERESULT=$(grep "^Package: " $SOURCESDIR$a | mawk '{print $2}') NPA=$(echo $PRERESULT | wc -w) COMPUTEMASS=$(($NPA*$NINSTALLED))
echo " [»] $NPA paquets dans la source, $NINSTALLED paquets installés sur $MACHINE"
[ -z "$RATIO" ] && f_benchmachine
### ALPHAPROGRESS: alteration proportionnelle de l'indicateur de progresssion. Utilise le nombre inverse de $NPA, pondere par $RATIO
PREALPHAPROG=`echo "scale=20;1/$NPA*(200+$NPA)*10"|bc`
[ `echo "scale=20; $PREALPHAPROG<=11"|bc` -eq 1 ]\
&& ALPHAPROGRESS=`echo "scale=20;(($PREALPHAPROG-10)*10+$PREALPHAPROG-10)/$RATIO"|bc|mawk '{printf "%0.0f\n",$1}'`\
|| ALPHAPROGRESS=`echo "scale=20;$PREALPHAPROG/$RATIO"|bc|mawk '{printf "%0.0f\n",$1}'`
[ `echo "scale=0; $ALPHAPROGRESS<1"|bc` -eq 1 ] && ALPHAPROGRESS=1
[ `echo "scale=0; $ALPHAPROGRESS>20"|bc` -eq 1 ] &&\
ALPHAPROGRESS=`echo "scale=20;20+(-1/$ALPHAPROGRESS+$ALPHAPROGRESS)/$NPA/1*$NPA/10"|bc|mawk '{printf "%0.0f\n",$1}'`
[ `echo "scale=0; $ALPHAPROGRESS>30"|bc` -eq 1 ] && ALPHAPROGRESS=30
ALPHAPROGRESS2=$(($ALPHAPROGRESS*2)) ALPHAPROGRESS3=$(($ALPHAPROGRESS*3)) ALPHAPROGRESS4=$(($ALPHAPROGRESS*4))
f_benchmark
f_estimate
[ "$ESTIMATEHS" -lt 120 ] && echo -n " [»] durée estimée de traitement: $ESTIMATE "\
|| echo -n " [»] durée estimée de traitement: $ESTIMATE (début $(date +%T)) "
time\
for WORKAROUND in 1
do
for b in $INSTALLED
do
f_progress
RESULTF="$RESULTF $(echo "$PRERESULT"|grep -xm 1 $b)"
done
f_clearline b 1 1
done
printf '%b\n' $RESULTF|sort -d > $CACHEDIR/sources/$a
echo "$MACHINE $(date "+%F %T") nouvelle source $a ajoutée" >>~/.$PROGNAME/$MACHINE/history.txt
RESULTFC=$(echo $RESULTF | wc -w)
[ $RESULTFC -ne 0 ] && echo " [*] $RESULTFC occurrences" || echo " [×] pas d'occurrence"
echo ; unset -v PROGRESS RESULTF
[ $TSOURCESM = $CSOURCES ] && local TIMEFORMAT=" [»] durée totale de traitement: %lR" && unset -v DEL SOURCESNEWS TSOURCESM
done
echo >>~/.$PROGNAME/$MACHINE/history.txt; echo; echo; read -s -n 1 -p " [-] valider pour continuer... "; f_clearline r 1 35; $CLEAR
}
f_updatecache()
{
mv -f $CACHEDIR/Installed $CACHEDIR/.old/ 2>/dev/null; printf '%b\n' $INSTALLED > $CACHEDIR/Installed
[ -f $CACHEDIR/.old/Installed ] || return
ISUPR=$(echo $(diff -y --suppress-common-lines $CACHEDIR/.old/Installed $CACHEDIR/Installed |cut -d'>' -f1 |cut -d'<' -f1))
INEWS=$(echo $(diff -y --suppress-common-lines $CACHEDIR/.old/Installed $CACHEDIR/Installed |cut -d'>' -f2 |cut -d'<' -f3))
[ -z "$ISUPR" -a -z "$INEWS" ] && return
echo -e "\n [>] Mise à jour du cache...\c"; mv -f $CACHEDIR/sources/* $CACHEDIR/.old/sources/ 2>/dev/null
for s in $(ls $CACHEDIR/.old/sources/)
do
## supprime du cache les occurrences desinstallees
for r in $ISUPR
do
grep -vx "$r" $CACHEDIR/.old/sources/$s > $CACHEDIR/sources/$s && cp -f $CACHEDIR/sources/$s $CACHEDIR/.old/sources/$s
done
PRERESULT=$(grep "^Package: " $SOURCESDIR$s | mawk '{print $2}')
cp -uf $CACHEDIR/.old/sources/$s $CACHEDIR/sources/$s
## ajoute au cache les nouvelles occurrences installees si elles apparaissent dans la source sauf si elles y sont deja
for n in $INEWS
do
grep -qxm 1 "$n" $CACHEDIR/sources/$s &>/dev/null && continue
echo "$PRERESULT"|grep -xm 1 "$n" >> $CACHEDIR/sources/$s
done
printf '%b\n' $(echo $(sort -d $CACHEDIR/sources/$s)) > $CACHEDIR/sources/$s
done
rm -f $CACHEDIR/.old/sources/* 2>/dev/null; f_clearline r 1 30
## il est a noter que les paquets obsoletes (plus presents dans les sources) sont conserves dans le cache et analysables comme obsoletes
}
f_selectsources()
{
unset -v RESUME TSOURCES
## formatage des sources pour la presentation, comptage des sources, presentation
for a in $SOURCES
do
[ "$(ls -sh $SOURCESDIR$a | mawk '{print $1}')" = "0" ]\
&& SOURCESP="$SOURCESP $(ls -sh $SOURCESDIR$a | mawk '{print $1"B"}') $a"\
|| SOURCESP="$SOURCESP $(ls -sh $SOURCESDIR$a | mawk '{print $1}') $a"
let TSOURCES++
done
[ -n "$ISUPR" -o -n "$INEWS" ] || echo; unset -v ISUPR INEWS
echo " [>] $TSOURCES sources de paquets actuellement sélectionnées pour analyse:"
echo ; unset -v TSOURCES
printf ' [%b]\t» %b\n' $SOURCESP
echo
read -p " [¿] Sélectionner ou éliminer (préfixe «-») un motif pour filtrer, valider pour terminer: " MOTIF
## si le MOTIF est vide, SOURCESS n'est pas initialisee par la boucle d'inclusion. On l'initialise a SOURCESS=$SOURCES
[ "$MOTIF" = "" ] && SOURCESS=$SOURCES
until [ "$MOTIF" = "" ]
do
MOTIFS="$MOTIFS $MOTIF"
read -p " [¿] continuer la sélection des sources à analyser, valider pour terminer: " MOTIF
done
## s'il n'y a que des eliminations, SOURCESS n'est pas initialisee par la boucle d'inclusion. On l'initialise a SOURCESS=$SOURCES
for m in $MOTIFS ; do MOTIFC="$(echo $m | cut -c 1) $MOTIFC" ; done
MCM=$(printf '%b\n' $MOTIFC | grep -c "-") MC=$( printf '%b\n' $MOTIFC | grep -c "")
[ "$MCM" = "$MC" ] && SOURCESS=$SOURCES
## boucle d'inclusion. La boucle interne permet de ne pas inclure une source deja presente (doublon)
for MOTIF in $MOTIFS
do
MOTIFC=$(echo $MOTIF | cut -c 1)
[ "$MOTIFC" != "-" ] && SELECT=$(printf '%b\n' $SOURCES | grep $MOTIF) || continue
for s in $SELECT
do
[[ $(printf '%b\n' "$SOURCESS" | grep -w "$s") ]] && continue
SOURCESS="$SOURCESS $s"
done
done
## boucle d'exclusion
for MOTIF in $MOTIFS
do
MOTIFC=$(echo $MOTIF | cut -c 1)
[ "$MOTIFC" = "-" ] && MOTIF=$(echo $MOTIF | cut -c 2-) && SOURCESS=$(printf '%b\n' $SOURCESS | grep -v $MOTIF)
done
SOURCES=$SOURCESS
echo
## exclusion des fichiers qui ne sont pas des descripteurs de paquets
echo " [>] Analyse des sources:"
[ "$SOURCES" != "" ] && NSOURCES=$(printf '%b\n' $SOURCES | grep -c "") || NSOURCES=0
for a in $SOURCES
do
if ! grep -qm 1 "^Package: " $SOURCESDIR$a
then
[ "$(ls -sh $SOURCESDIR$a | mawk '{print $1}')" = "0" ]\
&& b=$(ls -sh $SOURCESDIR$a | mawk '{print $1"B"}')\
|| b=$(ls -sh $SOURCESDIR$a | mawk '{print $1}')
echo " [×] non pertinente: $a [$b]"
continue
fi
SOURCESC="$SOURCESC $a" ; let TSOURCES++
done
SOURCES="$SOURCESC"; unset -v MOTIFC MOTIFS SOURCESC SOURCESP SOURCESS
[ "$SOURCES" = "" ] && TSOURCES=0
[ "$TSOURCES" != "0" ]\
&& SOURCES=$(printf '%b\n' $SOURCES|sort -d) SOURCES=$(echo $SOURCES)\
&& echo " [»] $TSOURCES sources sur $NSOURCES à traiter dans la sélection:" && printf ' [*] [%b]\n' $SOURCES\
|| echo " [»] pas de sources à traiter dans la sélection"
echo
while true; do let COUNT++; echo ${FUNCNAME[$COUNT]}|grep -qx main && MAIN=$COUNT && unset -v COUNT && break; done
RESUME=* ; echo " [-] Aide - Accueil - Quitter <h/w/q>"
while true
do
case "$RESUME" in
q|Q) f_exit; RESUME=*;;
h) less $0; RESUME=*;;
w) read -s -n 1 -p " [¿] Retourner à l'accueil ? <O/n>: " RESUME; [ "$RESUME" = n ] && f_clearline r 1 40 || { $ECHO; break $MAIN; };;
p) [ "$TSOURCES" != "0" ] && $CLEAR && f_selectsources || RESUME=r;;
l|L|"") [ "$TSOURCES" != "0" ] && break || [ "$RESUME" = "" ] && RESUME=r || RESUME=*;;
r|R) $CLEAR; f_init; f_selectsources;;
*) [ "$TSOURCES" != "0" ]\
&& read -s -n 1 -p " [¿] Préciser encore la sélection - Recommencer - Lancer l'analyse <p/r/L>: " RESUME\
&& f_clearline r 1 104
[ "$TSOURCES" = "0" ] && read -s -n 1 -p " [¿] Recommencer <R>: " RESUME && f_clearline r 1 50;;
esac
done
}
f_occm()
{
while true
do
read -s -n 1 -p " [¿] Par la suite traiter aussi les sources sans occurrences ? <o/N>: " SELECT
f_clearline r 1 75
case "$SELECT" in
q|Q) f_exit;;
h) less $0;;
w) read -s -n 1 -p " [¿] Retourner à l'accueil ? <O/n>: " RESUME; [ "$RESUME" = n ] && f_clearline r 1 40 || { $ECHO; break 2; };;
o|O) OCCLESS=0 ; unset -v SELECT ; $CLEAR ; break;;
n|N|"") OCCLESS=1 ; unset -v SELECT ; $CLEAR ; break;;
esac
done
}
f_squeezecache()
{
echo
for s in $SOURCES
do
local CSOURCES CSOURCESM CSOURCESS ; let CSOURCES++ ; let CSOURCESS++
RESULTF=$(cat $CACHEDIR/sources/$s) RESULTFC=$(echo $RESULTF | wc -w)
## eval interprete l'item suivant dans la liste comme une commande s'il y a un espace
RESULTF=`echo $RESULTF|mawk '{gsub(" ","¿");print $0}'`
## attribution d'une variable dynamique au resultat individuel - utilisation de eval
## identification par le n° de traitement $CSOURCES, attribution du contenu de RESULTF a la nouvelle variable
## la nouvelle variable recoit le nom de la source en alias, permet la concordance n°/nom
[ $RESULTFC -ne 0 ] && eval RESULTF$CSOURCES="$RESULTF" && eval alias RESULTF$CSOURCES=$s\
&& echo -e " [*] $RESULTFC occurrences\t$s"
[ $RESULTFC -eq 0 -a $OCCLESS -eq 0 ] && eval RESULTF$CSOURCES="$RESULTF" && eval alias RESULTF$CSOURCES=$s\
&& echo -e " [×] pas d'occurrence\t$s" && let CSOURCESM++
[ $RESULTFC -eq 0 -a $OCCLESS -eq 1 ] && let CSOURCES-- && echo -e " [×] pas d'occurrence\t$s"
unset -v RESULTF
done
echo ; TSOURCES=$CSOURCES ; [ -z $CSOURCESM ] && CSOURCESM=0
echo " [»] $(($CSOURCES - $CSOURCESM)) sources sur $CSOURCESS présentent des occurrences de paquets installés sur $MACHINE"
echo ; unset -v CSOURCESM CSOURCESS CSOURCES
## concatenation des resultats individuels - utilisation de la substitution de variable {!RESULTF}
for (( n=1; n <= TSOURCES; n++ ))
do
RESULTF=RESULTF$n ## RESULTF se substitue a la variable dynamique dont le contenu est appele par {!RESULTF}
RESULTFP=`echo ${!RESULTF}|mawk '{gsub("¿"," ");print $0}'` ; RESULTFP=$(echo $RESULTFP)
RESULTFT="$RESULTFT $RESULTFP" ## concatenation, doublons compris elimines par sort -u par la suite
SOURCESN="$SOURCESN $n" ## extrait les numeros des sources disponibles de 1 a n sources
done
SOURCESN=$(echo $SOURCESN) SOURCESNP=`echo $SOURCESN|mawk '{gsub(" ","\&|");print $0}'`
RESULTFTS=$(printf '%b\n' $RESULTFT | sort -d) RESULTFTU=$(echo $(printf '%b\n' $RESULTFT | sort -u))
RESULTFTC=$(echo $RESULTFT|wc -w) RESULTFTUC=$(echo $RESULTFTU|wc -w) RESULTFTCC=$(($RESULTFTC-$RESULTFTUC))
UNKNOWNS=$(printf '%b\n' $INSTALLED $RESULTFTU|sort -d|uniq -u) UNKNOWNC=$(echo $UNKNOWNS|wc -w)
NOPURGE=`dpkg --admindir=$INSTALLDIR -l|grep "^rc "|mawk '{print $2}'` NOPURGEC=$(echo $NOPURGE|wc -w)
echo
echo " [*] paquets installés sur $MACHINE: $NINSTALLED"
echo " [*] occurrences installées sur $MACHINE: $RESULTFTUC"
echo " [*] paquets installés non analysés: $(($NINSTALLED-$RESULTFTUC))"
echo " [*] croisements d'occurrences: $RESULTFTCC"
echo " [*] occurrences totales: $RESULTFTC"
echo
}
f_postproc()
{
f_fmt() { fmt -w $(tput cols); }
f_tee() { [ $RECORD = 1 ] && tee -a $RECFILE || tee; }
f_less() { [ $LESS = 1 ] && less -m~ || tee; }
f_pager()
{
read -s -n 1 -p " [¿] afficher les occurrences avec Less - directement - ne pas afficher <L/d/n>: " PAGER
f_clearline r 1 80 ; [ "$PAGER" = "d" -o "$PAGER" = "n" ] || PAGER=L ; PAGERM="\c"
[ "$PAGER" = L ] && LESS=1 PAGERM=" [affichage dans le pager]" || LESS=0; [ "$PAGER" = n ] && PAGERM=" -------------------------"
}
f_adv()
{
trap 'break' SIGUSR1
while true
do
echo -ne "\b\b\b\b» "; sleep .5; echo -ne "\b\b\b\b»» "; sleep .5
echo -ne "\b\b\b\b»»» "; sleep .5; echo -ne "\b\b\b\b "; sleep .5
done
}
f_dores()
{
for S in $S
do
RESULTF=RESULTF$S RESULTFALIAS=$(eval alias RESULTF$S | cut -d "'" -f2) ; [ "$1" = "-a" ] && return
RESULTF=`echo ${!RESULTF}|mawk '{gsub("¿"," ");print $0}'` ; RESULTF=$(echo $RESULTF)
RESULTFC=$(echo $RESULTF|wc -w) ; [ "$1" = "-r" ] && return
OBSOLETES=OBSOLETES$S; OBSOLETES=`echo ${!OBSOLETES}|mawk '{gsub("¿"," ");print $0}'`
OBSOLETES=$(echo $OBSOLETES); OBSOLETESC=$(echo $OBSOLETES|wc -w)
done
}
f_obs()
{
[ -n "$OBSOLETESTC" ] && return
echo -n " [»] traitement "; trap 'kill $(jobs -p f_adv); echo; exit' 2 3 9 15; f_adv &
for S in $SOURCESN
do
f_dores -r; unset -v OBSOLETES
for p in $RESULTF
do
grep -qxm 1 "Package: $p" $SOURCESDIR$RESULTFALIAS\
|| OBSOLETES="$OBSOLETES¿$p" OBSOLETEST="$OBSOLETEST $p"
done
eval OBSOLETES$S="$OBSOLETES"
done
OBSOLETEST=$(printf '%b\n' $OBSOLETEST|sort -u) OBSOLETESTC=$(echo $OBSOLETEST|wc -w)
for o in $OBSOLETEST
do
unset -v COUNTER NOBS
for S in $SOURCESN
do
f_dores -r
let COUNTER++; [ $COUNTER -eq 1 ]\
&& LOCI=$(grep -xnm 1 "Package: $o" $INSTALLDIR/status|cut -d: -f1) LOCIF=$(($LOCI+15))\
&& VERI=`mawk 'NR==LOCI,NR==LOCIF {print $0}' LOCI=$LOCI LOCIF=$LOCIF $INSTALLDIR/status|grep -m 1 "^Version: "`\
&& OBSOLETESTR="$OBSOLETESTR $o"
LOC=$(grep -xnm 1 "Package: $o" $SOURCESDIR$RESULTFALIAS); [ -z "$LOC" ] && continue
LOC=$(echo $LOC|cut -d: -f1) LOCF=$(($LOC+15))
VER=`mawk 'NR==LOC,NR==LOCF {print $0}' LOC=$LOC LOCF=$LOCF $SOURCESDIR$RESULTFALIAS|grep -m 1 "^Version: "`
[ "$VERI" = "$VER" ] && NOBS=1
done
[ -n "$NOBS" ] && OBSOLETESTR=$(printf '%b\n' $OBSOLETESTR|grep -vx $o)
done
OBSOLETESTRC=$(echo $OBSOLETESTR|wc -w); unset -v COUNTER; kill -s SIGUSR1 $(jobs -p f_adv); trap 2 3 9 15; f_clearline r 1 22
}
f_twin()
{
[ -n "$TWIN" -o -n "$SINGLE" ] && return
echo -n " [»] traitement "; trap 'kill $(jobs -p f_adv); echo; exit' 2 3 9 15; f_adv &
for u in $RESULTFTU
do
unset -v COUNTER
for s in $RESULTFTS
do
[[ "$u" != "$s" ]] && continue
let COUNTER++
done
[[ "$COUNTER" < 2 ]] && SINGLE="$SINGLE $u" && continue
TWIN="$TWIN $u"
TWINP="$TWINP $COUNTER"¿"$u"
done
TWINC=$(echo $TWIN|wc -w) SINGLEC=$(echo $SINGLE|wc -w)
TWINP=`printf ' %b\n' $TWINP|sort -d|mawk '{gsub("¿","× ");print $0}'`
SINGLEP=$(printf ' [%b]' $SINGLE) ; TWIND=$(printf '%b\n' $TWIN)
unset -v COUNTER; kill -s SIGUSR1 $(jobs -p f_adv); trap 2 3 9 15; f_clearline r 1 22
}
f_displayg()
{
{ echo; echo " [>] [$MACHINE] Occurrences globales:"; }|f_tee
[ "$SOURCESG" = "" ] &&\
for S in $SOURCESN;do f_dores -r;[ $RESULTFC -ne 0 ] && SOURCESG="$SOURCESG $RESULTFALIAS" && SOURCESNG="$SOURCESNG $S" && let SOURCESGC++
done
[ "$SOURCESG" = "" ] && { echo " [×] Aucune des sources analysées n'a d'occurrence installée sur $MACHINE"; echo -e "\n\n"; }|f_tee && return
{ echo " [»] $SOURCESGC sources analysées ont des occurrences installées sur $MACHINE:"; echo; }|f_tee
for S in $SOURCESNG; do f_dores -r; echo " [$S] $RESULTFALIAS [$RESULTFC occurrences]"|f_tee; TTLOCC=$(($TTLOCC+$RESULTFC)); done
f_obs
NOSOURCEDC=$(($OBSOLETESTRC+$UNKNOWNC)) SOURCEDC=$(($RESULTFTUC-$OBSOLETESTRC))
{ echo " [*] total: $TTLOCC occurrences"; echo; echo " [*] $NINSTALLED paquets installés sur $MACHINE"
echo " [*] $NOPURGEC paquets supprimés de $MACHINE mais non purgés"
echo " [*] $NOSOURCEDC paquets installés non présents dans les sources analysées"
echo " [*] dont $OBSOLETESTRC paquets obsolètes et $UNKNOWNC paquets d'origine inconnue"
echo " [*] $SOURCEDC paquets installés présents dans les sources analysées:"; echo; }|f_tee ; unset -v TTLOCC
f_pager
[ "$SOURCEDP" = "" ] && SOURCEDP=$(printf ' [%b]' $(printf '%b\n' $OBSOLETESTR $RESULTFTU|sort -d|uniq -u))
[ "$NOSOURCEDP" = "" ] && NOSOURCEDP=$(printf ' [%b]' $(printf '%b\n' $OBSOLETESTR $UNKNOWNS|sort -d))
[ "$NOPURGEP" = "" ] && NOPURGEP=$(printf ' [%b]' $NOPURGE)
[ $PAGER = L ] && { printf '\n%b\n' " [*] $SOURCEDC paquets installés présents dans les sources analysées:" "$SOURCEDP"|f_fmt
[ $NOSOURCEDC -gt 0 ] && printf '\n%b\n' " [*] $NOSOURCEDC paquets installés non présents dans les sources analysées:" "$NOSOURCEDP"|f_fmt
[ $NOPURGEC -gt 0 ] && printf '\n%b\n' " [*] $NOPURGEC paquets supprimés de $MACHINE mais non purgés:" "$NOPURGEP"|f_fmt; }|f_tee |f_less
[ $PAGER = d ] && { echo "$SOURCEDP"|f_fmt; [ $NOSOURCEDC -gt 0 ] &&\
printf '\n%b\n' " [*] $NOSOURCEDC paquets installés non présents dans les sources analysées:" "$NOSOURCEDP"|f_fmt
[ $NOPURGEC -gt 0 ] && printf '\n%b\n' " [*] $NOPURGEC paquets supprimés de $MACHINE mais non purgés:" "$NOPURGEP"|f_fmt; } |f_tee
[ $PAGER = n ] && echo -e "$PAGERM"|f_tee || echo -e "$PAGERM"; { echo ; echo; }|f_tee
[ $TSOURCES -eq 1 ] && { [ $RECORD = 1 ] && echo -e " [-] la séquence a été enregistrée dans $RECFILE\n\n" || echo; } && return
f_twin
[ $TWINC -eq 0 ] && { echo " [×] aucun croisement d'occurrence de paquets installés sur $MACHINE entre les sources analysées"
echo -e "\n\n"; }|f_tee && return
{ echo " [*] $SINGLEC occurrences uniques";echo " [*] $RESULTFTCC croisements d'occurrences";echo " [*] $TWINC occurrences croisées:"; }|f_tee
f_pager
[ $PAGER = L ] && { printf '\n%b\n%b\n\n%b' " [*] $RESULTFTCC croisements d'occurrences" " [*] $TWINC occurrences croisées:" "$TWINP"
printf '\n\n\n%b\n\n%b' " [*] $SINGLEC occurrences uniques:" "$SINGLEP"|f_fmt; }|f_tee |f_less && echo -e "\n$PAGERM"
[ $PAGER = d ] && { echo -e "\n$TWINP";echo -e "\n";echo -e " [*] $SINGLEC occurrences uniques:\n";echo "$SINGLEP"|f_fmt; }|f_tee
[ $PAGER = n ] && echo -e "\n$PAGERM"|f_tee
[ $RECORD = 1 ] && echo -e "\n\n [-] la séquence a été enregistrée dans $RECFILE\n\n" || echo -e "\n\n"
}
f_display()
{
{ echo; echo " [>] [$MACHINE] Occurrences par sources:"; echo; }|f_tee
{ for (( S=1; S <= $TSOURCES; S++ )); do f_dores -r; echo $SELECTS|grep -w $S &>/dev/null
[ $? -eq 0 ] && echo " [$S] $RESULTFALIAS [$RESULTFC occurrences]" || echo " [×]";done; }|f_tee
f_pager
[ $PAGER != n ] && f_obs &&\
for S in $SELECTS
do
f_dores
echo -e "\n [*] $RESULTFC occurrences installées présentes dans le cache de la source [$RESULTFALIAS]:"
[ $RESULTFC -ne 0 ] && echo && printf ' [%b]' $RESULTF|f_fmt; echo
[ $OBSOLETESC -ne 0 ] && echo " [*] dont $OBSOLETESC occurrences obsolètes:" && printf ' [%b]' $OBSOLETES|f_fmt && echo
done |f_tee|f_less ; echo|f_tee
[ $PAGER = n ] && echo -e "$PAGERM\n"|f_tee || echo -e "$PAGERM\n"; echo|f_tee
{ printf " [»] occurrences uniques et croisées des sources"; printf ' [%b]' $SELECTS; echo ":"; }|f_tee
f_pager
f_sort()
{
f_twin
for S in $SELECTS
do
f_dores -r
for r in $RESULTF
do
echo "$TWIND"|grep -qxm 1 "$r" &>/dev/null && MULTIX="$MULTIX $r" && continue
UNIX="$UNIX $r"
done
UNIXC=$(echo $UNIX|wc -w) MULTIXC=$(echo $MULTIX|wc -w)
echo -e "\n [$S] $RESULTFALIAS [$(($UNIXC+$MULTIXC)) occurrences]" ; echo
[ $UNIXC -ne 0 ] && echo " [*] $UNIXC occurrences uniques:" && printf ' [%b]' $UNIX|f_fmt && echo
[ $MULTIXC -ne 0 ] && echo " [*] $MULTIXC occurrences croisées:" && printf ' [%b]' $MULTIX|f_fmt && echo
unset -v UNIX MULTIX
done |f_tee |f_less ; echo -e "\n$PAGERM\n\n"
[ $RECORD = 1 ] && echo -e " [-] la séquence a été enregistrée dans $RECFILE\n\n" || echo
}
[ $PAGER != n ] && f_sort || echo -e "\n$PAGERM\n\n\n"|f_tee
}
f_displaym()
{
echo; echo " [>] [$MACHINE] Occurrences par sources:"; echo
for ((S=1;S<=TSOURCES;S++)); do f_dores -r; echo " [$S] $RESULTFALIAS [$RESULTFC occurrences]"; done; echo
while true
do
read -p " [¿] afficher les occurrences pour $SOURCESNP (défaut &) <$SOURCESN>: " SELECTS
case "$SELECTS" in
q|Q) f_exit;;
h) less $0;;
"") SELECTS=$SOURCESN ; $CLEAR ; f_display ; break;;
*) SELECTS=$(printf '%b\n' $SELECTS|sort -u) doit=1
for s in $SELECTS; do echo $SOURCESN|grep -w $s &>/dev/null; [ $? -ne 0 ] && doit=0; done
[ $doit -ne 0 ] && $CLEAR && f_display && break;;
esac
done
}
f_package()
{
{ echo -e "\n [>] [$MACHINE] Analyse par paquets:\n"; echo " [»] analyse des occurrences croisées entre les sources analysées:"; }|f_tee
f_twin
f_x()
{
{ echo " [*] $RESULTFTCC croisements d'occurrences"
echo " [*] $TWINC occurrences croisées:"; echo; }|f_tee
f_pager
[ $PAGER = n ] && echo -e "$PAGERM\n"|f_tee && return
for x in $TWIN
do
[ -z "$COUNT" -a $PAGER = L ] && printf '%b\n%b\n\n'\
" [*] $RESULTFTCC croisements d'occurrences" " [*] $TWINC occurrences croisées:"
let COUNT++; echo " [$COUNT] [$x]"; unset -v COUNTER
for S in $SOURCESN
do
f_dores -r; let COUNTER++
[ $COUNTER -eq 1 ]\
&& LOCI=$(grep -xnm 1 "Package: $x" $INSTALLDIR/status|cut -d: -f1) LOCIF=$(($LOCI+15))\
&& VERI=`mawk 'NR==LOCI,NR==LOCIF {print $0}' LOCI=$LOCI LOCIF=$LOCIF $INSTALLDIR/status|grep -m 1 "^Version: "`\
&& STATI=`mawk 'NR==LOCI,NR==LOCIF {print $0}' LOCI=$LOCI LOCIF=$LOCIF $INSTALLDIR/status|grep -m 1 "^Status: "`\
&& echo -e " $VERI $STATI"\
&& for d in $(ls $CACHEDIR/.old/sources/.deleted/)
do grep -qxm 1 "$x" $CACHEDIR/.old/sources/.deleted/$d && echo " présent dans la source supprimée $d"; done
LOC=$(grep -xnm 1 "Package: $x" $SOURCESDIR$RESULTFALIAS)
[ -z "$LOC" ] && { printf '%b\n' $RESULTF|grep -qxm 1 $x && echo " obsolète dans $RESULTFALIAS"; true; } && continue
LOC=$(echo $LOC|cut -d: -f1) LOCF=$(($LOC+15))
VER=`mawk 'NR==LOC,NR==LOCF {print $0}' LOC=$LOC LOCF=$LOCF $SOURCESDIR$RESULTFALIAS|grep -m 1 "^Version: "`
printf ' %b %b\n' "$VER" "dans $RESULTFALIAS"
done
echo
done |f_tee |f_less ; unset -v COUNT COUNTER; echo -e "$PAGERM\n"
}
[ $TWINC -eq 0 ]&&echo -e " [×] aucun croisement d'occurrences de paquets installés sur $MACHINE entre les sources analysées\n"|f_tee||f_x
echo -e "\n\n [»] analyse des paquets installés non présents dans les sources analysées:"|f_tee
f_u()
{
echo " [*] $UNKNOWNC paquets installés non présents dans les sources analysées:"|f_tee
f_pager; [ $PAGER = n ] && echo -e "\n$PAGERM\n"|f_tee && return
{ COUNT=0 TUNKNOWNS=$UNKNOWNS; [ $PAGER = L ] && echo " [*] $UNKNOWNC paquets installés non présents dans les sources analysées:"
for u in $UNKNOWNS
do
unset -v COUNTER
for d in $(ls $CACHEDIR/.old/sources/.deleted/)
do
grep -qxm 1 "$u" $CACHEDIR/.old/sources/.deleted/$d && { TUNKNOWNS=$(printf '%b\n' $TUNKNOWNS|grep -vx $u); let COUNTER++
[ $COUNTER -eq 1 ] && { let COUNT++; echo -e "\n [$COUNT] [$u]"; }; echo " origine possible: source supprimée [$d]"; }
done
done
[ $COUNT -gt 0 -a $COUNT -lt $UNKNOWNC ] && { echo -e \
"\n [×] les données dont dispose $PROGNAME sont trop récentes pour déterminer l'origine des $(($UNKNOWNC-$COUNT)) autres paquets:"
printf ' [%b]' $TUNKNOWNS|f_fmt; }\
|| { [ $COUNT -eq 0 ]&&echo " [×] les données dont dispose $PROGNAME sont trop récentes pour déterminer l'origine des $UNKNOWNC paquets:"
printf ' [%b]' $TUNKNOWNS|f_fmt; }; }|f_tee |f_less; unset -v COUNT COUNTER; echo -e "\n$PAGERM\n"
}
[ $UNKNOWNC -eq 0 ] && echo -e " [×] aucun paquet d'origine inconnue installé sur $MACHINE\n"|f_tee || f_u
echo -e "\n\n [»] analyse des occurrences obsolètes dans le cache des sources analysées:"|f_tee
f_obs
f_o()
{
echo " [*] $OBSOLETESTC occurrences obsolètes:"|f_tee
f_pager; [ $PAGER = n ] && echo -e "\n$PAGERM\n"|f_tee && return
{ OBS=$OBSOLETESTC; echo; [ $PAGER = L ] && { echo " [*] $OBSOLETESTC occurrences obsolètes:"; echo; }
for o in $OBSOLETEST
do
let COUNT++; unset -v COUNTER NOBS
for S in $SOURCESN
do
f_dores -r
let COUNTER++; [ $COUNTER -eq 1 ] && echo " [$COUNT] [$o]"\
&& LOCI=$(grep -xnm 1 "Package: $o" $INSTALLDIR/status|cut -d: -f1) LOCIF=$(($LOCI+15))\
&& VERI=`mawk 'NR==LOCI,NR==LOCIF {print $0}' LOCI=$LOCI LOCIF=$LOCIF $INSTALLDIR/status|grep -m 1 "^Version: "`\
&& STATI=`mawk 'NR==LOCI,NR==LOCIF {print $0}' LOCI=$LOCI LOCIF=$LOCIF $INSTALLDIR/status|grep -m 1 "^Status: "`\
&& echo " $VERI $STATI" && OBSR="$OBSR $o"
LOC=$(grep -xnm 1 "Package: $o" $SOURCESDIR$RESULTFALIAS)
[ -z "$LOC" ] && { printf '%b\n' $RESULTF|grep -qxm 1 $o && echo " obsolète dans $RESULTFALIAS"; true; }\
&& continue
LOC=$(echo $LOC|cut -d: -f1) LOCF=$(($LOC+15))
VER=`mawk 'NR==LOC,NR==LOCF {print $0}' LOC=$LOC LOCF=$LOCF $SOURCESDIR$RESULTFALIAS|grep -m 1 "^Version: "`
printf ' %b %b\n' "$VER" "dans $RESULTFALIAS" ; [ "$VERI" = "$VER" ] && NOBS=1
done
[ -n "$NOBS" ] && { echo " [¡] la version installée de $o n'est PAS obsolète"; let OBS--; OBSR=$(printf '%b\n' $OBSR|grep -vx $o); }
echo
done
[ $OBS -eq 0 ] && echo " [×] aucun des paquets installés sur $MACHINE n'est obsolète"\
|| { echo -e "\n [*] $OBS paquets installés sur $MACHINE sont obsolètes:"; printf ' [%b]' $OBSR|f_fmt; echo; }
[ $UNKNOWNC -ne 0 ]\
&& echo " [¡] il est possible que les $UNKNOWNC paquets non présents dans les sources analysées soient obsolètes"
} |f_tee |f_less; unset -v COUNT COUNTER; echo -e "\n$PAGERM\n"
}
[ $OBSOLETESTC -eq 0 ] && { echo " [×] aucune occurrence obsolète de paquets installés sur $MACHINE dans les sources analysées"
[ $UNKNOWNC -ne 0 ] &&\
echo -e " [¡] il est possible que les $UNKNOWNC paquets non présents dans les sources analysées soient obsolètes\n\n"; } |f_tee || f_o
[ $RECORD = 1 ] && echo -e "\n [-] la séquence a été enregistrée dans $RECFILE\n\n" || echo -e "\n\n"
}
echo
[ $TSOURCES -eq 0 -a $OCCLESS -eq 1 ]\
&& echo " [>] Aucune des sources traitées ne présente d'occurrence en concordance avec les paquets installés sur $MACHINE"\
&& echo " [»] aucune analyse à effectuer" && echo && read -s -n 1 -p " [-] valider pour continuer... " && f_clearline r 1 35 && return 2
echo " __________________________________________________________________________"
echo " [-] Enregistrer la prochaine séquence - Aide - Accueil - Quitter <r/h/w/q>" ; RECORD=0 REC=""
while true
do
read -s -n 1 -p " [¿]$REC [$MACHINE]: Analyse globale - Par sources - Par paquets <g/s/p>: " SELECT
f_clearline r 1 110
case "$SELECT" in
q|Q) f_exit;;
h) less $0;;
w) read -s -n 1 -p " [¿] Retourner à l'accueil ? <O/n>: " RESUME; [ "$RESUME" = n ] && f_clearline r 1 40 || { $ECHO; return; };;
r) REC=" [R]" RECORD=1;echo -e "\n\n $(date)" >>$RECFILE;;
g) $CLEAR; f_displayg;break;;
s) $CLEAR; f_displaym;break;;
p) $CLEAR; f_package;break;;
esac
done
f_postproc
}
f_home()
{
[ -d ~/.$PROGNAME/$(uname -n) ] || { $CLEAR; echo -e "\n [>] Initialisation de $PROGNAME\n"; MACHINE=$(uname -n)
f_init; f_mkcache; f_updatecache; trap 2 3 9 15; return; }
[ -d ~/.$PROGNAME/_alternate ] || { mkdir -p ~/.$PROGNAME/_alternate/
echo "Copiez ici les répertoires /var/lib/apt/lists/ et /var/lib/dpkg/ d'un système alternatif que vous souhaitez analyser"\
> ~/.$PROGNAME/_alternate/readme.txt; }
$CLEAR; echo -e "\n\n\n\n\n\n"
for w in Advanced Packaging Tool DIAGnostic
do
NL=$(echo ${#w}) NLA=$NL; echo -n " "
for ((l=1;l<=NL;l++))
do
L=$(echo $w|cut -c $l); echo $L|grep -q [A-Z] && L="\033[1m$L\033[0m"
for ((la=NLA;la>=0;la--))
do
for ((s=la;s>=1;s--)); do SPACE="$SPACE "; done
echo -ne "$SPACE$L "; NSPACE=$(echo ${#SPACE})
unset -v SPACE; sleep 0.01; [ $NSPACE -eq 0 ] && break
for ((b=1;b<=NSPACE+2;b++)); do echo -ne "\b"; done
done
NLA=$(($NLA-1))
let INTER++; for ((s=2;s<=INTER/2;s++)); do echo -n " "; done
done
echo; unset -v INTER
done
echo -e "\n\n\n\n\n\n\n\n\n\n\n\n\n\n [>] $PROGNAME"; echo
[ -d ~/.$PROGNAME/_alternate/lists/ -a -d ~/.$PROGNAME/_alternate/dpkg/ ] && { echo " [»] un système alternatif a été détecté"
[ -w ~/.$PROGNAME/_alternate/lists/ -a -w ~/.$PROGNAME/_alternate/dpkg/ ]\
|| { echo -e "\a\n [!] la configuration alternative n'a pas les droits en écriture, sortie\n"; exit 1; }
[[ $(ADM=~; dpkg --admindir=$ADM/.$PROGNAME/_alternate/dpkg/ -l 2>/dev/null) ]]\
|| { echo -e "\a\n [!] le répertoire ~/.$PROGNAME/_alternate/dpkg/ n'est pas une configuration valide pour dpkg, sortie\n"; exit 1; }
read -p " [¿] nom du système: " MACHINE; f_clearline r 1 100
MACHINE=$(echo $MACHINE|tr -d ".%$&|<>*\'\"# /\\" 2>/dev/null|tr "[A-Z]" "[a-z]"|sed 's/^-//')
[ $(echo ${#MACHINE}) -gt 35 ] && echo " [!] $MACHINE: ce nom est déraisonnablement long..." && sleep 3 && f_clearline r 1 120 && return
[ -d ~/.$PROGNAME/$MACHINE ] && echo " [!] $MACHINE: ce nom de système est déjà utilisé..." && sleep 3 && f_clearline r 1 100 && return
read -s -n 1 -p " [¿] ce nom est-il correct: $MACHINE ? <O/n>: " RESUME; [ "$RESUME" = n ] && f_clearline r 1 100 && return
$CLEAR; echo -e "\n [>] Initialisation du cache pour $MACHINE\n"; f_init; f_mkcache; f_updatecache; trap 2 3 9 15; return; }
echo " [»] systèmes analysables:"
echo " [1] $(uname -n)"; COUNTER=1 MACHINES=1 MACHINESP=1; unset -v MACHINESUP MACHINESUPP
for m in $(ls ~/.$PROGNAME/)
do
[ "$m" = "$(uname -n)" -o "$m" = "_alternate" ] && continue; [ -d ~/.$PROGNAME/$m ] || continue
let COUNTER++; alias $COUNTER=$m; MACHINES="$MACHINES $COUNTER" MACHINESP="$MACHINESP/$COUNTER"
MACHINESUP="$MACHINESUP $COUNTER" MACHINESUPP="$MACHINESUPP/$COUNTER"; echo " [$COUNTER] $m"
done
echo; unset -v COUNTER; echo " [-] Aide - Accueil - Quitter <h/w/q>"
[ -n "$MACHINESUP" ] && MACHINESUPP=$(echo $MACHINESUPP|sed 's/^\///') &&\
while true
do
read -s -n 1 -p " [¿] Sélectionner un système - Supprimer un système (défaut 1) <$MACHINESP/->: " SELECT
f_clearline r 1 100
case "$SELECT" in
q|Q) f_exit;;
h) less $0;;
w) read -s -n 1 -p " [¿] Recommencer ? <O/n>: " RESUME; [ "$RESUME" = n ] && f_clearline r 1 30 || { $ECHO; return; };;
-) read -s -n 1 -p " [¿] sélectionner un système pour SUPPRESSION <$MACHINESUPP>: " SELECTM; f_clearline r 1 100
echo $MACHINESUP|grep -w $SELECTM &>/dev/null\
&& { read -s -n 1 -p " [¿] supprimer $(alias $SELECTM|cut -d "'" -f2) de $PROGNAME ? <o/N>: " DEL; f_clearline r 1 100
[ "$DEL" = o ] && rm -fr ~/.$PROGNAME/$(alias $SELECTM|cut -d "'" -f2); unset -v DEL; return; };;
""|1) MACHINE=$(uname -n); break;;
*) echo $MACHINES|grep -w $SELECT &>/dev/null && MACHINE=$(alias $SELECT|cut -d "'" -f2) && break;;
esac
done || MACHINE=$(uname -n); for m in $MACHINESUP; do unalias $m &>/dev/null; done
while true
do
read -s -n 1 -p " [¿] [$MACHINE]: travailler sur l'ensemble des sources ? <O/n>: " SELECT
f_clearline r 1 100
case "$SELECT" in
q|Q) f_exit;;
h) less $0;;
w) read -s -n 1 -p " [¿] Recommencer ? <O/n>: " RESUME; [ "$RESUME" = n ] && f_clearline r 1 30 || { $ECHO; return; };;
o|O|"") $CLEAR; echo; f_init; f_mkcache; f_updatecache; trap 2 3 9 15; OCCLESS=1; f_squeezecache; f_postproc; break;;
n) $CLEAR; echo; f_init; f_mkcache; f_updatecache; trap 2 3 9 15; f_selectsources; f_occm; f_squeezecache; f_postproc; break;;
esac
done
}
while true; do f_home; done
PS: heureusement que c'est pas du python parce que l'indentation est un peu aléatoire sur le forum :)
Dernière modification par nofun (23-06-2009 16:12:19)