Як я можу розбудити сценарій сну?


27

Чи можливо пробудити процес, який призупинено за допомогою sleepкоманди?


Як приклад, скажімо, у вас є цей сценарій:

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

Через 30 хвилин ви виявите, що потрібен сценарій для припинення, тобто ви хотіли, щоб ви написали sleep 30mнатомість.

Ви не хочете ні дзвонити, kill PIDні натискати Ctrl+ C, оскільки тоді остання команда не виконується, і ви будете втомлені.

Чи є спосіб вивести процес з sleepабо, можливо, використовувати іншу команду, яка підтримує пробудження? Вітаються рішення як для фонових процесів, так і для переднього плану.


13
Кричати на це дійсно голосно.
Doorknob

2
@Doorknob gawking насправді не працює. Востаннє у мене був sleepпроцес, я pushdйого зняв з ліжка.
imallett

У вашому сценарії відсутній #!рядок. І це важливо, тому що відповідь на ваше запитання залежить від того, чи є -eв #!рядку.
kasperd

1
@kasperd Готово. З цікавості: який вплив має прапор -e?
Bittenus

2
За замовчуванням сценарій продовжується після помилки. Якщо ви користуєтесь #!/bin/bash -e, скрипт припиняється після помилки. Просто вбивство команди сну трактуватиметься як помилка bash. Це означає, що без -eвашої запитання є досить проста відповідь. Якщо -eйого використовували, то це стає набагато складніше, тому що вам потрібно буде зупинити процес сну, не вбиваючи його.
kasperd

Відповіді:


47

Коли використовується сценарій Bash sleep, ось, як це pstreeможе виглядати:

bash(10102)───sleep(8506)

Обидва мають ідентифікатори процесу (PID), навіть коли вони працюють як сценарій. Якби ми хотіли перервати сон, ми надішлемо, kill 8506і сеанс Bash відновиться ... Проблема полягає в сценарії, в якому ми не знаємо, PID sleepкоманди і не існує людини, яка б дивилася на процес дерево.

Ми можемо отримати PID сесії Bash через $$магічну змінну. Якщо ми можемо зберігати це десь, ми можемо націлити на екземпляри sleep, які працюють під цим PID. Ось що я ставлю в сценарій:

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

# go to sleep for a long time
sleep 1000

І тоді ми можемо сказати pkillнукерувати sleepекземпляри, що працюють під цим PID:

pkill -P $(<myscript.pid) sleep

Знову ж таки, це обмежується лише sleepпроцесами, що працюють безпосередньо під одним сеансом Bash. Поки PID був зареєстрований правильно, це робить його набагато безпечнішим, ніж killall sleepабо pkill sleep, що може зашкодити будь-якому sleep процесу в системі (дозволи дозволяють).

Ми можемо довести цю теорію на наступному прикладі, коли у нас є три окремих баш-сесії, два запущені sleep. Тільки тому, що ми вказуємо PID верхнього лівого сеансу bash, лише його sleepвбивається.

введіть тут опис зображення


Альтернативний підхід - відсунути sleepна другий план, зберегти його PID та повернути його на перший план. У сценарії:

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

І вбити його:

kill $(<myscript.sleep.pid)

5

Ви можете написати свій сценарій для обробки ("пастки") інших сигналів від вбити тощо, щоб ви могли змінити поведінку сценаріїв за потреби. Дивіться 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.

4

Ви можете просто вбити сон, який продовжуватиметься до наступного рядка сценарію:

pkill sleep

Зауважте, що це знищить будь-який процес сну, який працює у вашій системі, а не лише у вашому сценарії.


1

У мене є сценарій сплячого баш-програми, запущений під час cronзавантаження. Сценарій прокидається щохвилини і встановлює яскравість дисплея ноутбука на основі сходу та заходу, отриманого з Інтернету. Фаза переходу, налаштована користувачем між повним яскравим та повним затемненням, вимагає посилення та зменшення значень на 3, 4, 5 або що-небудь, що обчислюється щохвилини.

Олі коротко торкнувся pstreeсвоєї відповіді, але відхилив її, бо це вбило б усі sleepвипадки. Цього можна уникнути, звузивши пошук, використовуючи параметри pstree.

Використовуючи pstree -hми бачимо всю герархію:

$ 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

Як ви бачите, типовий логін Ubuntu містить безліч PID (ідентифікаторів процесу).

Ми можемо звузити його до нашого запущеного сценарію, використовуючи:

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

Ми бачимо:

  • cron запустив оболонку (ідентифікатор процесу 1308 та ідентифікатор сеансу 1308)
  • Оболонка викликає нашу програму, що працює під ідентифікатором процесу 1321 та ідентифікатором сеансу 1308 (відповідає оболонці)
  • Наша програма дзвонить sleepпід ідентифікатором процесу 26552 і знову ідентифікатором сеансу 1308

На даний момент ми можемо використовувати, pkill -s 1308і це знищило б весь сеанс, що включає оболонку, нашу програму display-auto-brightnessта sleepкоманду. Натомість ми будемо використовувати kill 26552лише для введення команди сну, змушуючи нашу програму прокинутися і регулювати яскравість.

Введіть це вручну в термінал, який ви бачите:

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

Наступний крок - це зробити, коли ноутбук прокинеться від призупинення. Наприклад, коли кришка закрилася, вона була повна темна, а яскравість екрана була встановлена ​​на "300". Коли кришка відкрита, денне світло і яскравість потрібно встановити на "2000". Звичайно, програма прокинеться самостійно за 1 до 59 секунд, але зручніше яскравість встановлювати миттєво.

Я опублікую код призупинення / відновлення після написання. Сподіваємось, ці вихідні.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.