View previous topic :: View next topic |
Author |
Message |
kaworu Guru
Joined: 07 Dec 2005 Posts: 450
|
Posted: Tue Jan 23, 2007 3:40 pm Post subject: [script] gerer son fichier world avec eworld |
|
|
Introduction
Salut !
depuis que je suis sous Gentoo j'aime bien avoir un contrôle sur mon fichier /var/lib/portage/world. Il y a plusieurs manipulation que je fais souvent, comme par exemple le trier et le copier pour regarder les paquets qu'il y a dedans, ou encore faire une copie de sauvegarde, ou simplement un petit grep <un_paquet> /var/lib/portage/world. Depuis quelques jour j'ai commencé à écrire un petit script pour faire tout ça (parce que je n'ai rien trouvé de tel dans les outils gentoo). Ce script s'apelle "naturelement" eworld, il est écris en bash et il est facilement extensible (il est simple de rajouter de nouvelles actions).
Utilisez eworld
Il suffit de copier le script dans un dossier de votre variable $PATH (comme par exemple /usr/local/bin) puis de le rendre exécutable grâce à la commande chmod.
Code: |
# chmod +x /usr/local/bin/eworld
|
Maintenant vous pouvez lancer et utiliser ce script en tant q'utilisateur
Le lancer sans aucun argument reviens à afficher l'aide (eworld help).
Les actions disponibles
Pour toutes les actions il est maintenant possible de lancer eworld sans couleur. Décommentez la ligne "#NO_COLOR=1" dans le script, ou lancez eworld en exportant la variable $NO_COLOR avant :
Code: |
$ export NO_COLOR=1
$ eworld
|
ou encore
Code: |
$ NO_COLOR=1 eworld
|
eworld help : affiche chaques actions possible avec leur aide d'utilisation.
eworld copy : fait une copie triée du fichier /var/lib/portage/world. Si un argument est donné c'est ce fichier qui sera la copie, autrement le fichier ~/world est crée. /!\ si un fichier ~/world existe déjà il sera écrasé.
exemple :
Code: |
$ eworld copy /home/alex/doc/world_copie
* copy : /var/lib/portage/world to /home/alex/doc/world_copie : OK
$ ls /home/alex/doc/world_copie
/home/alex/doc/world_copie
|
eworld backup : fais une sauvegarde du fichier /var/lib/portage/world actuel. La sauvegarde est faite dans le dossier ~/.eworld/backup (il est possible bien que déconseillé de changer ce répértoire de sauvegarde en changeant la variable $SAVE_DIR dans le script) et le nouveau fichier s'appelle world___<date> où <date> est au format de la commande date "+%Y-%m-%d_%H:%M:%S". Si la variable $AUTO_CLEAN est "yes", l'action clean est automatiquement appelée par backup. Vous pouvez changez cette variable directement dans le script ou si c'est temporaire par un export de variable
Code: |
$ export AUTO_CLEAN="false"
$ eworld backup
|
ou encore
Code: |
$ AUTO_CLEAN="false" eworld backup
|
eworld clean : Nettoie le dossier ~/.eworld/backup. Laisse les 10 fichiers les plus récents et supprime les autres. /!\ Cette action se base sur le nom des fichiers (qui contient la date de leur copie) pour supprimer les plus anciens, donc ne modifier pas leur nom. clean est automatiquement appelée par backup selon la variable $AUTO_CLEAN cf plus haut). Le nombre de fichier à garder peut être changé directement dans le script ou par un export juste avant l'appel à eworld clean :
Code: |
$ export SAVE_DIR_MAXF=0
$ eworld clean
|
ou encore
Code: |
$ SAVE_DIR_MAXF=0 eworld clean
|
eworld update : Met à jours le fichier /var/lib/portage/world. Le fichier donné en argument est copié vers /var/lib/portage/world, si aucun fichier n'est donné en argument le fichier ~/world est pris s'il existe. Si l'utilisateur n'as pas le droit d'écrire dans /var/lib/portage cette action tente de passer par sudo, sinon il vous faudra lancer cette commande avec des droits plus élevés (root ou membre du groupe portage). Avant la mise à jours, l'action backup est appellé afin de faire une sauvegarde. Après la mise à jour la commande /usr/sbin/emaint --check world est appelé pour voir si le nouveau fichier /var/lib/portage/world est correct. Si emaint découvre un problème, update le signalera mais ne tentera pas de réparer le fichier world, c'est à vous de faire le boulot Comme l'action backup est appelée automatiquement il
n'y pas trop de risque.
eworld grep : fais un grep sur le fichier /var/lib/portage/world. simple, utile et évite de tapper le chemin complet du fichier world
exemple :
Code: |
$ eworld grep 'kde-base/.*'
|
est pareil à
Code: |
$ grep --color=auto 'kde-base/.*' /var/lib/portage/world
|
eworld checkdep : Vérifie pour chaque paquet dans le world s'il dépend d'un autre. Cette action est très interessante, car elle permet de "nettoyer" intelligement son fichier world.
Si par exemple vous avez installé dev-lang/php, dev-db/mysql et dev-db/phpmyadmin. Vous utilisez mysql pour autre chose, mais php ne vous est utile uniquement pour phpmyadmin. Dans ce cas, le plus logique est d'avoir mysql et phpmyadmin dans votre world mais pas php. De cette manière le jour où vous décidez de vous séparer de phpmyadmin, le paquet php partira dans un emerge --depclean (si bien sûr, aucun autre programme ne dépend de lui), mais pas mysql (car il est dans votre world). De cette manière, si vous avez les trois dans votre world, eworld checkdep va vous signaler que php et mysql dépendent déjà de phpmyadmin, et vous pouvez vous poser la question "est ce que j'utilise php/mysql uniquement pour phpmyadmin ?". Si oui, vous pouvez retirer la ligne correspondante dans votre fichier world, ou sinon la laisser. Cela permet d'avoir un fichier world plus cohérent avec ce dont vous avez besoin, et permet de nettoyer beaucoup de paquets que l'on a emergé "vite
fais" qui font parti du système etc. Il y a actuellement deux implémentations de cette action. la première (celle par défaut) utilise le programme qdepends du paquet portage-utils et la deuxième utilise equery du paquet gentoolkit. la version avec qdepends est VRAIMENT plus rapide que equery (30secondes pour qdepends contre 15minutes avec equery) mais semble moins pertinente.
le script
Code: |
#!/bin/bash
#
# eworld.sh
#
#
################################################################################
# This program is free software; you can redistribute it and/or #
# modify it under the terms of the GNU General Public License #
# as published by the Free Software Foundation; either version 2 #
# of the License, or (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program; if not, write to the Free Software #
# Foundation, Inc., 51 Franklin Street, Fifth Floor, #
# Boston, MA 02110-1301, USA. #
################################################################################
#
#
#
#-------------- VARIABLES -------------
# do not add variables unless you really
# think that it'll be useful for some
# other action.
# variables must be in UPPER_CASE and
# should be declared like :
# YOUR_VAR=${YOUR_VAR:-"<default>"}
#--------------------------------------
#
# script version
VERSION="0.2.1"
# default world file path/name
WORLD_FILE=${WORLD_FILE:-"/var/lib/portage/world"}
# default copy world file
WORLD_FILE_COPY=${WORLD_FILE_COPY:-"$HOME/world"}
# save directory
SAVE_DIR=${SAVE_DIR:-"$HOME/.eworld"}
# max files in $SAVE_DIR
SAVE_DIR_MAXF=${SAVE_DIR_MAXF:-10}
# auto-clean option
AUTO_CLEAN=${AUTO_CLEAN:-"yes"}
# uncomment the next line if you don't want colored output
#NO_COLOR=1
#-------------- TOOLS -------------
# do not add tools functions unless
# you really think that it'll be
# useful for some other action.
# declare them like :
# my_function() { ...
# and not like :
# function my_function() {
#----------------------------------
#
# error output and exit
# you can use cecho syntax. please do mainingful errors
error() {
cecho -red "* " -bold "ERROR: " "$@"
exit 1
}
# colored echo
# ex : cecho -green "Gen" -blue "too" -red "is the best"
# cecho -nocolor -blue
cecho() {
while [ "$1" ]; do
case "$1" in
-file) color="\033[1m" ;; # bold
-dir) color="\033[34;01m" ;; # blue
-action) color="\033[36;01m" ;; # cyan
-cmd) color="\033[32;01m" ;; # green
-var) color="\033[32;01m" ;; # green
-args) color="\033[33;01m" ;; # yellow
-nc|-nocolor) color="\033[00m" ;;
-bold) color="\033[1m" ;;
-black) color="\033[30;01m" ;;
-red) color="\033[31;01m" ;;
-green) color="\033[32;01m" ;;
-yellow) color="\033[33;01m" ;;
-blue) color="\033[34;01m" ;;
-magenta) color="\033[35;01m" ;;
-cyan) color="\033[36;01m" ;;
-white) color="\033[37;01m" ;;
-darkblack) color="\033[30m" ;;
-darkred) color="\033[31m" ;;
-darkgreen) color="\033[32m" ;;
-darkyellow) color="\033[33m" ;;
-darkblue) color="\033[34m" ;;
-darkmagenta) color="\033[35m" ;;
-darkcyan) color="\033[36m" ;;
-darkwhite) color="\033[37m" ;;
-n) one_line=1; shift ; continue ;;
*) echo -n "$1"; shift ; continue ;;
esac
shift
[ ! "$NO_COLOR" ] && echo -en "$color"
echo -en "$1"
echo -en "\033[00m"
shift
done
if [ ! $one_line ]; then
echo
fi
unset one_line color
}
# test if a program is installed
need() {
if which "$1" &>/dev/null; then
return 0
else
prog=${2:-$1}
error "this script need the \"$prog\" program. please run " -cmd "emerge --ask --verbose $prog"
fi
}
# test if the world file is ok
emaint() {
cecho -n -green "* " "Starting " -cmd "/usr/sbin/emaint --check world"
emaint_error="$(/usr/sbin/emaint --check world | grep -v "Checking world for problems" | grep -v "Finished")"
if [ "$emaint_error" ]; then
echo
error -cmd "emaint" " reported problems in your world file, please fix them."
else
cecho ": OK"
return 0
fi
}
#-------------- ACTIONS -------------
# add your function here. ALL new action
# function MUST begin like :
#
# function _<your_action_name>() {
# #help
# if [ "$1" = "<your_action_name>" ]; then
# cecho -action "<your_action_name> " ": description ..."
# return 0
# fi
# #/help
# ...
# <your code here>
# ...
# }
#
# any new action function will be automatically detected
# and added to help action if declared properly.
#------------------------------------
#
function _help() {
#help
if [ "$1" = "help" ]; then
cecho -action "help " ": display this help (you can use \"h\" or \"--help\" or \"-h\" also)"
return 0
fi
#/help
cecho "$(basename $0) v$VERSION"
cecho "usage : " -cmd "$(basename $0) " -action "<action> " -args "<arg>\n"
cecho "actions :"
for action in $ACTIONS; do
echo -n " "
$action "help"
done
exit 0
}
function _copy() {
#help
if [ "$1" = "help" ]; then
cecho -action "copy " ": copy (and sort) " -file "$WORLD_FILE " "to " -args "<arg> " "(or " -file "$HOME/world " "if no arguments)"
return 0
fi
#/help
dest=${1:-"$WORLD_FILE_COPY"}
if sort "$WORLD_FILE" > "$dest"; then
cecho -green "* " -action "copy " ": " -file "$WORLD_FILE " "to " -file "$dest " ": OK"
else
error -action "copy " ": " -file "$WORLD_FILE " "to " -file "$dest " ": Failed"
fi
}
function _backup() {
#help
if [ "$1" = "help" ]; then
cecho -action "backup " ": save the current " -file "$WORLD_FILE " "to " -dir "$SAVE_DIR" ". use " -action "clean " "if " -var "\$AUTO_CLEAN " "is set to \"yes\" (current value is $AUTO_CLEAN)"
return 0
fi
#/help
if [ ! -e "$SAVE_DIR/backup" ]; then
mkdir "$SAVE_DIR/backup"
fi
now=$(date "+%Y-%m-%d_%H:%M:%S")
backup_file="${SAVE_DIR}/backup/$(basename ${WORLD_FILE})___${now}"
eworld_action copy $backup_file
if [ "$AUTO_CLEAN" = "yes" ]; then
eworld_action clean
fi
cecho -green "* " -action "backup " ": OK"
}
function _clean() {
#help
if [ "$1" = "help" ]; then
cecho -action "clean " ": clean the " -dir "$SAVE_DIR " "directory. Remove all files in this directory but the " -var "\$SAVE_DIR_MAXF " "latest (current value is $SAVE_DIR_MAXF)"
return 0
fi
#/help
nb_files=$(ls -1 "$SAVE_DIR/backup" | wc -l)
if [ $nb_files -gt $SAVE_DIR_MAXF ]; then
let "nb_files_to_rm = nb_files - SAVE_DIR_MAXF"
files_to_rm="$(ls -1 "$SAVE_DIR/backup" | head -n $nb_files_to_rm)"
for _file in $files_to_rm; do
rm -f "${SAVE_DIR}/backup/${_file}"
done
cecho -green "* " -action "clean " ": $nb_files_to_rm files removed"
else
cecho -green "* " -action "clean " ": Nothing need to be cleanned ;)"
fi
}
function _update() {
#help
if [ "$1" = "help" ]; then
cecho -action "update " ": copy " -args "<arg> " "to " -file "$WORLD_FILE " "(" -file "$WORLD_FILE_COPY " "is used if no argument). use sudo if you're not allowed to write in " -dir "$(dirname $WORLD_FILE)" ". use " -action "backup" ". use " -cmd "/usr/sbin/emaint " "to check " -file "$WORLD_FILE " "after update."
return 0
fi
#/help
if [ -w "$(dirname $WORLD_FILE)" ]; then
copy_command="cp"
else
need sudo
cecho -yellow "* " "using sudo"
copy_command="sudo cp"
fi
src_file=${1:-"$WORLD_FILE_COPY"}
if [ ! -f "$src_file" ]; then
error "No " -file "$src_file " "to copy"
fi
eworld_action backup
if $copy_command "$src_file" "$WORLD_FILE"; then
cecho -green "* " -action "update " ": $copy_command " -file "$src_file " -file "$WORLD_FILE " ": OK"
else
error -action "update " ": $copy_command " -file "$src_file " -file "$WORLD_FILE " ": Failed"
fi
emaint
}
function _grep() {
#help
if [ "$1" = "help" ]; then
cecho -action "grep " ": grep " -args "<arg> " -file "$WORLD_FILE "
return 0
fi
#/help
cecho -green "* " -action "grep" " : grep \"$@\" " -file "$WORLD_FILE"
if [ ! "$NO_COLOR" ]; then
grep "$@" "$WORLD_FILE" --color=auto
else
grep "$@" "$WORLD_FILE"
fi
}
function _checkdep() {
#help
if [ "$1" = "help" ]; then
cecho -action "checkdep " ": for each pkg in " -file "$WORLD_FILE " "check if it depends on another pkg. if " -args "<arg> " "is " -args "e " "or " -args "equery " "this action use " -cmd "equery " "from " -cmd "gentoolkit " "otherwise it use " -cmd "q" " from " -cmd "portage-utils" ". " -cmd "q " "is used by default because it's faster (but maybe less reliable)."
return 0
fi
#/help
emaint
if [ "$1" = "equery" ] || [ "$1" = "e" ]; then
need "equery" "gentoolkit"
else
need "qdepends" "portage-utils"
fi
for pkg in $(cat $WORLD_FILE | sort); do
if [ "$1" = "equery" ] || [ "$1" = "e" ]; then
depends="$(equery depends "$pkg" | grep -v 'Searching' | grep '^\w\+')"
else
# FIXME : maybe not the perfect regexp
depends="$(qdepends --query $pkg --verbose --nocolor | grep -v '^'$pkg'*' | sed 's/^\([^ ]*\):.* \([^ ]*'`basename $pkg`'[^ ]*\).*/\1 (\2)/')"
fi
if [ "$depends" ]; then
cecho -file "$pkg" " :"
cecho "$depends"
fi
done
}
#-------------- TESTS -------------
# do not add test unless you really
# think that it'll be useful for some
# other action.
# please just add a little comment before
# the test.
#----------------------------------
#
# $WORLD_FILE must exists
if [ ! -f "$WORLD_FILE" ]; then
error "file not found : " -file "$WORLD_FILE"
fi
# creat the $SAVE_DIR if not present
if [ ! -e "$SAVE_DIR" ]; then
mkdir "$SAVE_DIR/backup" || error "Failed while creating " -dir "$SAVE_DIR"
fi
# actions auto-detection.
ACTIONS=$(grep '^function \+_\w\+ *() *{ *$' "$0" | sed -e 's/function \(.*\)() *{/\1/')
# ------------- MAIN -------------
# lauch the appropriate action.
# if no args action help is called.
#---------------------------------
#
# action caller method
eworld_action() {
for action in $ACTIONS; do
if [ "_$1" = "$action" ]; then
shift
$action "$@"
flag="ok"
fi
done
if [ "$flag" != "ok" ]; then
error -action "$1 " "is not a valid action, please run " -cmd "$0 help"
fi
}
if [ $# -lt 1 ]; then
eworld_action "help"
fi
case "$1" in
h|--help|-h) eworld_action "help" ;;
*) eworld_action "$@" ;;
esac
|
Comment aider ?
Simplement en utilisant le script. Vous pouvez proposer de nouvelles action (voir plus bas) facilement, faire des critiques conseils etc. Voici ma TODOlist pour ceux qui veulent m'aider :
1) tester eworld checkdep avec equery et qdepends et me dire les différences de temps et de output. Chez moi equery met beaucoup de temps (15-18 minutes) mais chez d'autres c'est plutôt dans les 3 minutes (un problème dans mon cache portage ???). qdepends lui est très rapide (30 secondes) mais moins "bavard" que equery qui me trouve plus de dépendances.
2) vérifier le script, particulièrement les deux expressions régulières (ligne 282 et 312). la regexp ligne 282 parse la sortie de qdepends pour qu'elle ressemble à celle d'equery. celle 312 cherche les actions possibles dans le script.
3) expliquer comment ajouter une nouvelle action. Docummenter les variables / fonctions outils à disposition.
Comment ajouter une action
TODO
EDIT
2007-01-24
- v0.2.1
- fix du commentaire pour l'ajout d'actions
- checkdep démarre /usr/sbin/emaint --check world avant de commencer, pour s'assurer que le fichier world est correctement formé.
- Comme plusieurs action (checkdep et update et peut-être encore de futurs actions) utilisent emaint, une nouvelle fonction outil à été ajoutée (emaint).
- Ajout de la variable $NO_COLOR. Il est possible maintenant de démarrer le script en exportant cette variable (ou en l'initialisant dans le code) pour éviter un affichage coloré. Si vous ajouter une action qui produit un affichage coloré SANS passer par la fonction outils cecho n'oubliez pas de prendre cette variable en compte (comme c'est le cas pour l'action grep). _________________ Macbook
Core2Duo @ 2.0GHz - 1Go RAM - HD 80Go - Intel GMA 945
Gentoo GNU/Linux
~amd64 - 2.6.24-gentoo-r2 - Fluxbox || (KDE && Compiz-Fusion) |
|
Back to top |
|
|
truc Advocate
Joined: 25 Jul 2005 Posts: 3199
|
Posted: Wed Jan 24, 2007 3:05 pm Post subject: |
|
|
sans vouloir discrediter ton travail, tu dis ne pas avoir trouver d'outil gerant ton ce fichier entre autre, as tu jeter un oeil à udept:
Code: | app-portage/udept
gentoo: 0.5.96.2 0.5.99.0.2.95 0.5.99.0.2.95-r1* {:0}
Homepage: http://catmur.co.uk/gentoo/udept
Description: A Portage analysis toolkit
License: ( GPL-2 )
Use flags: bash-completion
|
il a d'ailleurs tout un thread qui lui est consacré: Clean out your world file _________________ The End of the Internet!
Last edited by truc on Tue Feb 06, 2007 12:38 pm; edited 1 time in total |
|
Back to top |
|
|
kaworu Guru
Joined: 07 Dec 2005 Posts: 450
|
Posted: Tue Feb 06, 2007 12:26 pm Post subject: |
|
|
Salut !
en faite j'ai testé udept et visiblement il n'as pas les même objectif que mon petit script.
udept intègre des fonctionnalités pour portage de manière générale (des fonctions que l'on retrouve dans equery ou q), des algo complexes, une syntaxe peu lisible (ça c'est mon avis ).
Mon script est juste un petit outil qui permet de gagner du temps, sans algo compliqué (parce que d'autres plus capables que moi l'on déjà fait ). Il faut qu'il reste simple.
Si j'ose la comparaison, udept me fais penser a equery (actions complexes comme les calculs de dépendances inverses), et eworld me fais plus penser à eselect, un outil pratique, pas indispensable mais drôlement utile _________________ Macbook
Core2Duo @ 2.0GHz - 1Go RAM - HD 80Go - Intel GMA 945
Gentoo GNU/Linux
~amd64 - 2.6.24-gentoo-r2 - Fluxbox || (KDE && Compiz-Fusion) |
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|