ฉันจะปลุกสคริปนอนหลับได้อย่างไร


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สคริปต์จะหยุดทำงานหลังจากเกิดข้อผิดพลาด เพียงแค่ฆ่าคำสั่ง sleep จะถือว่าเป็นข้อผิดพลาดโดยทุบตี ซึ่งหมายความว่าหากไม่มี-eคำตอบที่ง่ายสำหรับคำถามของคุณ ถ้า-eใช้แล้วมันจะกลายเป็นเรื่องยากมากขึ้นเพราะคุณจะต้องหยุดกระบวนการนอนหลับโดยไม่ฆ่ามัน
kasperd

คำตอบ:


47

เมื่อสคริปต์ Bash ทำงาน a sleepนี่คือpstreeลักษณะที่อาจเป็นดังนี้:

bash(10102)───sleep(8506)

ทั้งสองมี ID กระบวนการ (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กรณีของnuke ที่ทำงานภายใต้ PID นั้น:

pkill -P $(<myscript.pid) sleep

อีกครั้งนี่เป็นการ จำกัด ตัวเองให้sleepกระบวนการทำงานโดยตรงภายใต้หนึ่ง Bash เซสชัน ตราบใดที่ PID ได้รับการบันทึกอย่างถูกต้องสิ่งนี้จะทำให้ปลอดภัยกว่าkillall sleepหรือpkill sleepซึ่งจะทำให้กระบวนการใด ๆ sleepในระบบ (อนุญาตการอนุญาต)

เราสามารถพิสูจน์ทฤษฎีนั้นด้วยตัวอย่างต่อไปนี้ที่ซึ่งเรามีเซสชันการทุบตีสามครั้งแยกกันทำงานสองsleepครั้ง เพียงเพราะเรากำลังระบุ PID ของเซสชั่นทุบตีบนซ้ายเท่านั้นที่sleepจะถูกฆ่า

ป้อนคำอธิบายรูปภาพที่นี่


อีกวิธีหนึ่งคือการผลักsleepเข้าไปในพื้นหลังเก็บ PID ของมันแล้วกลับไปที่พื้นหน้า ในสคริปต์:

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

และเพื่อฆ่ามัน:

kill $(<myscript.sleep.pid)

5

คุณสามารถเขียนสคริปต์เพื่อจัดการ ("กับดัก") สัญญาณอื่น ๆ จาก kill ฯลฯ เพื่อให้คุณสามารถปรับเปลี่ยนพฤติกรรมของสคริปต์ได้ตามต้องการ เห็นคนทุบตี:

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

คุณสามารถฆ่า sleep ซึ่งจะไปยังบรรทัดถัดไปของสคริปต์:

pkill sleep

โปรดทราบว่านี่จะฆ่ากระบวนการสลีปใด ๆ ที่ทำงานในระบบของคุณไม่เพียง แต่ในสคริปต์ของคุณ


1

ฉันมีสคริปต์สควอชนอนโดยเริ่มต้นcronในการบูต สคริปต์ตื่นขึ้นทุกนาทีและตั้งค่าความสว่างหน้าจอแล็ปท็อปตามพระอาทิตย์ขึ้นและพระอาทิตย์ตกจากอินเทอร์เน็ต ขั้นตอนการเปลี่ยนรูปแบบที่ผู้ใช้สามารถกำหนดเองได้ระหว่างความสว่างเต็มและความสลัวแบบเต็มต้องการการเลื่อนขึ้นและการเลื่อนค่าโดย 3, 4, 5 หรืออะไรก็ตามที่ถูกคำนวณทุกนาที

Oli สัมผัสสั้น ๆ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 จำนวนมาก (ID กระบวนการ)

เราสามารถ จำกัด ให้สคริปต์การทำงานของเราแคบลงโดยใช้:

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

ที่เราเห็น:

  • cron เริ่มเชลล์ (กระบวนการ ID 1308 และเซสชัน ID 1308)
  • เชลล์เรียกโปรแกรมของเราที่ทำงานภายใต้กระบวนการ ID 1321 และเซสชัน ID 1308 (จับคู่เชลล์)
  • โปรแกรมของเราเรียกใช้sleepภายใต้รหัสกระบวนการ 26552 และเซสชัน ID 1308 อีกครั้ง

ณ จุดนี้เราสามารถใช้pkill -s 1308และมันจะฆ่าเซสชันทั้งหมดซึ่งรวมถึงเชลล์โปรแกรมdisplay-auto-brightnessและsleepคำสั่งของเรา แต่เราจะใช้kill 26552เพื่อฆ่าคำสั่ง sleep เท่านั้นเพื่อให้โปรแกรมของเราปลุกและปรับความสว่าง

พิมพ์ด้วยตนเองในเทอร์มินัลที่คุณเห็น:

───────────────────────────────────────────────────────────────────────────────
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 วินาที แต่จะสะดวกกว่าสำหรับความสว่างที่จะตั้งค่าทันที

ฉันจะโพสต์รหัส suspend / Resume หลังจากเขียน หวังว่าสุดสัปดาห์นี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.