0
votes

Délai d'expiration d'un script bash lorsqu'il n'y a pas de sortie pendant un certain temps

J'ai a.sh qui appelle un b.sh :

. "b.sh" 2>&1 | tee -a "log.txt" &
wait $!

xxx

comment puis-je écrire une condition qui détecte quand b.sh ne produit pas log.txt pendant un certain temps, puis exécuter wait $!


3 commentaires

Que signifie «traverser»? Utilisez une méthode d'interrogation - obtenir la longueur du fichier, attendre une seconde, obtenir la longueur du fichier - si les longueurs sont identiques, cela signifie que rien n'a été produit pendant un certain temps.


C'est risqué. Si b.sh génère un caractère toutes les 15 secondes, il est très probable que tee ne verra aucune donnée pendant plus de 4 heures. (En raison de la mise en mémoire tampon) (Ceci est moins probable si b.sh est un shell et appelle probablement des programmes courts qui écrivent la sortie et se terminent, mais tout à fait une possibilité.) Comment allez-vous gérer cela?


Mais bash interne read s » a une -t option vous pouvez utiliser.


3 Réponses :


0
votes
. "b.sh" 2>&1 | tee -a "log.txt" &
child=$!
# loop while child process exists
while kill -0 "$child" 2>/dev/null; then

     # get first length
     if [[ -z "$len1" ]]; then
          len1=$(wc log.txt)
     fi

     # sleep for a certain time
     sleep 1

     # get length of file after 1 second
     len2=$(wc log.txt)

     # compare lengths
     if [ "$len1" == "$len2" ]; then
         echo "Och my! File log.txt did not change in 1 second"
         break
     else
         echo "All good! File log.txt did change in 1 second"
     fi

     # len1 becomes len2
     len1=$len2;
fi

0 commentaires

2
votes

Vous pourriez faire:

#!/bin/bash


./b.sh 2>&1 | { while read -t 3 line; do
    echo "$line" >> log.txt; done; pkill -g 0; } &

wait $!

Notez que dans votre exemple, votre script n'appelle pas b.sh, mais le sourit. Cette solution appelle b.sh. Cela semble plus propre, car la lecture de la sortie d'un script source est un comportement vraiment étrange.

Mais notez que si b.sh appelle un programme de longue durée qui génère beaucoup de sortie mais le fait lentement, vous rencontrerez sans aucun doute des problèmes de mise en mémoire tampon. Le programme de longue durée mettra très probablement en mémoire tampon sa sortie, donc bien qu'il génère périodiquement des données dans ses tampons internes, la read dans la boucle while ne le verra pas et peut expirer prématurément.


0 commentaires

1
votes

Sujet assez ancien mais j'ai fait un mélange de toutes les solutions suggérées pour répondre à mon besoin et je pense

#!/bin/bash

set -e

rm -rf log.txt

touch log.txt

rm -rf finish

./"b.sh" > log.txt 2>&1 && touch finish &

process_to_keep=$!

{ tail -f log.txt | while read -t 3 line && kill -0 "$process_to_keep" 2>/dev/null; do
    echo "$line"
done;
if [ -e finish ]; then
  echo "finish properly"
else
  if kill -0 "$process_to_keep" 2>/dev/null; then
    echo "no output after 3s"
    kill $process_to_keep 2>/dev/null
  else
    echo "process not alive anymore"
  fi

  exit 1
fi; } &

process_to_wait=$!

wait $process_to_keep
echo "done" >> log.txt
wait $process_to_wait

echo "cleaning temporary files"
rm -rf finish
rm -rf log.txt

Ce script s'arrêtera si le script b se termine à tout moment (sans aucun délai ce qui était le cas avec une autre solution) et il se terminera également s'il n'y a pas de sortie pendant 3s avec un message correct dans la console.

Je pense que cette solution ne fonctionne pas correctement sur macOS.


0 commentaires