[bash] Extinction auto du pc si idle et eth0 non sollicité

Extinction auto du pc si idle et eth0 non sollicité [bash] - Codes et scripts - Linux et OS Alternatifs

Marsh Posté le 09-03-2009 à 21:01:34    

Petite prise de tête de la soirée, comment répondre à cette belle question ?
 
J'ai trouvé quelques pistes de scripts mais ca ne me plais pas en l'état.
 
Pour le moment j'ai presque le script pour éteindre le pc si tous les utilisateurs logués sont inactifs. Presque.
 

Code :
  1. #!/bin/bash
  2. #
  3. # This is scheduled in CRON using ROOT, it runs every 5 minutes
  4. # and uses who -a to determine user activity. Once the idle time is
  5. # more than the threshold value it shuts the system down.
  6. #
  7. echo "Start of automatic_shutdown_on_idle.sh"
  8. threshold=10
  9. log=/var/log/automatic_shutdown_on_idle.log
  10. #Sélection de tous les utilisateurs logués sur les consoles tty
  11. inactive=`who -a | grep tty | grep -e "LOGIN" -v | cut -c 42-46`
  12. #inactive=`who -u | cut -c40-50 | sort | grep [0-9] | head -n1 | sed 's/ //g'`
  13. echo "$inactive"
  14. if [ "$inactive" != "" ]; then
  15. echo "Idle time is: " $inactive
  16. echo `date` $inactive >> $log
  17. if [ "$inactive" = "." ]; then
  18.  echo "Tous les utilisateurs logués ne sont pas inactifs. Arrêt."
  19.  exit 0
  20. else
  21.  if [ "$inactive" >= "$threshold" ]; then
  22.   echo "Threshold met so issuing shutdown command"
  23.   /sbin/shutdown -h now
  24.  fi
  25. fi
  26. fi


Je me suis logué sur tty1 et tty7, et j'obtiens ceci après avoir exécuté (sauvagement) le script:

Code :
  1. root@thanux:/home/thana# ./shut
  2. Start of automatic_shutdown_on_idle.sh
  3. 00:27
  4.   . 
  5. Idle time is:  00:27 .
  6. ./shut: line 26: [: 00:27
  7.   .  : unary operator expected


 
J'ai aussi du mal à comprendre pourquoi, exécuté en tant que root, le script ne crée pas le fichier log [:transparency]
 
A vous les studios :jap:

Reply

Marsh Posté le 09-03-2009 à 21:01:34   

Reply

Marsh Posté le 09-03-2009 à 21:47:01    

salut,
 
en bash, utilise plutot les tests [[ au lieu de [ ils sont bien plus pratiques et puissants.

Citation :

<greybot> [[ is a shell keyword similar to (but more powerful than) the [ command. See http://mywiki.wooledge.org/BashFAQ/031 and http://mywiki.wooledge.org/BashGuide#Bash_Tests Unless you are scripting for POSIX sh we recommend [[.


Par exemple, ils peuvent éviter des problèmes de word-spliting.
Voici ce que tu demande à bash :

Code :
  1. $ sh -c '[ "00:27" >= "10" ]'
  2. sh: line 0: [: 00:27: unary operator expected


 
Essaye plutot ça :

Code :
  1. #!/bin/bash
  2. #
  3. # This is scheduled in CRON using ROOT, it runs every 5 minutes
  4. # and uses who -a to determine user activity. Once the idle time is
  5. # more than the threshold value it shuts the system down.
  6. #
  7. ## ${0##*/} utilise les "parameter expansions" pour decouper la chaine
  8. echo "Start of ${0##*/}"
  9. threshold=10
  10. log=/var/log/automatic_shutdown_on_idle.log
  11. ## si tu ne fait pas de source d'un environement, crontab n'aura pas tout dans le PATH
  12. ## et date ne fonctionnera pas, d'où le fait que le fichier ne se crèe pas.
  13. source /etc/profile
  14. #Sélection de tous les utilisateurs logués sur les consoles tty
  15. ## ( attention, je ne suis pas sur que ton cut soit fiable, tu devrais
  16. ## plutot prendre awk '{print $N}' ou N est la colonne que tu veut afficher.
  17. inactive=$(who -a | grep tty | grep -v -- "LOGIN" | cut -c 42-46)
  18. if ! [[ "$inactive" ]]; then
  19.     echo "Idle time is: $inactive"
  20.     echo "$(date) $inactive" >> $log
  21.     if [[ "$inactive" = "." ]]; then
  22.         echo "Tous les utilisateurs logués ne sont pas inactifs. Arrêt."
  23.         exit 0
  24.     else
  25.         ## pour l'arithmetique, on utilise en 2009 les doubles parentheses
  26.         ## pas besoin de mettre le $ sur les variables...
  27.         inactive=${inactive#*:} ## on reutilise les "parameter expansions"
  28.         ## car on ne peux pas creer un calcul avec par Ex : "00:27"
  29.         if ((inactive >= threshold)); then
  30.             echo "Threshold met so issuing shutdown command"
  31.             /sbin/shutdown -h now
  32.         fi
  33.     fi
  34. fi


 
Mes commentaires commencent avec ## dans le script.
A adapter peux etre, je t'invite à tout relire.


Message édité par sputnick le 10-03-2009 à 10:58:33
Reply

Marsh Posté le 10-03-2009 à 18:23:01    

Ok pour les conseils :jap:
 
Mais ca coince dés le premier if, je n'ai jamais le "Idle time is: $inactive".
 
Avec un utilisateur inactif sur tty1 et moi sur tty7, et un echo "$inactive" juste avant le if:

Code :
  1. sleep 60 && ./shut2
  2. Start of shut2
  3. 01
  4. .

Reply

Marsh Posté le 10-03-2009 à 20:59:49    

Donne moi la copie de ton terminal ( who ... ) sur http://pastebin.com par exemple. ( il doit y avoir le vrai nombre d'espace et/ou de tabs )

Reply

Marsh Posté le 10-03-2009 à 21:29:03    

http://pastebin.com/m4a09981c
 

Code :
  1. thana@thanux:~$ who -a | grep tty | grep -v -- "LOGIN" | awk '{print $6}'
  2. 03:13
  3. .

Reply

Marsh Posté le 10-03-2009 à 23:46:47    

Retire le "!" dans

Code :
  1. if ! [[ "$inactive" ]]; then

ca devrais aller.

Reply

Marsh Posté le 11-03-2009 à 07:28:24    

Ca avance un peu, mais il semble que le "parameter expansion" ne soit pas pris en compte pour les autres utilisateurs (le premier semble marcher):

 
Code :
  1. sleep 60 && ./shut2
  2. Start of shut2
  3. 02
  4. 00:01
  5. Idle time is: 02
  6. 00:01
  7. 02
  8. 00:01
  9. ./shut2: line 36: ((: 02
  10. 00:01: syntax error in expression (error token is "00:01" )


Message édité par thana54 le 11-03-2009 à 07:29:02
Reply

Marsh Posté le 11-03-2009 à 12:49:06    

Je suis une truffe en bash, mais n'y existe t-il pas un moyen de splitter $inactive et boucler sur chaque item splitté ?
J'ai l'impression que c'est le passage à un autre utilisateur (donc autre résultat dans $inactive) qui ne se fait pas bien.
/me va jeter un oeil sur les loop/while/for.


Message édité par thana54 le 11-03-2009 à 12:54:08
Reply

Marsh Posté le 11-03-2009 à 15:58:08    

Code :
  1. oIFS=$IFS; IFS=:; arr=( $inactive ); for item in ${arr[@]}; do echo $item; done; IFS=$oIFS


Message édité par sputnick le 11-03-2009 à 19:46:48
Reply

Marsh Posté le 11-03-2009 à 19:56:22    

J'avance bien :)

 

http://pastebin.com/f38af4c1c

 
Code :
  1. #!/bin/bash
  2. #
  3. # This is scheduled in CRON using ROOT, it runs every 5 minutes
  4. # and uses who -a to determine user activity. Once the idle time is
  5. # more than the threshold value it shuts the system down.
  6. #
  7. ## ${0##*/} utilise les "parameter expansions" pour decouper la chaine
  8. echo "Start of ${0##*/}";
  9. # Temps limite avant extinction de l'ordinateur
  10. threshold=10;
  11. # Fichier log utilisé
  12. log=/var/log/automatic_shutdown_on_idle.log;
  13. ## si tu ne fait pas de source d'un environement, crontab n'aura pas tout dans le PATH
  14. ## et date ne fonctionnera pas, d'où le fait que le fichier ne se crèe pas.
  15. source /etc/profile;
  16. # Sélection de tous les utilisateurs logués sur les consoles tty
  17. inactive=$(who -a | grep tty | grep -v -- "LOGIN" | awk '{print $6}')
  18. # Caractère de découpage (Input Field Separator)
  19. IFS=$'\n';
  20. # Tableau contenant les différents temps d'inactivité des users connectés
  21. arr=( $inactive );
  22. # Arrêt du programme par défaut, sans extinction (nombre par défaut d'utilisateurs inactifs)
  23. inactifs=0;
  24. # Nombre total d'utilisateurs logués (taille du tableau arr)
  25. total_logged_users=${#arr[@]};
  26. # Message à afficher dans le log/écran
  27. msg="";
  28. for item in ${arr[@]};
  29. do
  30. if  [[ "$item" ]]; then
  31.     echo "Idle time is: $item";
  32.     if [[ "$item" = "." ]]; then
  33.         msg="Tous les utilisateurs logués ne sont pas inactifs. Arrêt.";
  34.  echo " BREAK !!! ";
  35.  break;
  36.     else
  37.  # Conversion de l'inactivité "hh:mm" en "mmm"
  38.  IFS=:;
  39.  tab=( $item );
  40.  (( item = 60 * tab[0] + tab[1] ));
  41.  echo "Conversion terminée, tab[0]=<'${tab[0]}'>, tab[1]=<'${tab[1]}'>, item=<$item>";
  42.         ## pour l'arithmetique, on utilise en 2009 les doubles parentheses
  43.         ## pas besoin de mettre le $ sur les variables...
  44.  #item=${item#*:} ## on reutilise les "parameter expansions"
  45.         ## car on ne peux pas creer un calcul avec par Ex : "00:27"
  46.  if (( item >= threshold )); then
  47.              msg="Extinction du pc le $(date) après ${item}min d'inactivité";
  48.   (( inactifs += 1 ))
  49.         fi
  50.     fi
  51. fi
  52. echo "$msg" >> log;
  53. done;
  54. echo "Sortie: $inactifs/$total_logged_users utilisateur(s) intactif(s)";
  55. if (( inactifs == total_logged_users )); then
  56. echo " EXTINCTION ";
  57. ##/sbin/shutdown -h now;
  58. fi
  59. unset IFS;
  60. unset threshold;
  61. unset log;
  62. unset arr;
  63. unset item;
  64. unset tab;
  65. unset inactifs;
  66. unset total_logged_users;
  67. unset msg;
 

Oui bon c'est pas grand chose, mais c'est un début. La suite avec l'utilisation du net et du proc pour bientôt.


Message édité par thana54 le 11-03-2009 à 19:59:36
Reply

Marsh Posté le 11-03-2009 à 19:56:22   

Reply

Marsh Posté le 11-03-2009 à 20:33:36    

J'ai fait une version "clean" de ton code http://pastebin.com/d116b3c ( c'est important que ça soit lisible, il faut indenter correctement, etc...), mais il y a un truc qui me chagrine ( quelques modifications faites pour l'améliorer, je te laisse voir. J'ai retiré le superflus et simplifié certains trucs ) : tu teste ligne 33 si la variable est vide, mais elle l'est forcement puisque tu fait un "for" sur les valeurs successives du tableau.


Message édité par sputnick le 11-03-2009 à 20:35:16
Reply

Marsh Posté le 17-03-2009 à 19:28:07    

Petite avancée ce soir.
 
Je tente de savoir si il y a de l'activité sur eth en dl (ligne RX avec ifconfig).
ethstats me donne des lignes intéressantes, mais je ne sais pas comment l'arrêter (il tourne en boucle et dans un script ca me gêne).
J'ai trouvé une piste avec ca  

Code :
  1. /sbin/ifconfig eth0 | grep -m 1 RX | cut -d: -f2 | sed 's/ //g' | sed 's/errors//g'


mais ca me crée des fichiers :/ N'y a t-il pas un moyen de ne pas créer de fichier et de garder quelques secondes les données en mémoire ?

Reply

Marsh Posté le 17-03-2009 à 19:40:15    

utilise une variable :spamafote:


---------------
uptime is for lousy system administrators what Viagra is for impotent people - mes unixeries - github me
Reply

Marsh Posté le 17-03-2009 à 19:41:51    

Oui :jap:

Code :
  1. actual_rate=$(/sbin/ifconfig eth0 | grep -m 1 RX | awk '{print $2}' | sed 's/ //g' | sed 's/packets://' | sed 's/errors//g' && sleep 2 && /sbin/ifconfig eth0 | grep -m 1 RX | awk '{print $2}' | sed 's/ //g' | sed 's/packets://' | sed 's/errors//g')
  2. echo "$actual_rate"


Ca me parait pas mal, plus qu'à découper à coup d'IFS et une petite comparaison ca devrait aller.

 

[edit] Sûrement une subtilité du bash pour me crée le fichier [:transparency]
Ah oui le "echo 'blabla' > toto" [:prozac]


Message édité par thana54 le 17-03-2009 à 19:43:49
Reply

Marsh Posté le 17-03-2009 à 19:55:02    

tu as ta variable, ne crée pas de fichier [:mlc]


---------------
uptime is for lousy system administrators what Viagra is for impotent people - mes unixeries - github me
Reply

Marsh Posté le 17-03-2009 à 20:36:51    

Ne t'en fais pas, j'ai seulement remarqué ma bétise en exécutant un code tout fait.

Reply

Marsh Posté le 17-03-2009 à 20:52:43    

Code :
  1. packsons=$(/sbin/ifconfig eth0 | awk -F'[ :]' '/RX packets/ {print $13}')
  2. if (( packsons > 1 )); then echo "Activite detectee sur eth0"; else echo >&2 "Aucune activite sur eth0"; fi

Reply

Marsh Posté le 18-03-2009 à 21:48:23    

Merci, ca me raccourcis pas mal la commande :jap:
J'ai encore quelques idées à mettre en place pour finaliser le script :) Ca serais dommage de se prendre un shutdown dans les dents en plein matage de film/transfert vnc ou autre.

Reply

Marsh Posté le 01-04-2009 à 23:12:12    

Petite mise à jour ce soir sur une fonction permettant d'annuler l'extinction si certains processus sont lancés. Mais voila je coince sur un découpage :heink:
 
work in progress, donc des parties en commentaires.

Code :
  1. #!/bin/bash
  2. #
  3. # This is scheduled in CRON using ROOT, it runs every 5 minutes
  4. # and uses who -a to determine user activity. Once the idle time is
  5. # more than the threshold_time value it shuts the system down.
  6. #
  7. ## ${0##*/} utilise les "parameter expansions" pour decouper la chaine
  8. echo ">>> Start of ${0##*/}";
  9. ################################################################################
  10. # Variables personnelles                                                       #
  11. ################################################################################
  12. # Temps limite avant extinction du pc, en minutes
  13. threshold_time=1;
  14. # Débit limite en dessous duquel le pc sera éteint, en ko/s
  15. threshold_rate=10;
  16. # Fichier log utilisé
  17. log=/var/log/automatic_shutdown_on_idle.log;
  18. # Liste des programmes en cours d'exécution annulant l'extinction du pc
  19. process_list_to_monitor=( firefox iceweasel mplayer vlc ghb ogmrip medit );
  20. ################################################################################
  21. # Variables nécessaires pour le script                                         #
  22. ################################################################################
  23. source /etc/profile;
  24. # Sélection de tous les utilisateurs logués sur les consoles tty
  25. inactive=$(who -a | grep tty | grep -v -- "LOGIN" | awk '{print $6}')
  26. # Sauvegarde de l'IFS
  27. oIFS=IFS;
  28. # Caractère de découpage (Input Field Separator)
  29. IFS=$'\n';
  30. # Tableau contenant les différents temps d'inactivité des users connectés
  31. arr=( $inactive );
  32. # Arrêt du programme par défaut, sans extinction (nombre par défaut d'utilisateurs inactifs)
  33. inactives_users=0;
  34. # Nombre total d'utilisateurs logués (taille du tableau arr)
  35. total_logged_users=${#arr[@]};
  36. # Débit actuel sur eth
  37. rate=$(/sbin/ifconfig eth | awk -F'[ :]' '/RX packets/ {print $13}' && sleep 2 && /sbin/ifconfig eth | awk -F'[ :]' '/RX packets/ {print $13}');
  38. array=( $rate );
  39. (( actual_rate = (array[1] - array[0])/2 ));
  40. ################################################################################
  41. ## Recherche du nombre d'utilisateurs inactifs
  42. ################################################################################
  43. looking_for_inactives() {
  44. for item in ${arr[@]}; do
  45. echo ">>> Recherche du nombre d'utilisateurs inactifs: ...";
  46. echo "    Idle time is: $item";
  47. if [[ "$item" = "." ]]; then
  48.   echo ">>> BREAK !!! ";
  49.  break;
  50. else
  51.  # Conversion de l'inactivité "hh:mm" en "mmm"
  52.  IFS=:;
  53.  tab=( $item );
  54.  (( item = 60 * tab[0] + tab[1] ));
  55.  #echo "Conversion terminée, tab[0]=<${tab[0]}>, tab[1]=<${tab[1]}>, item=<$item>";
  56.  ## pour l'arithmetique, on utilise en 2009 les doubles parentheses
  57.  ## pas besoin de mettre le $ sur les variables...
  58.  #item=${item#*:} ## on reutilise les "parameter expansions"
  59.  ## car on ne peux pas creer un calcul avec par Ex : "00:27"
  60.  if (( item >= threshold_time )); then
  61.   (( inactives_users += 1 ))
  62.  fi
  63. fi
  64. done;
  65. }
  66. ## /
  67. ################################################################################
  68. ## Vérification du débit sur eth seulement si tous les utilisateurs sont inactifs
  69. ################################################################################
  70. looking_for_eth_rate() {
  71. echo "$(date) ### Tous les utilisateurs sont inactifs " >> $log;
  72. IFS=$'\n';
  73. #Avant d'éteindre le pc, on va vérifier qu'il n'y a pas d'activité importante sur eth
  74. echo "    Débit actuel sur eth: ${actual_rate}Ko/s";
  75. if (( actual_rate <= threshold_rate )); then
  76. echo "$(date) ### Peu d'activité sur eth (${actual_rate}ko/s)" >> $log;
  77. echo "$(date) ### EXTINCTION le $(date)" >> $log;
  78. return 1;
  79. else
  80. echo "$(date) ### Activité sur eth détectée (${actual_rate}ko/s). ARRET" >> $log;
  81. return 0;
  82. fi
  83. }
  84. ## /
  85. ################################################################################
  86. ## Recherche des process lancés
  87. ################################################################################
  88. looking_for_forbidden_process() {
  89. echo "into forbidden";
  90. for process in ${process_list_to_monitor[@]}; do
  91. echo "    Recherche du processus: ${process}";
  92. #presence=`ps -C  ${process} -o pid,pcpu,pmem,lstart,command | grep ${process}`;
  93. presence=`ps -C  ${process} -o pid,pcpu,pmem,command | grep ${process}`;
  94. if [[ "$presence" = "" ]]; then
  95.  echo "";
  96. else
  97.  IFS=' ';
  98.  tab=( $presence );
  99.  echo "    PID: ${presence[0]} CPU: ${presence[1]}";
  100. fi
  101. done;
  102. }
  103. ## /
  104. ################################################################################
  105. # Début du script                                                              #
  106. ################################################################################
  107. echo ">>> Initialisation...";
  108. echo "    Nombre d'utilisateurs logués: $total_logged_users";
  109. #looking_for_inactives;
  110. looking_for_forbidden_process;
  111. #if (( inactives_users == total_logged_users )); then
  112. # (( result=looking_for_eth_rate ));
  113. # echo "${result}";
  114. # if (( result )); then
  115. #  #Recherche des programmes qui vont interdire l'arrêt du pc
  116. #  looking_for_forbidden_process;
  117. #  ##/sbin/shutdown -h now;
  118. # fi
  119. #fi
  120. #echo "$(date) ### Sortie: $inactives_users/$total_logged_users utilisateur(s) intactif(s)" >> $log;
  121. ################################################################################
  122. # Fin du script                                                                #
  123. ################################################################################

Reply

Marsh Posté le 01-04-2009 à 23:18:47    

Peux tu expliquer ce que tu veut decouper ?
ca sert à rien ca :

Code :
  1. echo "$(date)"


 

Code :
  1. date


est emplement suffisant ^^

Reply

Marsh Posté le 01-04-2009 à 23:27:16    

Dans cette partie là, je récupère le résultat de la commande ps qui est une ligne (ou non) séparée par des espaces.
Mais je ne comprend pas pourquoi le découpage ne marche pas sur ce cas là, alors que j'ai précédemment réussi à découper une chaine comprenant ":". [:cerveau paysan]

Code :
  1. ################################################################################
  2. ## Recherche des process lancés
  3. ################################################################################
  4. looking_for_forbidden_process() {
  5. echo "into forbidden";
  6. for process in ${process_list_to_monitor[@]}; do
  7. echo "    Recherche du processus: ${process}";
  8. #presence=`ps -C  ${process} -o pid,pcpu,pmem,lstart,command | grep ${process}`;
  9. presence=`ps -C  ${process} -o pid,pcpu,pmem,command | grep ${process}`;
  10. if [[ "$presence" = "" ]]; then
  11. echo "";
  12. else
  13. IFS=' ';
  14. tab=( $presence );
  15. echo "    PID: ${presence[0]} CPU: ${presence[1]}";
  16. fi
  17. done;
  18. }
  19. ## /


Je sens que l'IFS n'est pas bon, mais je ne sais pas quoi lui spécifier.

Reply

Marsh Posté le 02-04-2009 à 00:06:55    

Peux tu expliquer en Francais éventuellement avec un exemple *clair et simple* ce que tu veut faire ?
 
Apprend à bien indenter, ca permet de pouvoir se relire aisement et c'est mieux aussi pour les autres...

Reply

Marsh Posté le 02-04-2009 à 09:14:15    

L'indentation n'a pas supporté le copier coller.
Le but de la fonction c'est de rechercher, parmi une liste, des processus en cours d'exécution (reste à distinguer ce point si vraiment ca peut être utile) et de comparer la charge cpu qui leur sont allouée.
 
J'arrive à avoir les processus de la liste avec quelques infos (pid, pcpu, pmem,command) mais je ne comprend pas pourquoi la ligne 14 ne me donne pas un tableau avec plusieurs indices (j'ai tout en ${presence[0]} et rien en ${presence[1]}).

Reply

Marsh Posté le 03-04-2009 à 19:01:19    

Je suis fatigué par moment [:prozac]
Faut le faire de demander un élément d'un string quand on découpe ce string vers une autre variable :pfff:

Code :
  1. IFS=$oIFS;
  2.  tab=( $presence );
  3.  echo "    PID: ${tab[0]} CPU: ${tab[1]} MEM: ${tab[2]}";


Et là ca passe tout de suite mieux.

 

Autre soucis maintenant, comment faire pour être sur de ne pas avoir de processus lancés doublon [:transparency]

 

Petite question: est-ce possible avec un echo (et un seul) d'afficher sur la sortie standard et en même temps dans un fichier ? Existe t-il un moyen de surcharger ce mot clef ?


Message édité par thana54 le 03-04-2009 à 19:11:03
Reply

Marsh Posté le 07-04-2009 à 00:47:53    

pour afficher et ecrire en meme temps : "echo foo | tee /tmp/pouet"
pour le reste je n'arrive pas à tout suivre...

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed