Comment puis-je réveiller un script de sommeil bash?

26

Est-il possible de réveiller un processus en pause à l'aide de la commande sleep ?

A titre d'exemple, disons que vous avez ce script:

#!/bin/bash
echo "I am tired"
sleep 8h
echo "I am fresh :)"

Après 30 minutes, vous découvrez que le script doit être arrêté, c’est-à-dire que vous souhaitiez plutôt avoir écrit sleep 30m .

Vous ne voulez ni appeler kill PID ni appuyer sur Ctrl + C , car la dernière commande n’est pas exécutée et vous resterez fatigué.

Y a-t-il un moyen de réveiller le processus de sleep ou peut-être d'utiliser une autre commande qui prend en charge le réveil? Les solutions aux processus d’arrière-plan et de premier plan sont les bienvenues.

    
posée Bittenus 20.01.2015 - 10:32
la source

4 réponses

45

Lorsqu'un script Bash exécute sleep , voici à quoi peut ressembler le pstree :

bash(10102)───sleep(8506)

Les deux ont des identifiants de processus (PID), même en tant que script. Si nous voulions interrompre le sommeil, nous enverrions kill 8506 et la session Bash reprendrait ... Le problème est dans un environnement scripté, nous ne connaissons pas le PID de la commande sleep et il n'y a pas de humain à regarder l’arbre de processus.

Nous pouvons obtenir le PID de la session Bash via la variable magique $$ . Si nous pouvons stocker cela quelque part, nous pouvons alors cibler les instances de sleep qui exécutent sous ce PID. Voici ce que j'ai mis dans le script:

# write the current session's PID to file
echo $$ >> myscript.pid

# go to sleep for a long time
sleep 1000

Ensuite, nous pouvons dire à pkill que nuke sleep instances fonctionnant sous ce PID:

pkill -P $(<myscript.pid) sleep

Encore une fois, cela se limite uniquement aux processus sleep exécutés directement sous cette session Bash. Tant que le PID a été enregistré correctement, cela le rend beaucoup plus sûr que killall sleep ou pkill sleep , ce qui pourrait interférer avec tout processus sleep sur le système (autorisations autorisées).

Nous pouvons prouver cette théorie avec l'exemple suivant où nous avons trois sessions bash distinctes, deux exécutant sleep . Seulement parce que nous spécifions le PID de la session bash gauche, seul son sleep est tué.

Une autre approche consiste à pousser sleep en arrière-plan, à stocker son PID et à le replacer au premier plan. Dans le script:

sleep 1000 &
echo $! > myscript.sleep.pid
fg

Et pour le tuer:

kill $(<myscript.sleep.pid)
    
réponse donnée Oli 20.01.2015 - 10:46
la source
5

Vous pouvez écrire votre script pour gérer ("traquer") d’autres signaux provenant de kill etc., de manière à pouvoir modifier le comportement des scripts selon vos besoins. Voir man bash:

SIGNALS
   When  bash  is  interactive,  in the absence of any traps, it ignores SIGTERM (so that kill 0 does not
   kill an interactive shell), and SIGINT is caught and handled (so that the wait builtin  is  interrupt-
   ible).   In all cases, bash ignores SIGQUIT.  If job control is in effect, bash ignores SIGTTIN, SIGT-
   TOU, and SIGTSTP.

   Non-builtin commands run by bash have signal handlers set to the values inherited by  the  shell  from
   its  parent.   When  job  control is not in effect, asynchronous commands ignore SIGINT and SIGQUIT in
   addition to these inherited handlers.  Commands run as a result of  command  substitution  ignore  the
   keyboard-generated job control signals SIGTTIN, SIGTTOU, and SIGTSTP.

   The shell exits by default upon receipt of a SIGHUP.  Before exiting, an interactive shell resends the
   SIGHUP to all jobs, running or stopped.  Stopped jobs are sent SIGCONT to ensure that they receive the
   SIGHUP.   To  prevent the shell from sending the signal to a particular job, it should be removed from
   the jobs table with the disown builtin (see SHELL BUILTIN COMMANDS below) or  marked  to  not  receive
   SIGHUP using disown -h.

   If  the huponexit shell option has been set with shopt, bash sends a SIGHUP to all jobs when an inter-
   active login shell exits.

   If bash is waiting for a command to complete and receives a signal for which a trap has been set,  the
   trap  will not be executed until the command completes.  When bash is waiting for an asynchronous com-
   mand via the wait builtin, the reception of a signal for which a trap has been set will cause the wait
   builtin  to  return immediately with an exit status greater than 128, immediately after which the trap
   is executed.
    
réponse donnée afbach 20.01.2015 - 19:49
la source
4

Vous pourriez simplement tuer le sommeil qui continuerait à la ligne suivante du script:

pkill sleep

Notez que cela supprime tous les processus de veille exécutés sur votre système, pas seulement dans votre script.

    
réponse donnée animaletdesequia 20.01.2015 - 10:47
la source
1

J'ai un script sleep bash démarré par cron au démarrage. Le script se réveille toutes les minutes et définit la luminosité de l'écran de l'ordinateur portable en fonction du lever et du coucher du soleil obtenus à partir d'Internet. Une phase de transition configurable par l'utilisateur entre la pleine luminosité et la saturation complète nécessite un pas en avant et une réduction de valeurs de 3, 4, 5 ou tout ce qui est calculé chaque minute.

Oli a brièvement évoqué pstree dans sa réponse, mais l'a rejeté car cela tuerait toutes les instances de sleep . Cela peut être évité en restreignant la recherche en utilisant les options pstree.

En utilisant pstree -h , nous voyons toute la hiérarchie:

$ pstree -h
systemd─┬─ModemManager─┬─{gdbus}
        │              └─{gmain}
        ├─NetworkManager─┬─dhclient
        │                ├─dnsmasq
        │                ├─{gdbus}
        │                └─{gmain}
        ├─accounts-daemon─┬─{gdbus}
        │                 └─{gmain}
        ├─acpid
        ├─agetty
        ├─atd
        ├─avahi-daemon───avahi-daemon
        ├─cgmanager
        ├─colord─┬─{gdbus}
        │        └─{gmain}
        ├─cron───cron───sh───display-auto-br───sleep
        ├─cups-browsed─┬─{gdbus}
        │              └─{gmain}
        ├─dbus-daemon
        ├─fwupd─┬─3*[{GUsbEventThread}]
        │       ├─{fwupd}
        │       ├─{gdbus}
        │       └─{gmain}
        ├─gnome-keyring-d─┬─{gdbus}
        │                 ├─{gmain}
        │                 └─{timer}
        ├─irqbalance
        ├─lightdm─┬─Xorg───3*[{Xorg}]
        │         ├─lightdm─┬─upstart─┬─at-spi-bus-laun─┬─dbus-daemon
        │         │         │         │                 ├─{dconf worker}
        │         │         │         │                 ├─{gdbus}
        │         │         │         │                 └─{gmain}
        │         │         │         ├─at-spi2-registr─┬─{gdbus}
        │         │         │         │                 └─{gmain}
        │         │         │         ├─bamfdaemon─┬─{dconf worker}
        │         │         │         │            ├─{gdbus}
        │         │         │         │            └─{gmain}
        │         │         │         ├─chrome─┬─2*[cat]
        │         │         │         │        ├─chrome─┬─chrome─┬─2*[chrome─┬─{Chrome_ChildIOT}]
        │         │         │         │        │        │        │           ├─5*[{CompositorTileW}]]
        │         │         │         │        │        │        │           ├─{Compositor}]
        │         │         │         │        │        │        │           ├─{GpuMemoryThread}]
        │         │         │         │        │        │        │           ├─{MemoryInfra}]
        │         │         │         │        │        │        │           ├─{Renderer::FILE}]
        │         │         │         │        │        │        │           ├─{TaskSchedulerRe}]
        │         │         │         │        │        │        │           └─{TaskSchedulerSe}]
        │         │         │         │        │        │        ├─7*[chrome─┬─{Chrome_ChildIOT}]
        │         │         │         │        │        │        │           ├─5*[{CompositorTileW}]]
        │         │         │         │        │        │        │           ├─{Compositor}]
        │         │         │         │        │        │        │           ├─{GpuMemoryThread}]
        │         │         │         │        │        │        │           ├─{MemoryInfra}]
        │         │         │         │        │        │        │           ├─{Renderer::FILE}]
        │         │         │         │        │        │        │           ├─{ScriptStreamerT}]
        │         │         │         │        │        │        │           ├─{TaskSchedulerRe}]
        │         │         │         │        │        │        │           └─{TaskSchedulerSe}]
        │         │         │         │        │        │        ├─chrome─┬─{Chrome_ChildIOT}
        │         │         │         │        │        │        │        ├─5*[{CompositorTileW}]
        │         │         │         │        │        │        │        ├─{Compositor}
        │         │         │         │        │        │        │        ├─{GpuMemoryThread}
        │         │         │         │        │        │        │        ├─{Media}
        │         │         │         │        │        │        │        ├─{MemoryInfra}
        │         │         │         │        │        │        │        ├─{Renderer::FILE}
        │         │         │         │        │        │        │        ├─{ScriptStreamerT}
        │         │         │         │        │        │        │        ├─{TaskSchedulerRe}
        │         │         │         │        │        │        │        └─{TaskSchedulerSe}
        │         │         │         │        │        │        └─2*[chrome─┬─{Chrome_ChildIOT}]
        │         │         │         │        │        │                    ├─5*[{CompositorTileW}]]
        │         │         │         │        │        │                    ├─{Compositor}]
        │         │         │         │        │        │                    ├─{GpuMemoryThread}]
        │         │         │         │        │        │                    ├─{Renderer::FILE}]
        │         │         │         │        │        │                    ├─{ScriptStreamerT}]
        │         │         │         │        │        │                    ├─{TaskSchedulerRe}]
        │         │         │         │        │        │                    └─{TaskSchedulerSe}]
        │         │         │         │        │        └─nacl_helper
        │         │         │         │        ├─chrome─┬─chrome
        │         │         │         │        │        ├─{Chrome_ChildIOT}
        │         │         │         │        │        ├─{MemoryInfra}
        │         │         │         │        │        ├─{TaskSchedulerSe}
        │         │         │         │        │        └─{Watchdog}
        │         │         │         │        ├─{AudioThread}
        │         │         │         │        ├─{BrowserWatchdog}
        │         │         │         │        ├─{Chrome_CacheThr}
        │         │         │         │        ├─{Chrome_DBThread}
        │         │         │         │        ├─{Chrome_FileThre}
        │         │         │         │        ├─{Chrome_FileUser}
        │         │         │         │        ├─{Chrome_HistoryT}
        │         │         │         │        ├─{Chrome_IOThread}
        │         │         │         │        ├─{Chrome_ProcessL}
        │         │         │         │        ├─{Chrome_SyncThre}
        │         │         │         │        ├─{CompositorTileW}
        │         │         │         │        ├─{CrShutdownDetec}
        │         │         │         │        ├─{D-Bus thread}
        │         │         │         │        ├─{Geolocation}
        │         │         │         │        ├─{IndexedDB}
        │         │         │         │        ├─{LevelDBEnv}
        │         │         │         │        ├─{MemoryInfra}
        │         │         │         │        ├─{NetworkChangeNo}
        │         │         │         │        ├─{Networking Priv}
        │         │         │         │        ├─4*[{TaskSchedulerBa}]
        │         │         │         │        ├─6*[{TaskSchedulerFo}]
        │         │         │         │        ├─{TaskSchedulerSe}
        │         │         │         │        ├─{WorkerPool/3166}
        │         │         │         │        ├─{WorkerPool/5824}
        │         │         │         │        ├─{WorkerPool/5898}
        │         │         │         │        ├─{WorkerPool/6601}
        │         │         │         │        ├─{WorkerPool/6603}
        │         │         │         │        ├─{WorkerPool/7313}
        │         │         │         │        ├─{chrome}
        │         │         │         │        ├─{dconf worker}
        │         │         │         │        ├─{extension_crash}
        │         │         │         │        ├─{gdbus}
        │         │         │         │        ├─{gmain}
        │         │         │         │        ├─{gpu-process_cra}
        │         │         │         │        ├─{inotify_reader}
        │         │         │         │        ├─{renderer_crash_}
        │         │         │         │        ├─{sandbox_ipc_thr}
        │         │         │         │        └─{threaded-ml}
        │         │         │         ├─compiz─┬─{dconf worker}
        │         │         │         │        ├─{gdbus}
        │         │         │         │        ├─{gmain}
        │         │         │         │        └─8*[{pool}]
        │         │         │         ├─conky───6*[{conky}]
        │         │         │         ├─2*[dbus-daemon]

( .... many lines deleted to fit in 30k limit .... )

        ├─vnstatd
        ├─whoopsie─┬─{gdbus}
        │          └─{gmain}
        └─wpa_supplicant

Comme vous pouvez le voir, une connexion Ubuntu typique contient de nombreux PID (identifiants de processus).

Nous pouvons le réduire à notre script en cours d'exécution en utilisant:

$ pstree -g -p | grep display-auto
  |-cron(1198,1198)---cron(1257,1198)---sh(1308,1308)---display-auto-br(1321,1308)---sleep(26552,1308)

On voit:

  • cron a démarré un shell (ID processus 1308 et ID session 1308)
  • Le shell appelle notre programme en cours d'exécution sous l'identifiant de processus 1321 et l'ID de session 1308 (correspondant au shell)
  • Notre programme appelle sleep sous l'ID de processus 26552 et à nouveau l'ID de session 1308

A ce stade, nous pouvons utiliser pkill -s 1308 et cela tuerait la session entière qui inclut le shell, notre programme display-auto-brightness et la commande sleep . Au lieu de cela, nous utiliserons kill 26552 pour ne tuer que la commande de sommeil, forçant notre programme à se réveiller et à ajuster la luminosité.

En tapant ceci manuellement dans le terminal que vous voyez:

───────────────────────────────────────────────────────────────────────────────
[email protected]:~$ pstree -g -p | grep display-auto
             |-cron(1198,1198)---cron(1257,1198)---sh(1308,1308)---display-auto-br(1321,1308)---sleep(32362,1308)
───────────────────────────────────────────────────────────────────────────────
[email protected]:~$ sudo kill 32362
───────────────────────────────────────────────────────────────────────────────
[email protected]:~$ pstree -g -p | grep display-auto
             |-cron(1198,1198)---cron(1257,1198)---sh(1308,1308)---display-auto-br(1321,1308)---sleep(1279,1308)
───────────────────────────────────────────────────────────────────────────────
[email protected]:~$ sudo kill 1279
───────────────────────────────────────────────────────────────────────────────
[email protected]:~$ pstree -g -p | grep display-auto
             |-cron(1198,1198)---cron(1257,1198)---sh(1308,1308)---display-auto-br(1321,1308)---sleep(4440,1308)
───────────────────────────────────────────────────────────────────────────────
[email protected]:~$ 

L'étape suivante consiste à le faire lorsque l'ordinateur portable se réveille de suspendre. Par exemple, lorsque le couvercle était fermé, il faisait noir et la luminosité de l'écran était réglée sur "300". Lorsque le couvercle est ouvert, il fait jour et la luminosité doit être réglée sur "2000". Bien sûr, le programme se réveillerait en 1 à 59 secondes, mais il est plus confortable de régler instantanément la luminosité.

Je posterai le code de suspension / reprise après son écriture. Espérons que ce week-end.

    
réponse donnée WinEunuuchs2Unix 23.08.2017 - 03:21
la source

Lire d'autres questions sur les étiquettes