web-dev-qa-db-fra.com

script bash pour timer

Je veux écrire un script bash pour exécuter un minuteur pendant 30 secondes. Après 30 secondes, il devrait rester enfoncé pendant 30 secondes. Ce minuteur démarrera de nouveau pendant 30 secondes et continuera ainsi.

for ((i=30; i>0; i--)); do
   sleep 1 &
   print "$i \r"
   wait
done

En utilisant le code ci-dessus, je peux exécuter le chronomètre pendant 30 secondes, mais je dois rester en attente pendant les 30 secondes suivantes, puis à nouveau exécuter le chronomètre pour les 30 prochaines secondes.

Comment puis-je faire ceci?

même chose que je peux faire dans Java en utilisant ce code

import Java.util.Timer;
import Java.util.TimerTask;
public class TestClass {
    static int count = 0;
    public static void main(String[] args)  {
        final TestClass test = new TestClass();
                Timer timer = new Timer();
                timer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        test.doStuff();
                      }
                }, 0, 1000);
    }
    public void doStuff() {
        if (count == 30) {
            try {
                Thread.sleep(30000);
                count = 0;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(++count);
    }
}
1
sourav

Enroulez votre boucle dans une boucle infinie ( c'est-à-dire une boucle while sans conditions), et ajoutez un sleep 30 dans cette boucle externe .

while :
do
    ###  < your
    ###   timer
    ###   here >
    sleep 30
done

Je vous suggère également de supprimer l'instruction wait et le & de "sleep 1 &". De plus, print n'est pas le bon programme pour écrire dans le terminal, utilisez plutôt echo.

while :
do
    for ((i=30; i>0; i--))
    do
       sleep 1 
       echo -n "$i "
    done
    sleep 30
    echo ""
done

Sachez que cette minuterie n’est pas précise, car l’évaluation des instructions de boucle prend un laps de temps (petit, mais non nul). Une solution utilisant date serait préférable: voir par exemple la fonction de compte à rebours ici: https://superuser.com/a/611582 .

3
Nicola Sap

Je pense que vous cherchez quelque chose comme ça:

#!/bin/bash

## Infinite loop
while :; do
        ## Run a sleep command for 30 seconds in the background
        sleep 30 &
        ## $! is the PID of the last backgrounded process, so of the sleep.
        ## Wait for it to finish.
        c=30
        while [[ -e /proc/$! ]]; do
                printf '%s\r' "$(( --c ))"
                ## For more precision, comment the line below. This causes the
                ## script to wait for a second so it doesn't spam your CPU.
                ## If you need accuracy, comment the line out. Although, if you
                ## really need accuracy, don't use the Shell for this.
                sleep 1
        done
done

Vous pouvez également utiliser date:

#!/bin/bash
waitTime=30;
## Infinite loop
while :; do
        startTime=$(date +%s)
        currentTime=$(date +%s)
        c=$waitTime;
        while [[ $((currentTime - startTime)) -lt $waitTime ]]; do
                printf '%s\r' "$(( --c ))"  
                ## For more precision, comment the line below. This causes the
                ## script to wait for a second so it doesn't spam your CPU.
                ## If you need accuracy, comment the line out. Although, if you
                ## really need accuracy, don't use the Shell for this.
                sleep 1
                currentTime=$(date +%s)
        done
        c=0
        echo "";
done

Pour encore plus de précision, ne stockez pas la date dans une variable:

#!/bin/bash
waitTime=4;
while :; do
        startTime=$(date +%s)
        c=$waitTime;
        while [[ $(($(date +%s) - startTime))  -lt $waitTime ]]; do
                printf '%s\r' "$(( --c ))"  
                sleep 1
        done
        c=0
done
1
terdon