如何唤醒休眠的 bash 脚本?

Bit*_*nus 27 command-line bash

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


例如,假设您有这个脚本:

#!/bin/bash
echo "I am tired"
sleep 8h
echo "I am fresh :)"
Run Code Online (Sandbox Code Playgroud)

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

你不想打电话kill PID或按Ctrl+ C,因为最后一个命令不会执行,你会很累。

有没有办法唤醒进程sleep或使用另一个支持唤醒的命令?欢迎后台和前台进程的解决方案。

Oli*_*Oli 49

当 Bash 脚本运行 时sleep,它pstree可能会如下所示:

bash(10102)???sleep(8506)
Run Code Online (Sandbox Code Playgroud)

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

我们可以通过$$magic变量得到Bash会话的PID 。如果我们可以将它存储在某个地方,那么我们就可以定位该 PIDsleep运行的实例。这是我在脚本中添加的内容:

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

# go to sleep for a long time
sleep 1000
Run Code Online (Sandbox Code Playgroud)

然后我们可以告诉pkillnukesleep在该 PID 下运行的实例:

pkill -P $(<myscript.pid) sleep
Run Code Online (Sandbox Code Playgroud)

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

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

在此处输入图片说明


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

sleep 1000 &
echo $! > myscript.sleep.pid
fg
Run Code Online (Sandbox Code Playgroud)

并杀死它:

kill $(<myscript.sleep.pid)
Run Code Online (Sandbox Code Playgroud)


afb*_*ach 5

您可以编写脚本来处理(“陷阱”)来自 kill 等的其他信号,以便您可以根据需要修改脚本行为。参见 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.
Run Code Online (Sandbox Code Playgroud)