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 27/01/2016, à 10:03

Boombastick

[BASH] Comment faire un timer ?

Ave à vous, frères basheux !

Je voudrais dans un bash, faire un timer pour vérifier que l'utilisateur est toujours présent et sinon redémarrer le script. Dans l'exemple j'utiliserais goto mais je le transformerais en boucle.

Du coup ça donnerais un truc du genre:

timer=30
if user fais rien pendant 10s
   commencer timer
if timer = 0
   goto début du script

Je suis même pas sur que ce soit faisable en bash mais si quelqu'un a une idée...

Au pire je suis preneur pour d'autres languages.

Hors ligne

#2 Le 27/01/2016, à 11:31

Watael

Re : [BASH] Comment faire un timer ?

salut,

quel est le contexte ? X, ou console ?

a priori, ce ne serait pas if user fais rien pendant 10s, mais TANT_QUE user ne fais rien ET temps écoulé inférieur à 10s; FAIRE passer N secondes; FIN-TANT_QUE

il n'y a pas de GOTO en shell, il y a des boucles.


Connected \o/
Welcome to sHell. · eval is evil.

Hors ligne

#3 Le 27/01/2016, à 14:01

serged

Re : [BASH] Comment faire un timer ?

Si tu veux juste attendre 30s :

sleep 30

suffit.

Si tu veux tester un truc pendant 30s :

#!/bin/bash
fin=`date +"%s"`
echo -n $fin
let fin=$fin+30
echo " " $fin

while [ `date +"%s"` -lt $fin ]
do
#  tester quelque chose
done
echo delai dépassé

LinuxMint Vera Cinnamon et d'autres machines en MATE, XFCE... 20.x , 21.x ou 19.x
Tour : Asus F2A55 / AMD A8-5600K APU 3,6GHz / RAM 16Go / Nvidia GeForce GT610 / LM21.1 Cinnamon
Portable : LDLC Mercure MH : Celeron N3450 /RAM 4Go / Intel HD graphics 500 i915 / biboot Win 10 (sur SSD) - LM21.1 MATE (sur HDD)

Hors ligne

#4 Le 27/01/2016, à 19:09

Totor

Re : [BASH] Comment faire un timer ?

serged a écrit :

[...]
Si tu veux tester un truc pendant 30s :

#!/bin/bash
[...]

La vache, comme ça, tu va bouffer tout le CPU ... enfin... tout dépend de ce qu'il entend par "user ne fait rien pendant 10s"....
Comme le dit Watael, tout dépend du contexte, etc...


-- Lucid Lynx --

Hors ligne

#5 Le 27/01/2016, à 22:32

Totor

Re : [BASH] Comment faire un timer ?

Si tu veux un "Timer" autonome en bash, alors soit le script "Timer.sh" suivant :

#!/bin/bash 

_SHELL_PID=
_SHELL_SIG=SIGUSR1
_SHELL_TIMESTAMP=60

function startTimer {
	while sleep ${_SHELL_TIMESTAMP}s
	do
		# on envoie le signal uniquement si le process existe toujours
		ps -p ${_SHELL_PID} &>/dev/null || return 0
		
		builtin kill -${_SHELL_SIG} ${_SHELL_PID}		
	done
}

# vérification des paramétres
while getopts :s:p:t: option 
do
	case "${option}" in
		p) _SHELL_PID=${OPTARG};;
		s) _SHELL_SIG=${OPTARG};;		
		t) _SHELL_TIMESTAMP=${OPTARG};;
		:) echo "Argument manquant pour l'option '${OPTARG}'" >&2
			exit 1;;
		"?") echo "Option non valide : ${OPTARG}." >&2
			exit 1;;
	esac
done

# vérifications liées au PID
# par défaut, le PID est le PID du parent
[[ ${_SHELL_PID} ]] || _SHELL_PID=${PPID}

# vérification du format & de l'existence du process
[[ ${_SHELL_PID//[0-9]} ]] && {
	# erreur dans le format attendu
	echo "Numéro de PID '${_SHELL_PID}' erroné !" >&2
	exit 1
}

# le PID existe-t-il ?
ps -p ${_SHELL_PID} &>/dev/null || {
	echo "Aucun processus pour le PID '${_SHELL_PID}'" >&2
	exit 1
}	

# Vérification du signal à passer
[[ ${_SHELL_SIG} ]] || _SHELL_SIG=SIGUSR1

# précautions d'usage
_SHELL_SIG="${_SHELL_SIG^^}"
_SHELL_SIG="SIG${_SHELL_SIG#SIG}"

_SIG_LISTE="$(builtin kill -l)"
# on vérifie si c'est un signale valide
[[ "${_SIG_LISTE}" == *${_SHELL_SIG}\)* || "${_SIG_LISTE}" == *\)\ ${_SHELL_SIG}[[:space:]]* ]] || {
	echo "Signal '${_SHELL_SIG}' non valide !" >&2
	exit 1
}

# vérification du délai
# par défaut, le timestamp est de 60sec
[[ ${_SHELL_TIMESTAMP} ]] || _SHELL_TIMESTAMP=60
[[ ${_SHELL_TIMESTAMP//[0-9]} ]] && {
	# erreur dans le format attendu
	echo "Délai '${_SHELL_TIMESTAMP}' non valide !" >&2
	exit 1
}
startTimer

et un script de test :

#!/bin/bash

trap test SIGUSR1
cpt=0

function test {
 echo "signal"
 ((cpt++))
}

coproc TIMER { ./Timer.sh -t 2 -p $$ ; }

_PID=${TIMER_PID}
echo ${_PID}
while ((cpt <= 2))
do
	ps -f -p $_PID --no-headers
	sleep 1	
done

Si tu exécutes ce dernier script, tu verras apparaitre dans cet ordre :

  • Le n° du processus du Timer sur la 1ère ligne

  • Puis 3 fois de suite 2 lignes contenant les infos sur ce même processus suivi du texte "signal"

Il est possible d'arrêter le Timer en envoyant le signal "SIGKILL" au processus "${TIMER_PID}".
Si tu changes le nom de ton coproc (tu peux utiliser ainsi plusieurs Timer), alors le nom de la variable contenant son PID changera également.
Pour plus d'info sur les coproc :

man bash | less +'/coproc \['

Dernière modification par Totor (Le 27/01/2016, à 22:36)


-- Lucid Lynx --

Hors ligne

#6 Le 28/01/2016, à 08:28

serged

Re : [BASH] Comment faire un timer ?

Totor a écrit :
serged a écrit :

[...]
Si tu veux tester un truc pendant 30s :

#!/bin/bash
[...]

La vache, comme ça, tu va bouffer tout le CPU ... enfin... tout dépend de ce qu'il entend par "user ne fait rien pendant 10s"....
Comme le dit Watael, tout dépend du contexte, etc...

C'était un exemple bête... Je ne sais pas ce qu'il veut tester. On peut mettre des sleep dans la boucle, par exemple.

Si on veut une simple entrée au clavier :

#!/bin/bash
echo -n Entrez votre choix :
if  read -t 30
then
 echo "Vous vous êtes endormi?"
else
 echo "Vous avez tapé $REPLY"
fi

Beaucoup de commandes (comme ici "read" avec -t) on une option de time-out...


LinuxMint Vera Cinnamon et d'autres machines en MATE, XFCE... 20.x , 21.x ou 19.x
Tour : Asus F2A55 / AMD A8-5600K APU 3,6GHz / RAM 16Go / Nvidia GeForce GT610 / LM21.1 Cinnamon
Portable : LDLC Mercure MH : Celeron N3450 /RAM 4Go / Intel HD graphics 500 i915 / biboot Win 10 (sur SSD) - LM21.1 MATE (sur HDD)

Hors ligne

#7 Le 28/01/2016, à 18:49

LeoMajor

Re : [BASH] Comment faire un timer ?

si l'utilisateur est toujours présent

Tu fais un test à partir de who,w, (session), si l'utilisateur est connecté
ou xprintidle (activité souris & clavier) : si la valeur tend vers 0, l'utilisateur tend à être actif, sinon, il est de plus en plus inactif

 while true; do while [ "$(xprintidle)" -lt 5000 ]; do xprintidle ; sleep 1; done; echo "5 secondes et plus d'inactivité de souris & clavier"; sleep 1; done

Pourquoi n'utilises-tu pas un cron ?  Tu as juste à tester directement who,w,xprintidle, sans faire de boucle/while.
Cela évite ce genre de code:

unset users;
users=( $(awk -F: '/10[0-9][0-9]/ {print $1}' /etc/passwd) );
while true; do for ((i=0;i<${#users[@]};i++)) ; do cond=$(who | grep -c "${users[$i]}"); if [ "$cond" -eq 0 ]; then echo "ko ${users[$i]} absent : script à exécuter"; else echo "ok ${users[$i]} présent"; fi; done; sleep 10; done

Hors ligne