Bash:如何确定第三方应用程序是否打开了终端


9

我希望bash脚本(特别是my ~/.bashrc)仅在终端由我直接打开时才执行某些操作,而在通过诸如VS Code之类的应用程序打开时则执行其他操作。如何确定情况如何?有一个变量吗?提前致谢。


1
有一种方法,我的第一个答复是在askubuntu.com/a/1042727/295286找到第二个示例 。尝试打开VS并运行env命令。看看是否有我们可以使用的特定于VS的变量。
Sergiy Kolodyazhnyy

1
如果什么都没有,请尝试另一种方法:查看终端仿真器是否设置了变量。我使用yakuake了变量PULSE_PROP_OVERRIDE_application.name=Yakuake集,并在我的机器上进行了xterm设置XTERM_VERSION=XTerm(322)
甜点

@SergiyKolodyazhnyy您能为环境变量方法写一个答案吗?
甜点

@dessert我愿意,但是我没有安装VS,如果有任何特定的环境变量可以锁住,那么OP都没有响应。
Sergiy Kolodyazhnyy

@SergiyKolodyazhnyy我也没有,但是问题标题说的是第三方应用程序,我想它就像任何终端仿真器一样工作–我认为像env >env_term1在一个仿真器中,env >env_term2在第二个仿真器中那样回答以及如何使用diff env_term{1,2}所说的内容非常有用。毕竟,OP说例如 VS Code
甜点

Answers:


10

您可能可以通过返回外壳的祖先并确定它是由等同于“您”的东西还是另一个程序启动来实现的。

获取外壳的PID(进程ID),并从中获取其PPID(父进程ID)。一直往前走,直到找到告诉你它来自哪里的东西。您可能需要在系统上进行试验-至少,我不知道它是否会通用。

例如,在我的系统上,获取外壳的PID并ps用来表明它是bash

$ echo $$
18852
$ ps --pid 18852
  PID TTY          TIME CMD
18852 pts/1    00:00:00 bash

取得18852的PPID:

$ ps -o ppid= -p 18852
18842

找出什么是PPID(18842):

$ ps --pid 18842
  PID TTY          TIME CMD
18842 ?        00:00:02 gnome-terminal

我们可以看到它是gnome-terminal,即终端仿真器/终端窗口。如果其他程序启动的外壳未在终端仿真器窗口中运行,那么这对您来说已经足够了。

如果不够好,请再上一个级别:

$ ps -o ppid= -p 18842
 2313
$ ps --pid 2313
  PID TTY          TIME CMD
 2313 ?        00:00:00 init

这告诉我们这gnome-terminal是从始init。我怀疑您的另一个程序启动的shell那里会有什么不同。


...或者也许是通过走pstree -s $$
钢缆车

9
“这告诉我们gnome-terminal是由init启动的。”我发现init不太可能启动终端窗口。相反,无论启动了什么,gnome-terminal都会死亡,并且gnome-terminal被重新绑定到init。检查gnome终端,似乎是双叉。因此,当它执行时,它会首先派生自己并杀死原始进程,并继续执行新进程。
JoL

@JoL公平点。该init过程不是pid 1,但不确定是否会改变任何东西。
卡巴斯德(Kasperd),

非常感谢!我能够检测到VS Code和Eclipse都不以的子代身份运行终端gnome-terminal。我在下面执行了命令if [ $(pstree -s $$ | grep "gnome-terminal" -c) -gt 0 ]; then ...,它起作用了。
PaperBag

9

就Visual Studio Code而言,显然有一种方法可以为集成终端设置其他环境变量。因此,将Visual Studio设置为使用此配置:

"terminal.integrated.env.linux": {
  "visual_studio": "true"
}

~/.bashrc

if [ -n "$visual_studio" ]; then
    # do something for Visual Studio
else
    # do something else for other types of terminal
fi

通常,您可以依靠为bash过程提供的环境。例如,$TERM变量,并运行一个类似的if..then...else...fi分支[ "$TERM" = "xterm" ]或别的东西。根据具体情况,您可以通过env在每个控制台中运行来调查环境中的差异,将其保存为文件中的内容env > output_console1.txt,并diff output_console1.txt output_console2.txt按照注释中甜点的说明进行保存。


$Env:var不是Bash中环境变量的语法。在我看来,这就像是Powershell的事情。
Dietrich Epp

@DietrichEpp是的,我最初是在研究在Visual Studio中设置其他环境变量的方法,但忽略了答案是使用PowerShell。这样$foo就足够了。咖啡可能还不够。
Sergiy Kolodyazhnyy

对于没有环境设置的第三方程序的一般情况,您可以运行该程序之前在包装器中设置自定义环境变量。看我的回答
彼得·科德斯

2

如果您在谈论一个特定的第三方应用程序,请使用环境变量。当大多数程序派生并执行新进程时,它们将在整个环境中保持不变。

因此,请使用您可以检查的自定义环境变量启动此应用。例如,为其创建一个别名,例如alias vs=RUNNING_FROM_VSCODE=1 VSCode,或创建一个包装脚本,如下所示:

#!/bin/sh
export RUNNING_FROM_VSCODE=1
exec VSCode "$@"

然后.bashrc,您可以

if (($RUNNING_FROM_VSCODE)); then
   echo "started from inside VSCode"
   # RUNNING_FROM_VSCODE=0  # optional if you only want the immediate child
fi

(( ))如果表达式的计算结果为非零整数,则bash算术语句为true(这就是我在1上面使用的原因)。空字符串(对于未设置的环境变量)为false。对于bash布尔变量很不错,但是您可以像使用true传统POSIX 一样轻松地使用和检查它

if [ "x$RUNNING_FROM_VSCODE" = "xtrue" ]; then
   echo "started from inside VSCode"
fi

如果您的应用程序主要清除了其子级环境,但仍然$PATH保持不变,则可以在包装器中使用它:

#!/bin/sh
export PATH="$PATH:/dev/null/RUNNING_FROM_VSCODE"
exec VSCode "$@"

并使用bash之类的模式匹配[[ "${PATH%RUNNING_FROM_VSCODE}" != "$PATH" ]]进行检查,以检查是否从PATH中删除后缀会改变它。

当程序正在寻找找不到的外部命令时,这应该无害地进行一次额外的目录查找。 /dev/null绝对不是任何系统上的目录,因此可以安全地用作伪目录,ENOTDIR如果PATH搜索在较早的PATH条目中找不到所需的内容,该目录将很快生成。


包装脚本通常是明智的选择,因此+1。唯一的次要缺点是,如果您有3个程序,则可能需要3个包装脚本或一个包含3个不同args的包装脚本,这可能会很乏味。尽管如此,这是一个可靠的方法。
Sergiy Kolodyazhnyy

1

这是我的2美分。只需将其添加到您的中即可.bashrcterminals用您喜欢的终端替换,并用您的终端export命令。

run_in_terminal(){
  local parent_command="$(ps --no-headers --pid $PPID -o command | awk '{print $1;}')"
  local parent="$(basename $parent_command)"
  local terminals=( gnome-terminal st xterm ) # list your favorite terminal here
  if [[ ${terminals[*]} =~ ${parent} ]]; then
    # Your commands to run if in terminal
    export MY_VAR_IN_TERMINAL="test"
  fi
}
run_in_terminal

这不适用于gnome-terminal的服务器-客户端模型。
egmont
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.