Page 1 sur 2

[script] contre la fuite memoire

Publié : dim. 19 août 2007, 11:26
par cassyb
salut,

Certaines applications (navigateurs web, telechargement, video, voire même le terminal quand il regarde un enorme log) provoque l'instabilité du système en nous obligeant à rebooter comme un bourrin.

Je voulais savoir le nom d'un paquet qui surveillerait les processus et si %mem et %CPU sont supérieur à un certains seuil pendant 4-5 secondes ça envoit un popup pour nous permettre de continuer l'execution du programme ou bien de le killer.

S'il n'existe pas pouvez-vous m'aider à la creation d'un script.
3 paramètres:
- Nbseconds
- mem_seuil
- cpu_seuil

Algo:
- lancer top
- regarder pendant Nbseconds si un process est au dessus de mem_seuil ou cpu_seuil
- si c'est le cas, ça envoie un popup: L'application "nom_application" rend votre système instable. Voulez-vous killer cette application?
- en cliquant sur le bouton killer, ça lance un kill -9 du pid ou un killall de l'application.

Mais est-il possible de s'envoyer un popup via un script sh?
merci pour votre aide.

a+
Cassy.

Publié : dim. 19 août 2007, 11:36
par wain
Oui envoyer un popup c'est possible de différentes manières. La plus simple qui me vient à l'esprit est d'utiliser xdialog.

Sinon au lieu d'utiliser top, je te conseille plutôt "ps". Rien qu'avec "grep" et "cut" tu pourra réaliser ce que tu souhaites.

Publié : dim. 19 août 2007, 12:06
par cassyb
b'hein top ça evite de lancer Nbseconds fois la commande ps non?
c'est pour ça que je pensais à top plutôt qu'à ps.

Publié : dim. 19 août 2007, 12:32
par wain
Je vois pas trop comment récupérer les infos de top... et puis faire tourner top en permanence ça doit pas etre rentable en terme de ressources consommées.
L'idéal serait peut-etre de taper dans /proc directement ?
un peu d'aide: http://forums.archlinux.fr/topic854.html

Publié : dim. 19 août 2007, 15:00
par cassyb
je suis aller voir ton lien...mais je ne vois pas trop comment je pourrais utiliser /proc (déjà que j'ai du mal avec ps)

j'arrive pas à classer le %mem ou %cpu en ordre décroissant.
sur un site j'ai vu qu'ils utilisent le champ rss, je ne sais pas si c'est un bon indicateur:
ps aux --sort:-rss

comment ferais-tu pour classer suivant %mem et %cpu décroissant.
et comment récupérer juste la 2ème ligne du ps c'est à dire l'application qui occupe le + de mémoire?

merci.

Publié : dim. 19 août 2007, 16:27
par cassyb
bon j'y suis presque.
mais j'arrive pas à créer une variable dynamiquement.
genre

APPLICATION_CPU='blabla'
echo $APPLICATION_CPU
renvoie blabla

EXT ='_CPU'
echo ${APPLICATION$EXT}
j'ai droit à un bad substitution
comment faire pour qu'il renvoie blabla?

Publié : dim. 19 août 2007, 17:33
par cassyb
Bon j'ai fait sans tant pis.

Aussi j'ai des pb d'accents, ça affiche des hieroglyphes...du coup j'ai fait en sorte qu'il n'y ait pas d'accents.

noMemoryLeak s'utilise avec un raccourci clavier.
Peut s'utiliser avec une crontab mais faut modifier le script en spécifiant un seuil de %mem et %cpu.

Code : Tout sélectionner

#!/bin/sh

#sources:
#http://searchenterpriselinux.techtarget.com/tip/0,289483,sid39_gci1248880,00.html
#http://xdialog.dyns.net/

#quelle application occupe le + en %mem
RESULT_MEM=$( ps -eo pmem,pid -o comm= | sort -k1 -n -r | head -1)
P_MEM=$( echo $RESULT_MEM | cut -d' ' -f1)
PID_MEM=$( echo $RESULT_MEM | cut -d' ' -f2)
APPLICATION_MEM=$( echo $RESULT_MEM | cut -d' ' -f3)

#quelle application occupe le + en %cpu
RESULT_CPU=$( ps -eo pcpu,pid -o comm= | sort -k1 -n -r | head -1)
P_CPU=$( echo $RESULT_CPU | cut -d' ' -f1)
PID_CPU=$( echo $RESULT_CPU | cut -d' ' -f2)
APPLICATION_CPU=$( echo $RESULT_CPU | cut -d' ' -f3)

# si c'est la même application qui occupe le + de mem et cpu
if [ $PID_CPU -eq $PID_MEM ]
then 
	CHOICE=`Xdialog --default-no --title "noMemoryLeak" \
        --checklist "Voulez-vous killer cette application?" 9 50 0 \
        "$PID_MEM"  "$APPLICATION_MEM utilise ${P_MEM}%mem et ${P_CPU}%cpu" on 2>&1`
else
	CHOICE=`Xdialog --default-no --title "noMemoryLeak" \
        --checklist "Voulez-vous killer ces applications?" 11 40 0 \
        "$PID_MEM"  "$APPLICATION_MEM utilise $P_MEM %mem" on \
        "$PID_CPU"  "$APPLICATION_CPU utilise $P_CPU %cpu" on 2>&1`
fi

case $? in
	0)
		# si au moins une checkbox cochee
		if [ $CHOICE ]
		then
			# doit-on killer une ou deux applications?
			if [ $( echo $CHOICE | cut -d'/' -f1) -eq $( echo $CHOICE | cut -d'/' -f2) ]
			then
				kill -9 $CHOICE
			else
				kill -9 $( echo $CHOICE | cut -d'/' -f1)
				kill -9 $( echo $CHOICE | cut -d'/' -f2)
			fi
			echo "killed."
		else
			echo "none killed."
		fi;;
	1)
		echo "Cancel pressed.";;
	255)
		echo "Box closed.";;
esac

Publié : dim. 19 août 2007, 18:47
par wain
ça a l'air déjà pas mal, sauf la boite de dialogue qui ne s'affiche pas chez moi.

J'ai pas pigé ce que tu veux dire par "créer une variable dynamiquement." ?

Publié : dim. 19 août 2007, 19:22
par cassyb
ça a l'air déjà pas mal, sauf la boite de dialogue qui ne s'affiche pas chez moi.
Tu connais l'histoire du gars qui conseille xdialog pour sa simplicité mais qui en fait ne l'a jamais installé? :wink:

t'as quelle erreur precisément?

variable dynamique...mais si quand le contenu d'une variable est elle même une variable...comme en php genre $$variable...

APPLICATION_CPU='blabla'
je voulais construire dynamiquement le nom de la variable APPLICATION_CPU ainsi:
${APPLICATION$EXT}
$EXT correspondant à _CPU ou à _MEM

je voulais faire la concatenation de APPLICATION et de _CPU donnant APPLICATION_CPU qui se trouve être cette variable contenant 'blabla'.
ça aurait economisé 4 lignes...pas bien grave.

Publié : dim. 19 août 2007, 20:32
par wain
cassyb a écrit :
ça a l'air déjà pas mal, sauf la boite de dialogue qui ne s'affiche pas chez moi.
Tu connais l'histoire du gars qui conseille xdialog pour sa simplicité mais qui en fait ne l'a jamais installé? :wink:

t'as quelle erreur precisément?

variable dynamique...mais si quand le contenu d'une variable est elle même une variable...comme en php genre $$variable...

APPLICATION_CPU='blabla'
je voulais construire dynamiquement le nom de la variable APPLICATION_CPU ainsi:
${APPLICATION$EXT}
$EXT correspondant à _CPU ou à _MEM

je voulais faire la concatenation de APPLICATION et de _CPU donnant APPLICATION_CPU qui se trouve être cette variable contenant 'blabla'.
ça aurait economisé 4 lignes...pas bien grave.
t'inquiète xdialog est bien là... c'est ton script qui foire:

Code : Tout sélectionner

Xdialog: missing box option !
Les variable dynamique ça n'existe pas en bash. Mais d'après ce que tu décrit, un tableau devrait faire l'affaire.

Publié : dim. 19 août 2007, 20:48
par cassyb
peut être le copié-coller qui a foiré.
Essaye avec le script du site officiel, j'ai pris leur syntaxe.
http://xdialog.dyns.net/

Publié : dim. 26 août 2007, 10:12
par cassyb
J'ai remarqué dans mon ~ que j'avais plein de fichier genre 7.4, 7.9, etc...

Le pb est ici:
if [ $P_MEM > $P_CPU ]

il ne fait pas la comparaison mais ecrit dans le fichier $P_CPU...
j'ai modifier en
if [[ $P_MEM > $P_CPU ]]

si je compare 32.4 à 5.6 il me dit que 5.6 est plus grand. :roll:
il doit faire une compraison de string...

Publié : dim. 26 août 2007, 16:19
par cassyb
bon j'ai fait autrement.
J'en ai profité pour améliorer le script en laissant au choix à l'utilisateur de killer soit l'application la + gourmande en cpu, soit en mem soit les deux.

le script se trouve ici.

Publié : dim. 26 août 2007, 20:32
par _alexmyself
pour pouvoir faire des calculs/comparaisons sur des nombres:

typeset -i mavarnombre=10

comme ça c'est un nombre et plus une chaine

Publié : lun. 24 sept. 2007, 14:06
par cassyb
J'aurais une autre question...
j'écris un autre script

Code : Tout sélectionner

PROCESS_LIST=`ps -eo user,pid -o comm= | grep rsync`
me retourne une liste genre:
root 28398 rsync

Code : Tout sélectionner

for process in $PROCESS_LIST
do
 echo $process
done
ça me renvoie:
root
28398
rsync
comment faire pour qu'il conserve la ligne?
pour que je puisse faire

Code : Tout sélectionner

USER=`echo $process | awk '{print $1}'`
PID=`echo $process | awk '{print $2}'`
PNAME=`echo $process | awk '{print $3}'`
merci.

Publié : lun. 24 sept. 2007, 18:46
par wain
Salut Cassyb

Si ton grep ne te renvoie qu'une seule ligne, alors tu peux utiliser ta variable comme un tableau.

Code : Tout sélectionner

USER=${PROCESS_LIST[0]}
PID=${PROCESS_LIST[1]}
PNAME=${PROCESS_LIST[2]}
si tu veux traiter chacune des lignes (l'une après l'autre), tu peux aussi utiliser la syntaxe "while read":

Code : Tout sélectionner

ps -eo user,pid -o comm= |
while read line; do
    USER=${line[0]}
    PID=${line[1]}
    PNAME=${line[2]}
    echo "$USER :  pid=$PID pname=$PNAME"
done
Mais ça dépend de ce que tu veux faire :)

Publié : lun. 24 sept. 2007, 19:12
par cassyb
alors tu peux utiliser ta variable comme un tableau
et ça split automatiquement ma ligne en tableau?
parce que
PID=${line[1]}
PNAME=${line[2]}
c'est vide chez moi avec bash, sh :shock:
line[0] contient en fait toute la ligne
en gros ça me renvoit ça:
cassy 7346 epiphany : pid= pname=
...

Publié : lun. 24 sept. 2007, 19:37
par wain
ah oui ça split pas pardon. Faut ajouter ligne=( $ligne ) avant

Publié : lun. 24 sept. 2007, 20:25
par cassyb
nikel merci.

Publié : jeu. 08 nov. 2007, 13:39
par cassyb
Juste une question...

Code : Tout sélectionner

ligne=( $ligne ) 
permet par défaut de spliter sur un espace mais si on veut que ça split sur un tiret par exemple t'écrirais ça comment?