Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Interrompre une commande si elle dure plus de N secondes dans un script (bash a priori)

30 réponses
Avatar
Francois Lafont
Bonjour à tous,

J'explique un peu le contexte d'abord. J'ai un script local qui est
lancé à l'ouverture de session sur une Debian Squeeze et dans ce script
local il y a ça :

#-------------------------------------------
if [ -r "/mnt/script_distant" ]; then
/bin/bash "/mnt/script_distant"
fi
#-------------------------------------------

Je teste si le fichier script_distant est bien accessible en lecture car
en réalité /mnt est un répertoire sur lequel est monté un partage Samba
et il se peut que le serveur Samba soit (momentanément) en carafe et
donc, bien que le montage ait été effectué correctement auparavant, le
fichier script_distant peut être (momentanément) inaccessible.

Mon problème, c'est que ce test dure vraiment longtemps dans le cas où
justement le serveur est en carafe (ça peut prendre une vingtaine de
secondes parfois) ce qui ralentit beaucoup trop l'ouverture de session.
Ce que je voudrais, du coup, c'est interrompre le test s'il dure plus de
5 secondes (par exemple), sachant qu'au delà de cette limite 5 secondes,
je décide que c'est mort pour le lancement du script_distant et le
script local passe à la suite de son travail.

Donc ma question est : comment faire pour interrompre une commande si
elle dure plus de 5 secondes ?

En faisant des recherches sur le Web, je suis arrivé à ça :

#-------------------------------------------
# Exemple fictif de commande qui peut durer...
sleep 10 &

compteur=$((1))

COMMANDE_INTERROMPUE=false

# On teste si le processus est en cours
# avec la valeur de retour de « ps $! ».

while ps $! >/dev/null 2>&1; do

if [ $compteur -le 5 ]; then
sleep 1
compteur=$((compteur+1))
else
kill -SIGKILL $! >/dev/null 2>&1
COMMANDE_INTERROMPUE=true
#break
fi

done

if $COMMANDE_INTERROMPUE; then
echo "La commande a été interrompue"
else
echo "La commande n'a pas été interrompue"
fi
#-------------------------------------------

1) Est-ce correct d'après vous ? Toute remarque constructive est la
bienvenue. ;-)

2) Je me pose une question à propos du « break » que j'ai laissé en
commentaire ci-dessus. En l'état, si je lance ce script (il s'appelle
test.bash), j'ai :

#-------------------------------------------
$ bash test.bash
test.bash: line 22: 10160 Processus arrêté sleep 10
La commande a été interrompue
#-------------------------------------------

Je n'arrive pas à comprendre pourquoi j'ai la sortie « test.bash: line
22: 10160 Processus arrêté sleep 10 » ? Elle provient de la sortie
standard des erreurs du script test.bash lui-même, c'est donc une erreur
dans le script, mais je ne la comprends pas. En revanche, si je «
décommente » le break, alors :

#-------------------------------------------
$ bash test.bash
La commande a été interrompue
#-------------------------------------------

Je n'ai plus cette erreur. Avez-vous une explication ?

Merci d'avance pour votre aide.


--
François Lafont

10 réponses

1 2 3
Avatar
Fabien LE LEZ
On Fri, 02 Mar 2012 15:52:40 +0100, Francois Lafont
:

Je n'arrive pas à comprendre pourquoi j'ai la sortie « test.bash: line
22: 10160 Processus arrêté sleep 10 » ?



Sans le break, la boucle "while" va faire un tour de plus, et ps sera
appelé sur un processus détruit. D'où le message d'erreur.
Avatar
Francois Lafont
Le 02/03/2012 15:56, Fabien LE LEZ a écrit :

Je n'arrive pas à comprendre pourquoi j'ai la sortie « test.bash: line
22: 10160 Processus arrêté sleep 10 » ?



Sans le break, la boucle "while" va faire un tour de plus, et ps sera
appelé sur un processus détruit. D'où le message d'erreur.



J'avais pensé à ça mais je n'arrive pas à reproduire le message d'erreur
en ligne de commandes.

Par exemple, j'ouvre un terminal et dedans je lance « sleep 500 ».
Ensuite, j'ouvre un autre terminal et je fais :

#-----------------------------------------
$ ps -a
PID TTY TIME CMD
10279 pts/1 00:00:00 sleep
10283 pts/0 00:00:00 ps

$ kill -SIGINT 10279; ps 10279
PID TTY STAT TIME COMMAND

$
#-----------------------------------------

J'ai bien détruit le processus 10279 puis j'ai fait un ps sur ce
processus et pourtant je n'ai pas le message d'erreur.


--
François Lafont
Avatar
Luc.Habert.00__arjf
Francois Lafont :

Ce que je voudrais, du coup, c'est interrompre le test s'il dure plus de
5 secondes



J'ai déjà fait ce genre de choses en shell, et j'en ai gardé l'impression
qu'il vaut mieux l'écrire en C.
Avatar
Francois Lafont
Le 02/03/2012 16:11, Luc Habert a écrit :

Ce que je voudrais, du coup, c'est interrompre le test s'il dure plus de
5 secondes



J'ai déjà fait ce genre de choses en shell, et j'en ai gardé l'impression
qu'il vaut mieux l'écrire en C.



Ah mince alors. Je ne connais vraiment pas le C. J'avais bien essayé de
m'y mettre à une époque mais je trouvé ça trop difficile. :-)


--
François Lafont
Avatar
Philippe Naudin
Le ven 02 mar 2012 15:52:40 CET, Francois Lafont a écrit:

Bonjour à tous,

J'explique un peu le contexte d'abord. J'ai un script local qui est
lancé à l'ouverture de session sur une Debian Squeeze et dans ce scri pt
local il y a ça :

#-------------------------------------------
if [ -r "/mnt/script_distant" ]; then
/bin/bash "/mnt/script_distant"
fi
#-------------------------------------------

Je teste si le fichier script_distant est bien accessible en lecture car
en réalité /mnt est un répertoire sur lequel est monté un partage Samba
et il se peut que le serveur Samba soit (momentanément) en carafe et
donc, bien que le montage ait été effectué correctement auparavant, le
fichier script_distant peut être (momentanément) inaccessible.

Mon problème, c'est que ce test dure vraiment longtemps dans le cas où
justement le serveur est en carafe (ça peut prendre une vingtaine de
secondes parfois) ce qui ralentit beaucoup trop l'ouverture de session.
Ce que je voudrais, du coup, c'est interrompre le test s'il dure plus de
5 secondes (par exemple), sachant qu'au delà de cette limite 5 secondes,
je décide que c'est mort pour le lancement du script_distant et le
script local passe à la suite de son travail.

Donc ma question est : comment faire pour interrompre une commande si
elle dure plus de 5 secondes ?



Une question idiote : il faut absolument attendre la fin de
script_distant avant de passer à la suite ? Quelque chose comme :

( [ -r "/mnt/script_distant" ] && /bin/bash "/mnt/script_distant" ) &

ne peut pas faire l'affaire, quitte à le faire suivre d'un sleep 5 si
on est sûr que 5 secondes suffisent lorsque le montage est accessible ?

--
Philippe Naudin
Avatar
Philippe Naudin
Le ven 02 mar 2012 17:45:22 CET, Philippe Naudin a écrit:

...
Une question idiote : il faut absolument attendre la fin de
script_distant avant de passer à la suite ? Quelque chose comme :

( [ -r "/mnt/script_distant" ] && /bin/bash "/mnt/script_distant" ) &

ne peut pas faire l'affaire, quitte à le faire suivre d'un sleep 5 si
on est sûr que 5 secondes suffisent lorsque le montage est accessible ?



Ah tiens, et s'il faut vraiment tuer script_distant :

( [ -r "/mnt/script_distant" ] && /bin/bash "/mnt/script_distant" ) &
pid=$!
sleep 5
ps $pid >& /dev/null && kill -SIGKILL $pid

mais pour le coup on perd quelques secondes si script_distant a bien
fonctionné.

--
Philippe Naudin
Avatar
Francois Lafont
Le 02/03/2012 17:45, Philippe Naudin a écrit :

Une question idiote : il faut absolument attendre la fin de
script_distant avant de passer à la suite ?



Oui, mais ce n'est pas une question idiote.

Quelque chose comme :

( [ -r "/mnt/script_distant" ] && /bin/bash "/mnt/script_distant" ) &

ne peut pas faire l'affaire, quitte à le faire suivre d'un sleep 5 si
on est sûr que 5 secondes suffisent lorsque le montage est accessible ?



En l'occurrence le script local doit se comporter différemment suivant
que script_distant a été interrompu ou non. Du coup, ça ne va pas.


--
François Lafont
Avatar
Fabien LE LEZ
On Fri, 02 Mar 2012 15:52:40 +0100, Francois Lafont
:

"/mnt/script_distant"



À quoi ressemble ce script ? Généralement, dans un programme de
connexion réseau, on peut mettre un timeout.
Avatar
Philippe Naudin
Le ven 02 mar 2012 18:26:42 CET, Francois Lafont a écrit:

Le 02/03/2012 18:02, Philippe Naudin a écrit :

> Ah tiens, et s'il faut vraiment tuer script_distant :
>
> ( [ -r "/mnt/script_distant" ] && /bin/bash "/mnt/script_distant" ) &
> pid=$!
> sleep 5
> ps $pid >& /dev/null && kill -SIGKILL $pid

Oui avec ça on peut agir différemment suivant qu'on a tué le proces sus
ou non.

> mais pour le coup on perd quelques secondes si script_distant a bien
> fonctionné.

Voilà. On prend 5 secondes dans la vue quoi qu'il arrive, alors qu'avec
un serveur qui fonctionne bien (ce qui est le cas la plupart du temps
quand même), le test « [ -r... ] » et l'exécution du script dista nt sont
très rapides (je n'ai pas regardé vraiment mais c'est sûrement moins
d'une seconde).



Dans ce cas, mais ça commence à être gore :
( [ -r "/mnt/script_distant" ] && /bin/bash "/mnt/script_distant" ) &
pid=$!
for x in x x x x x ; do ps $pid >& /dev/null && sleep 1 || break ; done
kill $pid >& /dev/null


--
Philippe Naudin
Avatar
Philippe Naudin
Le ven 02 mar 2012 18:46:50 CET, Fabien LE LEZ a écrit:

On Fri, 02 Mar 2012 15:52:40 +0100, Francois Lafont
:

>"/mnt/script_distant"

À quoi ressemble ce script ? Généralement, dans un programme de
connexion réseau, on peut mettre un timeout.



Je soupçonne que c'est le "[ -r "/mnt/script_distant" ]", et
l'automonteur qui est derrière, qui prend du temps... Si ce
n'est pas le cas, alors oui le script est à revoir.


--
Philippe Naudin
1 2 3