Forum Astuces.divers Un gestionnaire de téléchargement en shell

Posté par .
Tags : aucun
4
21
nov.
2010
L’idée est de pouvoir lancer un téléchargement en tâche de fond qui enregistre le fichier dans ~/data. On peut récupérer l’avancement des téléchargements en mode texte dans le fichier ~/.dm/log pour affichage dans Conky typiquement.

L’utilisation est très simple : dm 'url'. Un exemple :% dm 'http://ftp.halifax.rwth-aachen.de/blender/movies/sintel-2048(...)
# attendre un peu plus de 10 secondes
% cat ~/.dm/log
56% 10m48s sintel-2048-stereo.ogv ftp.halifax.rwth-aachen.de

% dm 'http://mirror.bigbuckbunny.de/peach/bigbuckbunny_movies/big_(...)
# attendre au moins 10 secondes
% cat ~/.dm/log
1% 14m38s big_buck_bunny_480p_h264.mov mirrorblender.top-ix.org
83% 4m10s sintel-2048-stereo.ogv ftp.halifax.rwth-aachen.de


Pour que conky l’utilise il suffit d’ajouter « ${tail /home/nicolas/.dm/log 20 10} », par exemple, dans la section TEXT.

En interne il y aura de multiples « clients » qui vont lancer wget et envoyer la sortie dans le fichier qui va bien. Un « serveur » (lancé et arrêté automatiquement) va se contenter de lire les fichiers des clients, et mettre en forme l’avancement dans le log.

#!/bin/sh

# Un gestionnaire de téléchargement

# Répertoire d’enregistrement des téléchargements
data=$HOME/data
# Répertoire du gestionnaire
dir=$HOME/.dm

# Des serveurs filtrent avec le user-agent
useragent='Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.15) Gecko/20101028 Conkeror/0.9.2 (Debian-0.9.2+git100804-1)'

if [ ! -d $dir ]
then
  mkdir $dir
fi
if [ ! -d $data ]
then
  mkdir $data
fi

lock=$dir/lock
if [ "$1" = "server" ]
then
  trap "rm -f $lock; exit" INT TERM EXIT
  touch $lock
  log=$dir/log
  run=1
  while [ $run -eq 1 ]
  do
    sleep 10
    echo -n ''>$log
    for tmp in $dir/*.tmp
    do
      if [ "$tmp" = "$dir/*.tmp" ]
      then
        run=0
      else
        run=1
        echo -n \
          "$(tail -n2 "$tmp"|head -n1|awk '{printf ("%3s %6s ", $7, $9)}')" \
          >>$log
        echo "$(basename "$tmp" .tmp)">>$log
      fi
    done
    echo ' '>>$log
  done
  rm $lock
  trap - INT TERM EXIT
else
  if [ "$1" = "client" ]
  then
    file=$(echo "$2"|awk --field-separator / '{print $NF" "$3}')
    log="$dir/$file.tmp"
    wget --user-agent "$useragent" --continue -P$data "$2" 2>$log &
    wait $!
    sleep 15
    rm "$log"
  else
    if [ ! -e $lock ]
    then
      $0 server &
    fi
    $0 client "$1" &
  fi
fi

Bien sûr il y a tout un tas de possibilité d’amélioration au script ! Par exemple la possibilité de pouvoir arrêter un téléchargement par la simple suppression de son fichier associé dans ~/.dm serait sympathique.
  • # plus tout ce que je n'ai pas vu...

    Posté par . Évalué à 4.

    Bonjour,

    if [ ! -d $dir ]
    then
    mkdir $dir
    fi
    peut être remplacé par [ -d $dir ] || mkdir $dirainsi que toutes les autres conditions simples

    if [ "$tmp" = "$dir/*.tmp" ] ça ne marchera jamais : les * ne sont pas développés entre " " et entre [ ], à moins qu'il puisse exister un fichier *.tmp !

    echo $(basenamenon
    :basename ... >> fichiervoire, utiliser le développement des paramètres
    • [^] # Re: plus tout ce que je n'ai pas vu...

      Posté par . Évalué à 1.

      Quelle horreur :)

      tail -n2 "$tmp"|head -n1|awk '{printf ("%3s %6s ", $7, $9)}'

      Si j'ai bien compris et que tu veux récuperer la 3eme ligne ...
      awk ' ($NR==3) {printf ("%3s %6s ", $7, $9)}'

      awk --field-separator / '{print $NF" "$3}'

      La version porrtable doit être awk -F"/" '{print $NF" "$3}"

      Et si le but est de récupérer le nom de fichier .... man basename

      # basename /toto/titi/tutu.tmp
      tutu.tmp
      • [^] # Re: plus tout ce que je n'ai pas vu...

        Posté par . Évalué à 2.

        Oups .... une coquille :
        awk ' ($NR==3) {printf ("%3s %6s ", $7, $9)}'

        C'est plutot sans le "$" devant NR

        awk ' (NR==3) {printf ("%3s %6s ", $7, $9)}'

        Déformation Perlienne.
      • [^] # Re: plus tout ce que je n'ai pas vu...

        Posté par . Évalué à 2.

        Je veux récupérer l’avant dernière ligne. Peut-être y’a-t-il moyen de le faire avec awk seul ? Je connais assez mal son langage, du coup je fais usage immodéré des sed, tail et head entubés. Pourquoi ce serait mal ?

        À vrai dire je me suis contenté d’avoir un script fonctionnel, toutefois j’utilise dash, ce qui devrait déjà le rendre relativement portable, c’est sûr qu’il y aura toujours les gnu-keries dans awk&co que j’ai tendance à utiliser sans faire attention.
        • [^] # Re: plus tout ce que je n'ai pas vu...

          Posté par . Évalué à 0.

          Je veux récupérer l’avant dernière ligne. Peut-être y’a-t-il moyen de le faire avec awk seul ?

          Peut-être :) Je regarde, j'ai peut-être ça qelque part.

          Je connais assez mal son langage, du coup je fais usage immodéré des sed, tail et head entubés. Pourquoi ce serait mal ?
          Parce que sur un nombre important de lignes à traiter, tu gagnes en rapidité d'exécution. Pour ma part quand j'utilise awk, j'essaie de tout faire avec dans la mesure du possible (sauf si c'est un truc jetable que je dois utiliser une fois).
    • [^] # Re: plus tout ce que je n'ai pas vu...

      Posté par . Évalué à 1.

      Je prends note pour la version raccourcie des conditions simples, je n’y pense pas en shell.

      Pour le '*' non developpé c’est exactement le but ! Lorsqu’il n’existe aucun fichier dans ~/.dm/*.tmp, ma boucle « for tmp in $dir/*.tmp » fait une itération dans laquelle $tmp prend la valeur $dir/'*'.tmp ('*' est là pour signaler que le * n’est pas développé) je teste donc la valeur de cette variable, et arrête le « serveur » dans ce cas précis.

      Pour le « echo $(basename… », oups! Effectivement ça peut se simplifier, disons pour ma défense qu’un script shell ça bouge pas mal et que j’ai sûrement été amené à simplifier cette ligne en oubliant le echo superflu.

      « plus tout ce que je n'ai pas vu... »

      Mais non, mais non… 0:)

      Ceci dit, merci, le but inavoué était aussi de me faire reprendre un peu le code pour voir ce qui était améliorable. :)

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.