Bagaimana saya bisa membangunkan skrip bash yang sedang tidur?

27

Apakah mungkin untuk membangunkan proses yang dijeda menggunakan sleepperintah?


Sebagai contoh, katakanlah Anda memiliki skrip ini:

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

Setelah 30 menit Anda menemukan bahwa Anda memerlukan script untuk berhenti, yaitu, Anda berharap telah menulis sleep 30msebagai gantinya.

Anda tidak ingin memanggil kill PIDatau menekan Ctrl+ C, karena perintah terakhir tidak dijalankan dan Anda akan tetap lelah.

Apakah ada cara untuk membangunkan proses dari sleepatau mungkin menggunakan perintah lain yang mendukung wakeup? Solusi untuk proses latar belakang dan latar depan dipersilakan.

Bittenus
sumber
13
Berteriaklah dengan sangat keras.
Gagang pintu
2
@ Kerja sama gawksekali tidak bekerja. Terakhir kali saya memiliki sleepproses, saya pushdturun dari tempat tidur.
Imallett
Script Anda kehilangan satu #!baris. Dan itu penting karena jawaban untuk pertanyaan Anda tergantung pada apakah ada -eyang #!sesuai.
kasperd
1
@kasperd Selesai. Karena penasaran: pengaruh apa yang dimiliki bendera -e?
Bittenus
2
Secara default, skrip akan dilanjutkan setelah kesalahan. Jika Anda menggunakan #!/bin/bash -e, skrip akan berhenti setelah kesalahan. Cukup membunuh perintah tidur akan diperlakukan sebagai kesalahan oleh bash. Itu berarti tanpa -eada jawaban yang cukup sederhana untuk pertanyaan Anda. Jika -edigunakan, maka itu menjadi jauh lebih sulit karena Anda harus menghentikan proses tidur tanpa membunuhnya.
kasperd

Jawaban:

47

Saat skrip Bash menjalankan sleep, inilah yang pstreeakan terlihat seperti:

bash(10102)───sleep(8506)

Keduanya memiliki ID proses (PID), bahkan saat dijalankan sebagai skrip. Jika kami ingin mengganggu tidur, kami akan mengirim kill 8506dan sesi Bash akan dilanjutkan ... Masalahnya adalah di lingkungan yang dituliskan skrip kami tidak tahu PID dari sleepperintah dan tidak ada manusia untuk melihat prosesnya pohon.

Kita bisa mendapatkan PID dari sesi Bash melalui $$variabel ajaib. Jika kita dapat menyimpannya di suatu tempat, kita dapat menargetkan contoh sleepyang berjalan di bawah PID itu. Inilah yang saya masukkan ke dalam skrip:

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

# go to sleep for a long time
sleep 1000

Dan kemudian kita bisa mengatakan pkillkepada sleepcontoh nuklir yang menjalankan di bawah PID itu:

pkill -P $(<myscript.pid) sleep

Sekali lagi, ini membatasi dirinya hanya untuk sleepproses yang berjalan langsung di bawah satu sesi Bash. Selama PID dicatat dengan benar, ini membuatnya jauh lebih aman daripada killall sleepatau pkill sleep, yang dapat membatalkan proses apa pun sleep pada sistem (izin memungkinkan).

Kita dapat membuktikan teori itu dengan contoh berikut di mana kita memiliki tiga sesi bash terpisah, dua running sleep. Hanya karena kami menetapkan PID dari sesi bash kiri atas, hanya sleepitu yang terbunuh.

masukkan deskripsi gambar di sini


Pendekatan alternatif adalah mendorong sleepke latar belakang, menyimpan PID dan kemudian mengembalikannya ke latar depan. Dalam skrip:

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

Dan untuk membunuhnya:

kill $(<myscript.sleep.pid)
Oli
sumber
5

Anda dapat menulis skrip Anda untuk menangani ("menjebak") sinyal lain dari kill dll sehingga Anda dapat memodifikasi perilaku skrip sesuai kebutuhan. Lihat bash man:

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.
afbach
sumber
4

Anda bisa mematikan tidur yang akan berlanjut ke baris script berikutnya:

pkill sleep

Perhatikan bahwa ini akan membunuh proses tidur yang berjalan di sistem Anda, tidak hanya di skrip Anda.

animaletdesequia
sumber
1

Saya memiliki skrip bash tidur yang dimulai cronsaat boot. Script bangun setiap menit dan mengatur kecerahan tampilan laptop berdasarkan matahari terbit dan terbenam yang diperoleh dari internet. Fase transisi yang dapat dikonfigurasi pengguna antara kecerahan penuh dan redup penuh memerlukan peningkatan dan penurunan nilai sebesar 3, 4, 5 atau apa pun yang dihitung setiap menit.

Oli dengan singkat menyinggung pstreejawabannya tetapi menolaknya karena itu akan membunuh semua sleepcontoh. Ini dapat dihindari dengan mempersempit pencarian menggunakan opsi pstree.

Dengan menggunakan pstree -hkita melihat seluruh heirarki:

$ 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

Seperti yang Anda lihat login khas Ubuntu berisi banyak PID (ID Proses).

Kami dapat mempersempitnya ke skrip kami yang sedang berjalan menggunakan:

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

Kami melihat:

  • cron memulai sebuah shell (ID proses 1308 dan sesi ID 1308)
  • Shell memanggil program kami berjalan di bawah ID proses 1321 dan sesi ID 1308 (cocok dengan shell)
  • Program kami memanggil sleepdalam ID proses 26552 dan lagi sesi ID 1308

Pada titik ini kita dapat menggunakan pkill -s 1308dan itu akan mematikan seluruh sesi yang meliputi shell, program kita display-auto-brightnessdan sleepperintah. Sebagai gantinya kita akan menggunakan kill 26552hanya untuk membunuh perintah tidur memaksa program kita untuk bangun dan menyesuaikan kecerahan.

Mengetik ini secara manual di terminal yang Anda lihat:

───────────────────────────────────────────────────────────────────────────────
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:~$ 

Langkah selanjutnya adalah melakukannya ketika laptop bangun dari menangguhkan. Misalnya ketika tutupnya tertutup, layarnya gelap gulita dan kecerahan layar ditetapkan "300". Ketika tutup dibuka itu siang hari dan kecerahan perlu diatur ke "2000". Tentu saja program akan bangun sendiri dalam 1 hingga 59 detik tetapi lebih nyaman untuk kecerahan diatur secara instan.

Saya akan memposting kode penangguhan / resume setelah ditulis. Semoga akhir pekan ini.

WinEunuuchs2Unix
sumber