Bash: como determinar se o terminal é aberto por um aplicativo de terceiros

9

Eu quero que meu script bash (especificamente meu ~/.bashrc ) faça algo somente se o terminal foi aberto por mim diretamente e faça outra coisa se ele for aberto por meio de um aplicativo, por exemplo, Código VS. Como posso determinar qual é o caso? Existe uma variável para isso? Agradecemos antecipadamente.

    
por PaperBag 01.06.2018 / 22:01

4 respostas

10

Você provavelmente poderia fazê-lo andando de volta pela ancestralidade do shell e descobrindo se ele foi iniciado por algo que equivale a "você" ou outro programa.

Obtenha o PID do shell (ID do processo) e, a partir dele, seu PPID (ID do processo pai). Continue subindo até chegar a algo que lhe diga de onde veio. Você pode precisar experimentar em seu sistema - pelo menos, não sei se será universal.

Por exemplo, no meu sistema, pegue o PID de um shell e use ps para mostrar que é bash :

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

Obtenha o PPID de 18852:

$ ps -o ppid= -p 18852
18842

Descubra o que o PPID (18842) é:

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

Podemos ver que é gnome-terminal, ou seja, a janela do terminal / emulador de terminal. Talvez seja bom o suficiente para você, se o seu shell lançado pelo outro programa não estiver sendo executado em uma janela do emulador de terminal.

Se não for bom o suficiente, suba outro nível:

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

Isso nos diz que gnome-terminal foi iniciado por init . Eu suspeito que seu shell iniciado por outro programa terá algo diferente lá.

    
por Mark Smith 01.06.2018 / 23:14
9

Com relação ao código do Visual Studio, aparentemente há uma maneira de definir ambiente adicional variáveis para o terminal integrado . Então, configure o Visual Studio para usar essa configuração:

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

E dentro de ~/.bashrc :

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

Em geral, você pode confiar no ambiente dado ao processo bash . Por exemplo, a variável $TERM , e execute uma ramificação if..then...else...fi semelhante para [ "$TERM" = "xterm" ] ou outra coisa . Em uma base caso a caso, você pode investigar as diferenças no ambiente executando env em cada console, salvar no arquivo como em env > output_console1.txt e diff output_console1.txt output_console2.txt como sugerido por desser nos comentários .

    
por Sergiy Kolodyazhnyy 01.06.2018 / 23:56
2

Se você estiver falando sobre um aplicativo de terceiros específico, use uma variável de ambiente. A maioria dos programas transmitirá todo o ambiente inalterado quando forçar + executar novos processos.

Então, inicie este aplicativo com um env env personalizado que você pode verificar por . por exemplo. crie um alias para ele como alias vs=RUNNING_FROM_VSCODE=1 VSCode ou crie um script de wrapper assim:

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

Em seguida, no seu .bashrc , você pode fazer

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

Uma instrução aritmética bash (( )) é verdadeira se a expressão for avaliada como um inteiro diferente de zero (é por isso que usei 1 acima). A string vazia (para uns unset env var) é falsa. É bom para variáveis basean booleanas, mas você poderia facilmente usar true e verificar isso com um POSIX tradicional

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

Se o seu aplicativo limpar principalmente o ambiente de seus filhos , mas ainda transmitir $PATH inalterado, você poderá usá-lo em seu wrapper:

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

e verifique se há uma correspondência de padrão como bash [[ "${PATH%RUNNING_FROM_VSCODE}" != "$PATH" ]] para verificar se a remoção de um sufixo do PATH a altera.

Isso deve fazer uma pesquisa de diretório extra quando o programa estiver procurando por comandos externos não encontrados. O /dev/null definitivamente não é um diretório em nenhum sistema, portanto, é seguro usá-lo como um diretório falso que resultará rapidamente em ENOTDIR se as pesquisas PATH não encontrarem o que estão procurando nas entradas anteriores do PATH.

    
por Peter Cordes 02.06.2018 / 15:19
1

Aqui estão meus 2 centavos. Basta adicioná-lo ao seu .bashrc . Substitua terminals pelos seus terminais favoritos e o comando export pelo seu.

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
    
por Zalatik 02.06.2018 / 00:05