我如何唤醒处于睡眠状态的 bash 脚本?

我如何唤醒处于睡眠状态的 bash 脚本?

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


举个例子,假设你有这个脚本:

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

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

您不想拨打电话kill PID或按Ctrl+ C,因为这样最后一个命令就不会执行,而且您会感到疲倦。

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

答案1

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

bash(10102)───sleep(8506)

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

我们可以通过魔法变量获取 Bash 会话的 PID $$。如果我们可以将其存储在某个地方,那么我们就可以定位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系统上的进程(权限允许)。

我们可以用下面的例子来证明这个理论,我们有三个独立的 bash 会话,其中两个正在运行sleep。因为我们指定了左上角 bash 会话的 PID,所以只有它的会话sleep被终止。

在此处输入图片描述


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

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

并杀死它:

kill $(<myscript.sleep.pid)

答案2

您可以编写脚本来处理(“捕获”)来自 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.

答案3

您可以直接终止睡眠,然后继续执行脚本的下一行:

pkill sleep

请注意,这将终止系统中运行的所有睡眠进程,而不仅仅是脚本中的睡眠进程。

答案4

最简单的方法是中断睡觉脚本中的命令是运行睡觉在后台睡 30 分钟随后是等待命令。bash内置等待' 可以被任何允许脚本管理中断陷阱的信号中断。

#!/bin/bash      
sleep 600 &         
PID=$!      
wait $PID      

什么时候等待被打断你可以杀死睡觉命令使用PID从 bash 中捕获内置$!

相关内容