Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 20/06/2013, à 20:06

Zolotaya

[Script] Variable partagée entre plusieurs scripts

Bonjour à tous,

J'ai actuellement un petit problème de scripting et je cherche quelqu'un qui aurait une idée pour le résoudre.
La situation est la suivante :

J'ai fait un NAS maison qui tourne actuellement 7/7, 24/24. Seule problème : Ma facture d’électricité a explosé ...
Je souhaite donc éteindre mon NAS quand je ne l'utilise pas.
1ere solution : se connecter en ssh puis faire un "halt" --> pas pratique
2eme solution : un cron avec un halt tous les jours à 2h --> pas pratique non plus
3eme solution : un script maison qui détecte tout seul la consommation de la bande-passante et si il fait rien depuis x temps, il s'éteint tout seul.


J'ai donc commencé à écrire le bout le code à la fin de ce poste
L'idée est la suivante :
à l'aide de vnstat, je calcul le trafic réseau toutes les 5 secondes.
Je met dans un tableau le total de Kbits utilisé pendant ces 5 dernières secondes.
De cette façon, je peux retrouver exactement quel a été le trafic il y a 3 heure pour une durée déterminé genre 5 minutes / 30 minutes, la dernière heure, les 15 dernières secondes ...
Je peux donc faire facilement une règle qui dit :

Si le NAS a un trafic inférieur à 10Mbits la dernière heure et 1Mbits la dernière minutes et 10kbits les 10 dernières secondes alors il s’arrête

Le truc c'est que j'aurais voulu déporté cette règle la dans un autre script qui serait appelé par un crontab (genre toutes les 15 minutes)
Mon soucis c'est qu'en faisant ça, je ne peux pas récupérer la valeur de mes variables qui sont mises à jour dans le script ci-dessous. Si quelqu'un a une idée, je suis preneur.

#---- Functions ----#
usage(){
	cat << EOF
usage: $0 options

This script save the network usage for a specific delay time.

OPTIONS:
   -h      Show this help message
   -i      Define a specific interface (ex : eth0).
   -d      Delay of recording network usage history in minutes. Default 24 hours
EOF

exit 1
}

#---- Script ----#
declare -a RECV_HISTORY
declare -a SEND_HISTORY
export SEND_HISTORY
export RECV_HISTORY
export HISTORY_SIZE
export HISTORY_START
export HISTORY_END
DELAY=1440

#-- Script start here
while getopts :i:d:h option
do
   case "${option}"
   in
      i) IFACE=${OPTARG};;
      d) DELAY=${OPTARG};;
      h) HELP=1;;
      \?) echo "Invalid option: -$OPTARG" >&2
      HELP=1;;
      :) echo "Invalid option: -$OPTARG ; require an argument" >&2
      HELP=1;;
   esac
done

vnstat > /dev/null
RET=`echo $?`
if [[ ${RET} -ne 0 ]] ; then
   echo "The command vnstat is required to launch this script" >&2
   exit 1
fi

if [ -n "$HELP" ] ; then
   usage
fi
# Set specific interface
if [ -n "$IFACE" ] ; then
   IFACE=" -i ${IFACE}"
fi

HISTORY_SIZE=`echo $DELAY \* 60 / 5 | bc`
HISTORY_START=0
HISTORY_END=0

while true
do 
   NETWORK_USAGE=`vnstat ${IFACE} -tr`

   # retreive bandwith used the last 5th seconds
   RECV_DATA=`echo ${NETWORK_USAGE} | sed -e 's/.*rx \([[:digit:]][[:digit:]]*\.[[:digit:]][[:digit:]]\) kbit.*/\1/' -e 's/.*rx \([[:digit:]][[:digit:]]*\.[[:digit:]][[:digit:]]\) Mbit.*/\1 \* 1024/'`
   SEND_DATA=`echo ${NETWORK_USAGE} | sed -e 's/.*tx \([[:digit:]][[:digit:]]*\.[[:digit:]][[:digit:]]\) kbit.*/\1/' -e 's/.*tx \([[:digit:]][[:digit:]]*\.[[:digit:]][[:digit:]]\) Mbit.*/\1 \* 1024/'`

   # Compute using data
   RECV_DATA=`echo $RECV_DATA \* 5 | bc `
   SEND_DATA=`echo $SEND_DATA \* 5 | bc `

   echo "-----"
   echo "received data : ${RECV_DATA}"
   echo "sended data : ${SEND_DATA}"

   # Adding at the end of the array
   SEND_HISTORY[${HISTORY_END}]=${SEND_DATA}
   RECV_HISTORY[${HISTORY_END}]=${RECV_DATA}
   
   # Free memory over history size
   if [[ ${#SEND_HISTORY[*]} -gt ${HISTORY_SIZE} ]] ; then
      unset RECV_HISTORY[${HISTORY_START}]
      unset SEND_HISTORY[${HISTORY_START}]
      HISTORY_START=`expr ${HISTORY_START} + 1`
   fi

   HISTORY_END=`expr ${HISTORY_END} + 1`
done

Je reste à votre disposition si vous avez des questions
Merci par avance pour vos réponses
Zolotaya.

Hors ligne

#2 Le 20/06/2013, à 20:20

amj

Re : [Script] Variable partagée entre plusieurs scripts

Salut
je pense que c'est ceci que tu cherche http://fr.wikibooks.org/wiki/Programmat … ironnement

donc

export VAR

Est-ce qu'un raspberry pi (3W) ne conviendrais pas? (ça dépend de la quantité de donné à stoker sans doute.)

quand ça viens de la doc c'est encore mieux smile

man bash a écrit :

       export [-fn] [name[=word]] ...
       export -p
              The supplied names are marked for automatic export to the  envi‐
              ronment  of subsequently executed commands.  If the -f option is
              given, the names refer to functions.  If no names are given,  or
              if  the  -p  option  is  supplied,  a list of all names that are
              exported in this shell is printed.  The  -n  option  causes  the
              export  property  to  be  removed from each name.  If a variable
              name is followed by =word, the value of the variable is  set  to
              word.   export  returns  an  exit  status of 0 unless an invalid
              option is encountered, one of the names is  not  a  valid  shell
              variable name, or -f is supplied with a name that is not a func‐
              tion.

(export -p reviens plus ou moins au même que env)

Dernière modification par amj (Le 20/06/2013, à 20:37)


Vive le logiciel libre !! Articles aléatoires sur Wikipédia sur les logiciels libre, sur linux.

@amj@mastodon.xyz

Hors ligne

#3 Le 20/06/2013, à 21:35

Zakhar

Re : [Script] Variable partagée entre plusieurs scripts

Salut Zolotaya,

eh oui, la consommation électrique... C'est pour ça que les vendeurs de NAS existent et font attention à ce genre de chose.

Mon Synology consomme environ 30W avec ses 4 disques en marche, et presque rien en hibernation. Or, le calcul financier est vite fait, j'arrondis de la façon suivante :

1W  = 1€ / an

(en fait c'est légèrement plus, mais ça donne une idée simple).

Pour ton "partage de variable", c'est tout simplement impossible comme tu l'entends... et heureusement que c'est impossible !

Tu vas comprendre, c'est assez simple en fait : ton shell qui suit le trafic réseau, et le shell que sera lancé dans le cron sont deux process totalement indépendants. Il ne peuvent donc absolument pas partager des "variables" si tu entends par là une zone mémoire où est stockée une valeur.

L'export cité ci-dessus ne marchera pas. L'export fonctionne quand tu es par exemple dans ta console, tu lances un script qui veut 'setter' une variable, mais tu veux que cette variable persiste après la fin du script en cours parce que tu en as besoin dans les scripts suivants.
Si tu te contentes de mettre une valeur dans la variable, la variable et sa valeur seront perdues quand le script en cours dans ta console se termine.
Au contraire, si le script en cours fait un export, lorsqu'il se termine, le "parent" (ici la console) voit encore la variable.
Mais l'export ne fonctionne qu'avec ton parent, et pas avec deux scripts qui n'ont aucun rapport et ne sont pas lancés par le même "parent".

Pour faire ce "partage", il faut que tu passes pas un élément commun entre ces deux process totalement indépendants.
L'idée la plus simple est alors de passer par un fichier.
Si tu veux éviter les accès disques, tu peux mettre le fichier sur /dev/shm, ou tout répertoire monté en tmpfs.

Le shell qui calcule l'activité écrit un fichier.
Le cron lit le fichier.

Pour que ce soit simple, le 1er shell peut écrire ça sous forme de morceau de code directement exploitable par le second, par exemple :

last5min=12345
last1h=147859
# etc....

Ainsi le cron peut simplement 'sourcer' ce fichier pour récupérer les variables.

Ce n'est qu'une façon de faire. Elle a le mérite d'être simple... mais n'est pas exempte de problèmes. Par exemple un 'attaquant' peut remplir ton fichier avec des valeurs pour provoquer l'arrêt de ton PC (denial of service)... Parade : si tes deux scripts sont lancés en root, bien gérer les droits du fichier d'échange. Ainsi l'attaquant devra déjà avoir les droits roots... et s'il les a déjà, il peut de toute façon faire ce qui lui chante !
Autre exemple, se protéger du cas (improbable... mais l'improbable finit toujours par arriver !) où celui qui lit essaye de le faire en même temps que celui qui écrit. Tu peux utiliser flock (file lock) pour ça. man flock te donnera toutes les infos.


Après tu peux utiliser des solutions plus "complexes" et architecturées. Si par exemple tu as un serveur PhP ou Java, tu peux toujours faire un "WebService" (simplifié) avec une primitive pour 'setter' tes variables, et une pour les 'getter'.

Dernière modification par Zakhar (Le 20/06/2013, à 21:43)


"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne

#4 Le 20/06/2013, à 22:18

Zolotaya

Re : [Script] Variable partagée entre plusieurs scripts

Bonsoir,

@amj J'ai déjà essayé avec export et ça ne fonctionne pas. Tu peux essayer en faisant comme ça :

# declare une variable d'environnement
export TEST=test1
# affiche la variable
echo $TEST
# ouverture d'un sous-bash
bash
echo $TEST
# Modification de la variable d'env
TEST=test2
echo $TEST
# affiche test2
exit
# affichage de la variable d'environnement -> test1
echo $TEST

Les variables sont récupérés dans les sous-bachs mais leur portée (en cas de modification) reste dans le bach dans lesquels elles sont modifiés. Dans le cas de mon script, les modifications restes en interne.

@Zakhar
Merci pour cette réponse, c'est intéressant ce que tu dis.
Pour les synalogy je suis OK, mais le faire sois meme permet d'apprendre plus et de pouvoir le faire évoluer comme tu veux. Je peux sans soucis le transformer en pc d'appoint en installant en environnement graphique... Je pense qu'il y a du plus et du moins dans chaque solution

L'idée de l'affichage sur tmpfs ou autre est pas mal mais cela enlève beaucoup de possibilité au script. En gros, tout ce que je peux faire vnstat le fait déjà.
L'idée du script est le suivant : Si on considère le tableau avec m=la minute courante m + 1 la minute précédente ...
[m=10][m+1=0][m+2=3][m+4=50][m+5=100]...

Je peux donc calculer la consommation entre la minute 3 et 5, les 5 dernières minutes... En gros je peux choisir un intervalle de temps pendant laquelle je peux calculer la consommation et pas uniquement les n dernières minutes.

L'idée était de lancer le script un peu comme un daemon et pouvoir l’interroger avec une date de début de recherche et une date de fin (par exemple : "usage d 3 2"  me renverrais la bande passante en download entre depuis il y a 3 minutes pour une durée de 2 minutes). Cette appel se ferait depuis un script qui serait appelé par le cron.

Je vais continuer à chercher un peu

Hors ligne

#5 Le 20/06/2013, à 22:39

pingouinux

Re : [Script] Variable partagée entre plusieurs scripts

Bonsoir,

Zakhar   #3 a écrit :

Au contraire, si le script en cours fait un export, lorsqu'il se termine, le "parent" (ici la console) voit encore la variable.

Un export chez le père permet de passer une variable au processus fils, mais une variable modifiée chez le fils, qu'il fasse un export ou non, ne sera pas modifiée chez le père.

$ cat mon_script
echo "a=$a (début script)"
export a=5
echo "a=$a (fin   script)"

$ a=4; echo "a=$a (avant script)"; ./mon_script; echo "a=$a (après script)"
a=4 (avant script)
a= (début script)
a=5 (fin   script)
a=4 (après script)

$ export a=3; echo "a=$a (avant script)"; ./mon_script; echo "a=$a (après script)"
a=3 (avant script)
a=3 (début script)
a=5 (fin   script)
a=3 (après script)

Hors ligne

#6 Le 20/06/2013, à 22:44

amj

Re : [Script] Variable partagée entre plusieurs scripts

Je me doutais bien que c'était trop simple roll


Vive le logiciel libre !! Articles aléatoires sur Wikipédia sur les logiciels libre, sur linux.

@amj@mastodon.xyz

Hors ligne

#7 Le 20/06/2013, à 22:57

Zakhar

Re : [Script] Variable partagée entre plusieurs scripts

Oui c'est sûr, on apprend mieux en faisant son NAS soit-même... "the hard way" comme disent nos amis d'outre-manche... sur ta facture ! wink

Mais il est clair que ça te donne au final une machine plus évolutive qu'un NAS.

Pour ce que tu imagines, tu vois bien que tu es en train de penser :
- il y a un "service" qui mesure la consommation réseau et 'sert' des requêtes 'usage'
- il y a un "client" consommateur du service (le cron) qui demande l'usage et agit en conséquence.

C'est une bonne architecture, mais si tu restes en shell, tu vas être limité par le shell et les outils disponibles.

En effet, ton "service" doit à la fois mesurer la consommation, et "servir" une demande d'usage.
Un script classique étant 'monotâche' ne peut pas faire les deux à la fois.
Pour pouvoir faire les deux à la fois il te faut clairement un truc 'multitâche'.
Ce n'est pas qu'on ne puisse pas faire de shell multitâches... on peut tout à fait lancer un "fils" en tâche de fond et le surveiller, mais de toute façon la communication shell parent/shell fils sera presque aussi compliquée que communiquer avec le cron.

Si ta période de scan est suffisant grande (1min) tu peux faire presque aussi bien que le multitâche.
Tu peux alternativement :
- lire les stats
- utiliser un netcat qui 'écoute' les demandes d'usage
- tu mets un timer sur ton netcat pour boucler sur tes stats

Du côté cron, tu es obligé de faire une petit boucle d'attente pour le cas où tu tombes sur un moment où le netcat n'est pas actif.
En gros ça revient au même que le fichier, sauf qu'au lieu d'écrire systématiquement le fichier, tu l'écris vers le cron quand il te le demande.

Niveau sécurité et failles c'est pas mieux. Un attaquant peut profiter d'un moment où ton script 1 lit pour servir à la place de ton script et balancer des valeurs qui arrêteront ton PC... ou planteront ton script 1 parce que tu as fait un nc sur un port occupé...
Le même attaquant peut aussi lire en permanence sur ce port histoire que les stats aient peu de chance d'arriver au cron.

Bon tests !


"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne

#8 Le 20/06/2013, à 23:04

Zakhar

Re : [Script] Variable partagée entre plusieurs scripts

pingouinux a écrit :

Bonsoir,

Zakhar   #3 a écrit :

Au contraire, si le script en cours fait un export, lorsqu'il se termine, le "parent" (ici la console) voit encore la variable.

Un export chez le père permet de passer une variable au processus fils, mais une variable modifiée chez le fils, qu'il fasse un export ou non, ne sera pas modifiée chez le père.

Tu as bien fait de corriger, j'ai écrit un peu trop vite le contraire de ce que je voulais dire.

Il n'y a effectivement pas de moyen de passer une variable au père (et encore moins à tout autre process indépendant).

Le seul 'contournement' pour le père est de récupérer le stdout du fils comme ça :

$ ( foo='Hello World'; echo "${foo}" ); echo "${foo}"
Hello World

$ foo="$( foo='Hello World'; echo "${foo}" )"; echo "${foo}"
Hello World

... mais comme de toute façon stdout est un fichier, ça revient à l'écriture en fichier que j'évoquais plus haut.


"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne