我经常在工作时播放一些儿童节目。为此,我需要将屏幕扩展到电视、更改音频接收器等。并将 mplayer 窗口从主屏幕移动到所需屏幕 + 使该窗口固定。我知道如何做所有这些,我可以编写该脚本。但要做到这一切,我需要刚刚执行的 MPlayer 的 PID。但是,如果我从 bash 脚本内部运行 MPlayer,mplayer ... &
我可以通过获取 PID $!
,但脚本结束时我将失去控制 mplayer 的能力。我知道可以通过-slave
选项执行 mplayer,但我想以与正常启动 MPlayer 相同的方式控制它。
是否有人知道如何在 bash 脚本中调用 MPlayer,能够获取它的 PID,并且能够在脚本结束时通过正常的 MPlayer 控制台交互来控制 MPlayer?
我也愿意接受其他解决方案,但本质上我需要先以某种方式启动 mplayer,然后获取它的 PID 以便能够运行 pacmd 和 wmctrl 命令,并且所有这些都不会改变执行的 mplayer 的行为。
答案1
下面的脚本执行以下步骤:
- 保存原始 stdin 以供日后使用。在您的用例中,它很可能指向终端。
- 将 stdin 从 重定向
/dev/null
,因此默认情况下没有进程(包括未来的子进程)使用原始进程。请注意,/dev/tty
直接访问(例如sudo
要求输入密码)的进程仍可能会产生干扰。 - 在后台运行
mplayer
,并将 stdin 重定向到原始 stdin。这样它就成为唯一使用它的进程。命令行参数按原样传递。 - 等待正确的窗口出现。
- 做你想做的事。
- 等待
mplayer
退出。
如果mplayer
提前退出,那么脚本将永远不会超越“等待正确的窗口”。因此,最好在后台的子 shell 中执行几个步骤。mplayer
退出时,主脚本不应让子 shell 存活。
如果启用了作业控制,该脚本将出现错误,因此不要从具有作业控制的 shell 中获取它。如果获取它,它也可能kill
超出您的预期。您应该将脚本作为独立可执行文件运行。
#!/bin/bash
trap 'kill 0' EXIT # do not let children survive
manage_mp() {
# wait for window to appear
until wmctrl -lp | grep -q '\b'"$mppid"'\b.*\bMPlayer\b'; do sleep 1; done
# do whatever you want to do; the PID is in $mppid in case you lose $!
# test line below
wmctrl -r MPlayer -b add,above
}
exec 17<&0 # save stdin
exec 0</dev/null # redirect stdin, so the original is not used
<&17 mplayer "$@" & # run mplayer in background
mppid="$!"
manage_mp &
wait "$mppid" # wait for mplayer