如何唤醒睡眠中的bash脚本?


27

是否可以唤醒使用sleep命令暂停的进程?


例如,假设您具有以下脚本:

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

30分钟后,您发现需要停止脚本,也就是说,您希望自己编写了该脚本sleep 30m

您不想呼叫kill PID或按Ctrl+ C,因为那样将不会执行最后一个命令,您会很累。

有没有办法从该进程中唤醒,sleep或者是否可以使用另一个支持唤醒的命令?欢迎为后台和前台流程提供解决方案。


13
大吼大叫。
门把手2015年

2
@Doorknobing gawk并没有真正起作用。上一次我进行sleep唱歌的过程pushd是在床上。
imallett 2015年

您的脚本缺少#!一行。这很重要,因为在回答你的问题取决于是否有任何-e#!线。
卡巴斯德(Kasperd)

1
@kasperd完成。出于好奇:-e标志有什么影响?
Bittenus

2
默认情况下,脚本将在错误后继续。如果使用#!/bin/bash -e,脚本将在错误后停止。bash将简单地杀死sleep命令视为错误。这意味着没有-e一个简单的答案可以回答您的问题。如果-e使用了它,那么它将变得更加困难,因为您将需要停止睡眠过程而不杀死它。
卡巴斯德(Kasperd),2015年

Answers:


47

当Bash脚本运行时sleeppstree可能如下所示:

bash(10102)───sleep(8506)

两者都具有进程ID(PID),即使作为脚本运行也是如此。如果我们想中断睡眠,我们将发送kill 8506该消息,然后Bash会话将恢复...问题出在脚本化环境中,我们不知道sleep命令的PID,也没有人去看这个过程树。

我们可以通过$$magic变量获取Bash会话的PID 。如果我们可以将其存储在某个位置,则可以将其实例定位该PID sleep运行。这是我在脚本中输入的内容:

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

# go to sleep for a long time
sleep 1000

然后我们可以告诉在该PID下运行的pkill核武器sleep实例:

pkill -P $(<myscript.pid) sleep

同样,这将自身限制为仅sleep在该Bash会话下直接运行的进程。只要正确记录了PID,这将使其比killall sleep或安全得多pkill sleep,这可能会破坏系统上的任何 sleep进程(允许的权限)。

我们可以通过以下示例证明这一理论,其中有三个单独的bash会话,两个运行sleep。仅仅因为我们指定了左上bash会话的PID,才sleep杀死了它。

在此处输入图片说明


另一种方法是推sleep入后台,存储其PID,然后将其返回到前台。在脚本中:

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

并杀死它:

kill $(<myscript.sleep.pid)

5

您可以编写脚本来处理(“捕获”)来自kill等的其他信号,因此您可以根据需要修改脚本的行为。见男人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在启动时有一个睡眠的bash脚本。该脚本每分钟唤醒一次,并根据从互联网获得的日出和日落设置笔记本电脑的显示亮度。用户在全亮和全暗之间的可配置过渡阶段需要按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在进程ID 26552下再次调用,并在会话ID 1308下再次调用

在这一点上,我们可以使用pkill -s 1308它,它将杀死包括shell,我们的程序display-auto-brightnesssleep命令在内的整个会话。取而代之的是,我们将kill 26552仅使用kill 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秒内自行唤醒,但立即设置亮度会更舒适。

写入后,我将发布暂挂/恢复代码。希望这个周末。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.