URL: https://linuxfr.org/forums/programmation-shell/posts/astuce-wget-trop-lent-axel-prend-le-relai Title: astuce : wget trop lent, axel prend le relai Authors: steph1978 Date: 2016年03月18日T14:26:13+01:00 License: CC By-SA Tags: axel, wget et hack Score: 10 # Le problème Un fichier archive à télécharger, premier réflexe : ``` wget http://url/vers/mon/fichier ``` Et au bout que quelques minutes se dire : "Zut, il est gros ce fichier et c'est lent, ça ne sature même pas mon lien ADSL..." Second réflexe : j'aurai dû utiliser [axel](http://axel.alioth.debian.org/). Dilemme, je kill le wget en cours et relance avec axel ? Dommage pour tous ces octets qui ont déjà fait un si long voyages. Si je pouvais dire à axel que wget a déjà fait un gros bout du travail, il pourrait prendre la suite au lieu de tout recommencer. # L'idée Axel dump régulièrement un fichier d'état pour pouvoir reprendre le téléchargement si il est interrompu. Est ce que je ne peux pas construire ce fichier à partir de ce qu'a déjà téléchargé par wget ? réponse : si, avec le script disponible [ici](https://framabin.org/?4503b528f5805f2e#p4KL4MoKZRpzrYjYwzQH6e1TO6LePRavvRn8gq0494c=). Le script n'utilise que bash, coreutils et axel. Et implicitement dépend du format interne du fichier d'état de axel qui n'est pas dans un format standard mais reste très simple. # Comment ? Pour rappel, axel découpe le travail en morceaux de taille équivalente et lance une connexion HTTP par morceau en utilisant l'[option "range" de HTTP](https://tools.ietf.org/html/draft-ietf-http-range-retrieval-00). Le format du fichier d'état est le suivant: ``` nombre de connexions simultanées (int) octets déjà téléchargés (long) où j'en suis sur la 1ère connexion (long) où j'en suis sur la 2ème connexion (long) ... où j'en suis sur la Nème connexion (long) ``` Il ne manque qu'une donnée de départ : la taille totale du fichier à télécharger. Le script lance axel une première fois pour récupérer cette information et le kill dans la foulée. Cela aurai pu être n'importe quel client http mais autant limiter les dépendances. wget a fait tout le travail pour les premiers morceaux, partiellement pour un d'entre eux et pas du tout pour les derniers. Si on reprend le fichier d'état, on a donc: ``` nombre de connexions (int) => 4 (c'est un choix raisonnable) octets déjà téléchargés (long) => nombre d'octets déjà téléchargés par wget = taille du fichier partiel où j'en suis sur la 1ère connexion (long) => fini 1/4 taille totale où j'en suis sur la 2ème connexion (long) => partiel = taille du fichier partiel, compris entre 1/4 et 2/4 où j'en suis sur la 3ème connexion (long) => vide donc 2/4 où j'en suis sur la 4ème connexion (long) => vide donc 3/4 ``` Bien sûr, il y a des variations et il faut faire attention aux cas limites mais l'idée est là. Pour se tromper le moins possible, le script reprend l'algorithme itératif de découpage dans code source d'axel (révision 94 au moment de l'écriture) Le script embarque une petite optimisation : si on a déjà une bonne partie du fichier (>2/5) autant lancer plus de connexions, sachant que les premières n'ont rien à faire, on va retomber sur le nombre de connexions simultanées voulues. # Conclusion Finalement, cela se passe comme cela: ``` wget http://url/vers/mon/fichier CTRL+C /path/to/axel_from_wget.sh fichier http://url/vers/mon/fichier use more connections Initializing download: http://url/vers/mon/fichier File size: 41428290 bytes Opening output file fichier State file found: 22036480 bytes downloaded, 19391810 to go. Starting download Connection 4 finished [ 63%] [................................5 6 7 ] [ 1.3MB/s] [00:10] ``` Le plus compliqué aura été : 1. d'écrire des données brutes en bash. 1. de parvenir à la réflexion qu'il était plus efficace d'utiliser le code source du logiciel plutôt que d'essayer de deviner l’algorithme à partir de données brutes. N'est ce pas tout l'intérêt d'utiliser un produit open source !