web-dev-qa-db-fra.com

Bash: Comment déterminer si un terminal est ouvert par une application tierce

Je veux que mon script bash (en particulier mon ~/.bashrc) ne fasse quelque chose que si le terminal a été ouvert directement par moi, et je fais autre chose s'il était ouvert via une application, par exemple. Code VS Comment puis-je déterminer quel est le cas? Y a-t-il une variable pour cela? Merci d'avance.

9
PaperBag

Vous pouvez probablement le faire en remontant l'ascendance de Shell et en déterminant si elle a été lancée par quelque chose qui équivaut à "vous" ou à un autre programme.

Obtenez le PID (ID de processus) du shell, puis son PPID (ID de processus parent). Continuez jusqu'à ce que vous arriviez à quelque chose qui vous dit d'où ça vient. Vous devrez peut-être expérimenter sur votre système - du moins, je ne sais pas si ce sera universel.

Par exemple, sur mon système, obtenez le PID d'un shell et utilisez ps pour indiquer qu'il s'agit de bash:

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

Obtenez le PPID de 18852:

$ ps -o ppid= -p 18852
18842

Découvrez ce qu'est le PPID (18842):

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

Nous pouvons voir que c'est gnome-terminal, c’est-à-dire la fenêtre émulateur/terminal. C’est peut-être suffisant si votre shell lancé par l’autre programme ne s’exécute pas dans une fenêtre d’émulateur de terminal.

Si cela ne suffit pas, passez à un autre niveau:

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

Cela nous indique que gnome-terminal a été lancé par init. Je pense que votre Shell lancé par un autre programme aura quelque chose de différent là-bas.

10
Mark Smith

En ce qui concerne Visual Studio Code, il existe apparemment un moyen de définir variables d’environnement supplémentaires pour le terminal intégré . Donc, configurez Visual Studio pour utiliser cette configuration:

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

Et dans ~/.bashrc:

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

En général, vous pouvez compter sur l'environnement attribué au processus bash. Par exemple, la variable $TERM et exécutez une branche if..then...else...fi similaire pour [ "$TERM" = "xterm" ] ou quelque chose d'autre. Au cas par cas, vous pouvez étudier les différences d’environnement en exécutant env dans chaque console, enregistrez-le dans le fichier sous env > output_console1.txt et diff output_console1.txt output_console2.txt comme suggéré par dessert dans les commentaires .

9

Si vous parlez d'une application tierce spécifique, utilisez une variable d'environnement. La plupart des programmes transmettent intégralement l'environnement dans leur intégralité lorsqu'ils achètent + exécutent de nouveaux processus.

Donc, démarrez cette application avec une variable personnalisée que vous pouvez vérifier . par exemple. Créez-lui un alias du type alias vs=RUNNING_FROM_VSCODE=1 VSCode, ou créez un script wrapper ressemblant à ceci:

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

Ensuite, dans votre .bashrc, vous pouvez faire

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

Une instruction arithmétique bash (( )) est vraie si l'expression est évaluée à un entier différent de zéro (c'est pourquoi j'ai utilisé 1 ci-dessus). La chaîne vide (pour une variable env non définie) est false. C'est bien pour les variables booléennes bash, mais vous pouvez tout aussi bien utiliser true et le vérifier avec un POSIX traditionnel

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

Si votre application nettoie principalement l'environnement pour ses enfants , mais transmet toujours $PATH sans modification, vous pouvez l'utiliser dans votre enveloppe:

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

et vérifiez-le avec une correspondance de motif comme bash [[ "${PATH%RUNNING_FROM_VSCODE}" != "$PATH" ]] pour vérifier si le fait de supprimer un suffixe de PATH le modifie.

Cela devrait sans danger faire une recherche de répertoire supplémentaire lorsque le programme recherche des commandes externes non trouvées. /dev/null n'est en aucun cas un répertoire sur un système. Vous pouvez donc l'utiliser en tant que répertoire factice qui entraînera rapidement un ENOTDIR si les recherches PATH ne trouvent pas ce qu'elles recherchent dans les entrées PATH précédentes.

2
Peter Cordes

Voici mes 2 cents. Ajoutez-le simplement à votre .bashrc. Remplacez terminals par vos terminaux préférés et la commande export par la vôtre.

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
1
Zalatik