这可能是一个简单的问题,但我还没有找到答案。
我想从 shell 脚本启动一个程序,然后稍后再从 shell 脚本关闭它。
一旦程序加载,脚本就会挂起,因为焦点现在位于打开的程序上。
我如何将焦点重新返回到脚本?
答案1
我想从 shell 脚本启动一个程序,然后稍后再从 shell 脚本关闭它。
脚本本质上是顺序的,脚本中执行的任何非内置命令都需要创建单独的进程并等待该进程将控制权返回给脚本。还有一些其他复杂的细节,但这就是 shell 脚本工作原理的基本要点。
现在,您要让脚本启动一个进程并使用相同的脚本关闭该进程。这意味着命令必须独立于脚本(单独的进程)并以某种方式知道该进程是什么。无需过多介绍如何实现此目的的多种方法,最实用的方法是.pid
为命令创建一个文件。
例如,这里有一个脚本可以做这样的事情:
#!/bin/sh
pid_file_exists()[ -f "$1" ]
pid_file='/tmp/mycommand.pid'
# Check if file exists, which may mean the process exists
if pid_file_exists "$pid_file" ; then
pid=$(cat "$pid_file" )
# Replace script with kill command. This will prevent going
# further in the script.
rm "$pid_file"
exec kill $pid
fi
# Save script's PID
echo $$ > "$pid_file"
# Replace script process with zenity, PID now
# is saved and we know it belongs to this command, not script
exec zenity --info "THIS IS A TEST"
如果您在一个终端选项卡中启动脚本,您将看到zenity
实用程序创建的弹出窗口。如果您在另一个选项卡中运行脚本 - 它将关闭该弹出窗口。现在您会注意到脚本在第一个选项卡中保留了对终端的控制。这就是 shell 进程的工作方式。因此,如果您想从同一个终端执行此操作,您可能需要在启动所需应用程序时使用nohup
或setsid
命令来分离脚本。例如,要开始使用
# &>/dev/null hides all output
setsid ./controller_script.sh &>/dev/null
要关闭,您只需执行
./controller_script.sh
还要注意,这里的假设是您只想通过脚本控制应用程序。如果您要控制的应用程序已经退出(通过 GUI 按钮或其他进程关闭),您将收到错误,但仅此而已 - 错误不会造成任何损害。现在,如果该 PID 已经由另一个进程拥有 - 这可能是一个问题,因此如果您要实现真正可移植的东西,您可能还会添加检查,以确定该进程是否真正属于您想要的应用程序,例如通过检查/proc/$pid/cmdline
文件。