vim 的最新版本引入了该:terminal
命令,它在新的编辑器窗格中启动终端。
有没有办法识别从 vim 启动的这些 shell 与由 xterm/urxvt/gnome-terminal 启动的常规 shell?
答案1
自从Vim 补丁 8.1.049,Vim 确实导出VIM_TERMINAL
了值为 的环境变量v:version
。在此之前,您只能通过获取进程树信息来解决这个问题,或者可能但不是万无一失的通过测试$VIM
和$VIMRUNTIME
环境变量来解决这个问题。
答案2
一般方法ps
您需要调查 shell 的父进程是否是vim
。这在我的 Debian 9 中有效:
pid=1234 # specify PID of the shell in question
ps -o comm= "$(ps -o ppid= "$pid")"
其中ps -o ppid= "$pid"
返回父进程 ID。请注意,如果没有 PID 为 的进程$pid
,则整个命令将变为ps -o comm= ""
无效并抛出错误。
这假设您知道正确的 PID。例如,您可以迭代输出pidof bash
:
for pid in $(pidof bash); do ps -o comm= "$(ps -o ppid= "$pid")" 2>/dev/null; done
从外壳内部
在外壳内本身正确的PID是$$
,因此上述简化为
ps -o comm= "$(ps -o ppid= "$$")" # non-optimal though, see below
但也有$PPID
。它在 shell 初始化期间由 shell 设置为其父进程 ID 的值。因此这应该几乎等同于:
ps -o comm= "$PPID"
几乎,因为一般来说,如果父进程死亡而 shell 存活(这是可能的),那么孤立的 shell 会得到一个新的父进程。我认为这会反映在ps -o ppid= "$$"
而不是echo "$PPID"
。在你的情况下,差异不应该有影响,因为:
- 如果 shell 存活下来,尽管两种方法会产生不同的结果,但结果都不会是这样的
vim
,所以最终的结论无论如何都是“不是 vim 终端”。 - 我希望
vim
在它退出时杀死启动的shell:terminal
(但我目前无法确认这一点),因此上述观点无关紧要。 - 我希望任何交互式 shell 在失去控制终端时都会自行退出;因此,即使之前的预期是错误的,或者只是
vim
被强制终止(因此它无法向其子进程发送信号),shell 仍然会退出。因此,以上几点无关紧要。
因此,我认为可以安全地假设$PPID
在实践中采用和不采用的方法是等效的。
注意,根据您的设置和启动方式vim
,ps -o comm= ...
可能不会返回文字vim
字符串。例如,它可能是vim.basic
,vim.gtk3
或其他内容。