[Bash] Problème avec une variable (résolu)

Applications, problèmes de configuration réseau
Répondre
@rché0
Daikyu
Messages : 90
Inscription : jeu. 09 sept. 2021, 20:57

[Bash] Problème avec une variable (résolu)

Message par @rché0 »

Bonjour,

j'ai fais un script en bash pour récupérer des blocklists et les convertir au format Unbound. Je souhaite lire le nombre de lignes du fichier crée. J'ai ça pour le moment (la variable et ce que je veux afficher):

Code : Tout sélectionner

nb_l=`wc -l $dir|awk '{print $1}'`
echo -e "\033[0;36;1m"`expr $nb_l - 1` adresses sont maintenant bloquées par Unbound.
Le problème est que si je supprime une blocklist et que je relance le script le nombre de lignes ne change pas. Il faut que je l’exécute à nouveau pour que ce soit bon.
Dernière modification par @rché0 le lun. 21 mars 2022, 17:26, modifié 2 fois.
Avatar de l’utilisateur
papajoke
Elfe
Messages : 773
Inscription : sam. 30 août 2014, 19:54

Re: [Bash] Problème variable dans un texte coloré

Message par papajoke »

bonjour

pas bien compris la première ligne, tu comptes le nombre de fichiers dans un répertoire ("$dir") ou des lignes dans un fichier ?
Si fichier, je ne connais pas ton format de fichier mais le code devrait-être plutôt proche du type:

Code : Tout sélectionner

nombre_exact=$(grep -Ev '^#|^$' "$mon_fichier_config" -c)
echo -e "\033[0;36;1m${nombre_exact} adressses sont bloquées"
NOTE: $( commande ) est la bonne syntaxe depuis de nombreuses années
@rché0 a écrit : dim. 20 mars 2022, 08:53 je relance le script le nombre de lignes ne change pas. Il faut que je l’exécute à nouveau pour que ce soit bon.
pas tout compris : tu relances ce script -> rien, puis re-relance encore une fois c'est ok ?
En tout cas, c'est normal de relancer (une fois) ce script pour qu'il affiche les nouvelles valeurs. "$nb_l" n'est valide (si code bon) qu'au moment où le script est lancé. Sinon il faut que ton script soit un service (peut-être utiliser un service inotify ?) tes 2 lignes ne donnent aucune info sur ton véritable problème...

En tout cas, que le texte soit coloré ou non, ne change rien :?

EDIT: changé "print" par "echo -e"
Dernière modification par papajoke le dim. 20 mars 2022, 16:15, modifié 1 fois.
Arch stable - Kde 5 / zsh - btrfs/mbr - Intel Core i3 - 6Go RAM - GeForce 405 video-nouveau
@rché0
Daikyu
Messages : 90
Inscription : jeu. 09 sept. 2021, 20:57

Re: [Bash] Problème variable dans un texte coloré

Message par @rché0 »

Bonjour,

C'est pour compter les lignes du fichier ($dir=/etc/unbound/blocklist).
Je suppose que tu veux dire "printf" au lieux de "print". J'avais un soucis avec echo qui m'affichait le texte sans la valeur de ma variable, c'est maintenant réglé, merci. Par contre, le problème est toujours là:

Le script compte trois listes.Dans le fichier j'ai disons 20 lignes. Si je commente pour n'avoir que deux listes et que je lance le script, j'ai encore 20 lignes. Il faut que je relance encore le script pour n'avoir que 11 lignes par exemple.

La variable que tu m'as fourni, c'est pour supprimer les commentaires et les lignes vides mais dans le fichier, je les ai déjà supprimé.

EDIT: j'ai tenté en changeant la variable nb_l par:

Code : Tout sélectionner

nb_l=$(grep -vE '^server' "$dir" -c)
Mais, c'est le même résultat qu'avec wc -l…
Avatar de l’utilisateur
papajoke
Elfe
Messages : 773
Inscription : sam. 30 août 2014, 19:54

Re: [Bash] Problème variable dans un texte coloré

Message par papajoke »

pas tout compris ... c'est donc ce même script qui génère le fichier /etc/unbound/blocklist, puis à la fin exécute tes 2 lignes ? Alors ton problème est sans doute bien avant ces 2 lignes ? à la génération ?
pour debug, faire un cat de ce fichier au moment de ces 2 lignes de code pour bien vérifier que son contenu est bien valide à tes attentes :wink:
c'est pour supprimer les commentaires et les lignes vides mais dans le fichier, je les ai déjà supprimé.
c'était un exemple générique puisque je n'ai aucune idée du format de ton fichier (sans un exemple), peut-être qu'un grep -E 'xxx=.*' -v est la bonne façon...
EDIT nb_l=$(grep -vE '^server' "$dir" -c) veut dire toute ligne qui ne commence pas par "server" ... j'ai un doute :?

-----
désolé pour le "print", je mélange les langages, c'est echo -e en bash
Arch stable - Kde 5 / zsh - btrfs/mbr - Intel Core i3 - 6Go RAM - GeForce 405 video-nouveau
@rché0
Daikyu
Messages : 90
Inscription : jeu. 09 sept. 2021, 20:57

Re: [Bash] Problème variable dans un texte coloré

Message par @rché0 »

printf marche bien, avec echo -e, j'avais le texte complet sans la valeur de la variable.
Voici mon script, ça devrait te parler plus :)

Code : Tout sélectionner

#!/usr/bin/env sh
# Convertir différants fichiers hosts pour Unbound.

dir='/etc/unbound/blocklist'
nb_l=$(grep -vE '^server' "$dir" -c)

alias no_g='curl https://raw.githubusercontent.com/nickspaargaren/no-google/master/google-domains'
alias no_t='curl https://raw.githubusercontent.com/notracking/hosts-blocklists/master/hostnames.txt'
alias oisd='curl https://hosts.oisd.nl/basic'

	no_g >  /tmp/host
printf "\033[0;33;4mFichier no-google téléchargé.\n\033[0m"
	no_t >> /tmp/host
printf "\033[0;33;4mFichier no-tracking téléchargé.\n\033[0m"
	oisd >> /tmp/host
printf "\033[0;33;4mFichier oisd-basic téléchargé.\n\033[0m"
echo
printf "\033[3;31;1mContinuer pour convertir le fichier ? [O/n] : \033[0m"; read var
		if [[ $var =~ ^[nN] ]]; then
printf "\033[3;31;1mLe fichier n'a pas été converti.\n\033[0m"
	exit 1
		else

grep -E '^([0127]+.0.0.[01]|^::[ 1])' /tmp/host|sed '/[[:upper:]]/d'|tee /tmp/host2 1>/dev/null
printf 'server:\n'|sudo tee $dir 1>/dev/null
awk '{print "local-zone: \""$2"\" always_refuse"}' /tmp/host2|sort -g|uniq|sudo tee -a $dir 1>/dev/null
echo
printf "\033[0;36;1mUn petit extrait du fichier :\n\033[0m"
head -5 $dir; printf "\033[0;36;1m${nb_l} adresses sont maintenant bloquées par Unbound.\n\n"
printf "\033[3;32;1mLa convertion a été un succès. À bientôt.\n\033[0m"
	exit 0
		fi
EDIT : echo -e marche, j'avais pas mis ${} comme variable mais ``. Ça doit venir de là, sinon je n'ai pas d'explications.
Avatar de l’utilisateur
papajoke
Elfe
Messages : 773
Inscription : sam. 30 août 2014, 19:54

Re: [Bash] Problème variable dans un texte coloré

Message par papajoke »

pas cherché à comprendre si le script fonctionne bien (les "sudo tee xxx /dev/nul" bien bizarre, comme créer des alias; mais pas le sujet ici)
MAIS
oui, ta valeur "adresses sont maintenant bloquées" est logiquement fausse ! tu lis le fichier "$dir" AVANT de le générer : donc tu affiches la valeur AVANT génération et non la courante (APRES génération).

---
je ne connais pas unbound, mais peut-être qu'il faut relancer le service à la fin du script pour qu'il recharge les nouveaux dns ?
Arch stable - Kde 5 / zsh - btrfs/mbr - Intel Core i3 - 6Go RAM - GeForce 405 video-nouveau
@rché0
Daikyu
Messages : 90
Inscription : jeu. 09 sept. 2021, 20:57

Re: [Bash] Problème variable dans un texte coloré

Message par @rché0 »

Bonjour,
sudo tee xxx /dev/nul" bien bizarre
Je te laisse lancer le script sans les /dev/null, et tu devrais comprendre le pourquoi du pourquoi :D

Pour la suite de ta phrase, tu dois avoir raison mais je ne la comprend pas. Ce qui génère le fichier final, c'est la ligne awk… et elle est située en amont du echo -e…adresses sont maintenant bloquées. Une explication plus claire est la bienvenue.
peut-être qu'il faut relancer le service à la fin du script
Oui, tu as entièrement raison mais je lance ce script avant de me coucher et j’éteins le pc ensuite. Donc ça ne m'est pas utile, j'ai quand même rajouté cette suggestion par soucis du détail.

PS : je ne sais pas toi mais je ne reçois que le premier mail de notification d'une réponse mais pas les suivants.
Avatar de l’utilisateur
papajoke
Elfe
Messages : 773
Inscription : sam. 30 août 2014, 19:54

Re: [Bash] Problème variable dans un texte coloré

Message par papajoke »

@rché0 a écrit : lun. 21 mars 2022, 06:26 Je te laisse lancer le script sans les /dev/null, et tu devrais comprendre le pourquoi du pourquoi :D
La question est plutôt pourquoi utiliser ces sudo tee, c'est un alourdissement du code bien inutile:
- tu peux lancer ton script directement via sudo, ou
- tu peux générer ton fichier de sortie dans /tmp puis à la fin faire un simple sudo cp /tmp/unbound /etc/unbound
Pour la suite de ta phrase, tu dois avoir raison mais je ne la comprend pas. Ce qui génère le fichier final, c'est la ligne awk… et elle est située en amont du echo -e…adresses sont maintenant bloquées. Une explication plus claire est la bienvenue.
oops, ton niveau en bash est très très faible, Ok, c'est donc une copie d'un script existant…

Code : Tout sélectionner

nb_l=$(grep -vE '^server' "$dir" -c)
c'est ligne 5, ici ce n'est pas un alias ! tu exécutes bien cette commande (lire le nombre de lignes dans le fichier de config).

Code : Tout sélectionner

printf "\033[0;36;1m${nb_l} adresses sont maintenant bloquées par Unbound.\n\n"
A la toute fin du script ! Ici, tu ne fais que afficher la variable que tu as calculé ligne 5 (donc bien avant la génération du fichier)

Il te suffit donc de juste déplacer ta ligne nb_l=$(...) :D
Arch stable - Kde 5 / zsh - btrfs/mbr - Intel Core i3 - 6Go RAM - GeForce 405 video-nouveau
@rché0
Daikyu
Messages : 90
Inscription : jeu. 09 sept. 2021, 20:57

Re: [Bash] Problème avec une variable

Message par @rché0 »

c'est donc une copie d'un script existant…
Non, non… c'est bien un script original. Mais pour mon niveau en bash, tu n'as pas tord :copain:

J'ai pensé que la variable n'était exécuté qu'a partir du $. Je comprend maintenant.
C'est résolu.
Avatar de l’utilisateur
papajoke
Elfe
Messages : 773
Inscription : sam. 30 août 2014, 19:54

Re: [Bash] Problème avec une variable

Message par papajoke »

@rché0 a écrit : lun. 21 mars 2022, 17:25 J'ai pensé que la variable n'était exécuté qu'a partir du $. Je comprend maintenant.
C'est la base de tout langage de programmation :
1) on assigne une valeur dans une variable nommée

Code : Tout sélectionner

age_du_capitaine=18
fichier="/tmp"
2) après, on a accès à la valeur de cette variable qui a été faite lors de l'assignation, on ne fait donc que lire cette valeur déjà en mémoire

Code : Tout sélectionner

echo $age_du_capitaine $fichier
une variable pointe vers des données brutes dans une zone mémoire, donc on n'exécute rien
une fonction pointe vers du code dans une zone mémoire, donc ici, on exécute du code



---------------------


Non, non… c'est bien un script original. Mais pour mon niveau en bash, tu n'as pas tord
ok, puisque c'est de toi, donc voici un (autre) squelette sans tes alias ni "sudo tee" (script non posix, mais ok pour bash archlinux) et on compte les "local-zone"

Code : Tout sélectionner

color_g="\033[0;36;1m"
color_none="\033[0m"

downloadfile="/tmp/download" # toutes les datas des url, formatées à la suite
tmpfile="/tmp/unbound"    # fichier config pour unbound à recopier dans /etc/

function formater() {
    # formate le retour de curl au format unbound, a utiliser dans un pipe
    cat | awk '/^([0127]+.0.0.[01]|^::[ 1])/ {print "local-zone: "$2" always_refuse"}'
}

echo "" > "$downloadfile"
declare -i total=0
declare -i nombre=0
for url in "raw.githubusercontent.com/nickspaargaren/no-google/master/google-domains" "raw.githubusercontent.com/notracking/hosts-blocklists/master/hostnames.txt" "hosts.oisd.nl/basic"; do
    echo "download ${url} ..."
    ladate=$(curl -sI "https://${url}" | grep '^last-modified')
    curl -sL "https://${url}" | formater >> "$downloadfile" || exit 4
    ((nombre=$(grep '^local-zone' "$downloadfile" -c)))
    printf "OK pour: ${color_g}${url%%/*}${color_none}\t${ladate}\t${color_g}%i${color_none} adresses\n" $((nombre-total))
    ((total=nombre))
done

echo -n "server:" > "$tmpfile"
cat "$downloadfile"|sort -g|uniq >> "$tmpfile"
nombre=$(grep '^local-zone' "$tmpfile" -c)
echo -e "\n${color_g}${nombre}${color_none} adresses peuvent être bloquées par Unbound.\n\n"

read -n1 -p "Sauvegarder la config [o/N] ? "
if [[ ${REPLY,,} == "o" ]]; then
    echo
    # sudo cp "$tmpfile" "/etc/unbound/blocklist"  # A DECOMMENTER uniquement si script est valide...
    less "/tmp/unbound"
    ls -oh "/tmp/unbound"
fi

rm "$downloadfile" "$tmpfile"
Arch stable - Kde 5 / zsh - btrfs/mbr - Intel Core i3 - 6Go RAM - GeForce 405 video-nouveau
@rché0
Daikyu
Messages : 90
Inscription : jeu. 09 sept. 2021, 20:57

Re: [Bash] Problème avec une variable (résolu)

Message par @rché0 »

Bonjour,

Ne m'en veux pas mais j'ai passé tellement de temps sur ce script que je vais le garder. Je ne comprend pas l'intégralité du tien.

J'ai eu l'idée de ce script grâce à la documentation sur Unbound qui donne la commande awk '{print "local-zone: \""$2"\" always_refuse"}'. J'ai pas mal galéré pour le regex grep -E '^([0127]+.0.0.[01]|^::[ 1])'. J'ai fais pleins de tests jusqu’à trouver le bon.
J'ai repris quelques idées que tu m'as suggéré, ajouté une liste supplémentaire ainsi qu'une condition qui indique que le script doit être lancé en tant que root car il y avait un bug si je validais la question puis si je quittais le script avec Ctrl+C.

Rien que ça, j'ai mis du temps car j'ai dû tenter plusieurs approches ($UID, $EUID ou $(id -u) n'ont pas marché). J'ai trouvé avec sudo true. C'est peut-être pas très élégant mais ça fonctionne, pour rm j'ai dû le mettre trois fois car je n'ai pas trouvé d'autres solutions :D

Tu vas pas aimer car j'ai gardé les alias et j'ai rajouté pleins de dir… Voici le script dernière version :

Code : Tout sélectionner

#!/usr/bin/env sh
# Convertir différents fichiers hosts pour Unbound.

dir1='/tmp/hosts'
dir2='/tmp/hosts2'
dir3='/tmp/unbound'
dir4='/etc/unbound/blocklist'
url='https://raw.githubusercontent.com/'

alias a_me='curl ${url}iam-py-test/my_filters_001/main/Alternative%20list%20formats/antimalware_pure_hosts.txt'
alias no_g='curl ${url}nickspaargaren/no-google/master/google-domains'
alias no_t='curl ${url}notracking/hosts-blocklists/master/hostnames.txt'
alias oisd='curl https://hosts.oisd.nl/basic'

	a_me >  $dir1
printf "\033[0;33;4mFichier 'antimalware' téléchargé\n\033[0m"
	no_g >> $dir1
printf "\033[0;33;4mFichier 'no-google' téléchargé\n\033[0m"
	no_t >> $dir1
printf "\033[0;33;4mFichier 'no-tracking' téléchargé\n\033[0m"
	oisd >> $dir1
printf "\033[0;33;4mFichier 'oisd-basic' téléchargé\n\033[0m"
echo
grep -E '^([0127]+.0.0.[01]|^::.)' $dir1|sed '/[[:upper:]]/d'|tee $dir2 1>/dev/null
printf 'server:\n'|tee $dir3 1>/dev/null
awk '{print "local-zone: \""$2"\" always_refuse"}' $dir2|sort -g|uniq|tee -a $dir3 1>/dev/null
nb_ad1=$(grep -E '^local-zone' "$dir3" -c)
nb_ad2=$(grep -E '^local-zone' "$dir4" -c)
printf "\033[0;36;1m** ${nb_ad1} adresses peuvent être bloquées par Unbound (${nb_ad2} actuellement) **\n\033[0m"
printf "\033[3;31;1m:: Sauvegarder la liste de blocage créée vers '${dir4}' ? [O/n] : \033[0m"; read var

		     if [[ $var =~ ^[nN] ]]; then
rm $dir1 $dir2 $dir3
printf "\033[3;31;3m=> La conversion a été abandonnée.\n\033[0m"
	exit 1
		     elif [[ ! $var =~ ^[nN] ]]; then
		     if sudo true; then
echo
sudo cp $dir3 $dir4; sudo systemctl restart unbound.service
printf "\033[0;36;3mUn petit extrait du fichier généré :\n\033[0m"
head -5 $dir4; rm $dir1 $dir2 $dir3
printf "\033[3;32;3m=> La conversion et la sauvegarde ont été un succès. À bientôt.\n\033[0m"
	exit 0
		     else
rm $dir1 $dir2 $dir3
printf "\033[3;31;1m=> Ce script doit être lancer en tant que root.\n\033[0m"
	exit 2
		     fi
	fi

Ce fichier n'était pas prévu d'être sur le web mais vous pouvez l'utiliser si vous le souhaitez.
Attention, la liste 'no-google' va bloquer l'intégralité des domaines de :google: . Si vous avez une utilité à utiliser leurs services, il faudra la supprimer ou en rajouter une autre.
Pour les listes à rajouter, il faudra veiller à ce que celle-ci ne contiennent pas les adresses localhost, sinon il y aura comme un problème :D

Merci bien papajoke.
Répondre