Bash: Terminalin üçüncü taraf uygulaması tarafından açılıp açılmadığı nasıl belirlenir


9

Benim bash betiğimi (özellikle benim ~/.bashrc) sadece terminal doğrudan benim tarafımdan açılmışsa bir şey yapmasını ve bir uygulama örneğin VS Kodu ile açılmışsa başka bir şey yapmasını istiyorum. Davanın ne olduğunu nasıl belirleyebilirim? Bunun için bir değişken var mı? Şimdiden teşekkürler.


1
Bunun bir yolu var, ilk cevabım askubuntu.com/a/1042727/295286 adresindeki ikinci örnekle gitmek olacaktır . VS'yi açmayı ve envkomutu çalıştırmayı deneyin . Kullanabileceğimiz VS'ye özgü bir değişken olup olmadığına bakın.
Sergiy Kolodyazhnyy

1
Hiçbir şey yoksa, tersini deneyin: Terminal öykünücünüzün bir değişken ayarlayıp ayarlamadığını görün. Kullandığım yakuakeve değişken olması PULSE_PROP_OVERRIDE_application.name=Yakuakeseti ve xtermsetleri XTERM_VERSION=XTerm(322)benim makinede.
tatlı

@SergiyKolodyazhnyy Çevre değişkeni yaklaşımı için bir cevap yazabilir misiniz lütfen?
tatlı

@ tatlı yapardım, ama VS yüklü değil, kilitlenebileceğimiz belirli bir ortam değişkeni varsa, OP de yanıt vermedi.
Sergiy Kolodyazhnyy

@SergiyKolodyazhnyy Bende yok, ama soru başlığı üçüncü taraf uygulaması diyor ve sanırım herhangi bir terminal emülatörü gibi çalışıyor - sanırım bir env >env_term1emülatörde, env >env_term2ikinci birde ve nasıl diff env_term{1,2}faydalı olduğunu söyleyen bir cevap nasıl kullanacağını düşünüyorum . Ne de olsa OP diyor, örneğin VS Code .
tatlı

Yanıtlar:


10

Muhtemelen kabuğun soyuna geri dönüp "siz" ya da başka bir programa denk gelen bir şey tarafından başlatılıp başlatılmadığını öğrenerek yapabilirsiniz.

Kabuğun PID'sini (işlem kimliği) ve bundan PPID'sini (üst işlem kimliği) alın. Size nereden geldiğini söyleyen bir şeye ulaşıncaya kadar devam edin. Sisteminizi denemeniz gerekebilir - en azından evrensel olup olmayacağını bilmiyorum.

Örneğin, sistemimde, bir kabuğun PID'sini alın ve psbunun olduğunu göstermek için kullanın bash:

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

18852 PPID'sini alın:

$ ps -o ppid= -p 18852
18842

PPID'nin (18842) ne olduğunu öğrenin:

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

Gnome-terminalini, yani terminal emülatörü / terminal penceresini görebiliriz. Diğer program tarafından başlatılan kabuğunuz bir terminal öykünücü penceresinde çalışmıyorsa, bu sizin için yeterince iyi olabilir.

Yeterince iyi değilse, başka bir seviyeye çıkın:

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

Bu bize bunun gnome-terminalbaşladığını söyler init. Ben başka bir program tarafından başlatılan kabuk orada farklı bir şey olacak şüpheli.


... ya da belki sonucupstree -s $$
steeldriver

9
"Bu bize gnome-terminalinin init tarafından başlatıldığını söyler" init'in terminal pencerelerini başlatması pek mümkün değil. Aksine, gnome-terminali başlamış olan her şey öldü ve gnome-terminali yeniden başlatılmak üzere yeniden eğitildi. Gnome terminalini kontrol etmek, çift çatal gibi görünüyor. Böylece, yürütüldüğünde, önce kendini çatallar ve orijinal süreci öldürür, yenisine devam eder.
JoL

@JoL Adil nokta. Bu initsüreç pid 1 olsa da, bunun bir şey değiştirip değiştirmeyeceğinden emin değilim.
kasperd

Çok teşekkürler! Ne VS Kodu ne de Eclipse terminali bir çocuk olarak çalıştırmak olduğunu tespit edebildi gnome-terminal. Komutumu altında yerine getirdim if [ $(pstree -s $$ | grep "gnome-terminal" -c) -gt 0 ]; then ...ve işe yaradı.
PaperBag

9

Visual Studio Code'a gelince, görünüşe göre entegre terminal için ek ortam değişkenleri ayarlamanın bir yolu var . Bu nedenle, Visual Studio'yu bu yapılandırmayı kullanacak şekilde ayarlayın:

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

Ve içinde ~/.bashrc:

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

Genel olarak, bashsürece verilen çevreye güvenebilirsiniz . Örneğin , $TERMdeğişken , ve benzer bir if..then...else...fişube için çalıştırın [ "$TERM" = "xterm" ]veya başka bir şey. Harf için ayrı ayrı, çalıştırmakta yoluyla çevredeki farklılıkları araştırabilir envgibi dosyaya bu tasarruf, her konsolda env > output_console1.txtve diff output_console1.txt output_console2.txtönerdiği gibi yorumlarında tatlı .


$Env:varBash içindeki ortam değişkenlerinin sözdizimi değildir. Bu benim için bir Powershell meselesine benziyor.
Dietrich Epp

@DietrichEpp Evet, aslında Visual Studio'da ek ortam değişkenleri belirlemenin yollarını araştırıyordum, ancak cevapların PowerShell kullandığını göz ardı ettim. Bu $fookadar yeter. Kahve muhtemelen yeterli değil.
Sergiy Kolodyazhnyy

Env ayarı olmayan 3. taraf programların genel durumu için, programı çalıştırmadan önce bir sarmalayıcıda özel bir env var ayarlayabilirsiniz . Cevabımı gör .
Peter Cordes

2

Belirli bir üçüncü taraf uygulamasından bahsediyorsanız, bir ortam değişkeni kullanın. Çoğu program, yeni süreçleri çatalla + çalıştırdıklarında tüm ortam boyunca değişmeden geçer.

Bu nedenle, kontrol edebileceğiniz özel bir env var ile bu uygulamayı başlatın . örneğin bunun için bir takma ad oluşturun alias vs=RUNNING_FROM_VSCODE=1 VSCodeveya bunun gibi bir sarıcı komut dosyası oluşturun:

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

Sonra .bashrcsenin içinde yapabilirsin

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

(( ))Eğer ifade sıfırdan farklı bir tamsayı olarak değerlendirilirse bash aritmetik ifadesi doğrudur (bu yüzden 1yukarıda kullandım ). Boş dize (bir unset env var için) false değeridir. Bas boole değişkenleri için güzel, ancak truegeleneksel bir POSIX ile kolayca kullanabilirsiniz ve kontrol edebilirsiniz.

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

Uygulamanız çoğunlukla çocukları için ortamı temizliyor , ancak yine de $PATHdeğişmeden geçiyorsa , bunu paketleyicinizde kullanabilirsiniz:

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

ve [[ "${PATH%RUNNING_FROM_VSCODE}" != "$PATH" ]]PATH'den bir sonek çıkarmanın onu değiştirip değiştirmediğini kontrol etmek için bash gibi bir desen eşleşmesi ile kontrol edin.

Bu, program bulunmayan harici komutları ararken zararsız bir şekilde ekstra bir dizin araması yapmalıdır. /dev/nullkesinlikle herhangi bir sistemde bir dizin değildir, bu yüzden ENOTDIRPATH aramaları önceki PATH girişlerinde aradıklarını bulamazsa hızlı bir şekilde sonuçlanacak sahte bir dizin olarak kullanmak güvenlidir .


Wrapper komut dosyaları genellikle mantıklı bir yaklaşımdır, dolayısıyla +1. Tek küçük dezavantaj, 3 programınız varsa, 3 sarıcı komut dosyası veya 3 farklı argüman alan bir sarıcı komut dosyası olmasını isteyebilir, bu da onu sıkıcı hale getirebilir. Yine de sağlam bir yaklaşım.
Sergiy Kolodyazhnyy

1

İşte benim 2 sentim. Sadece ekleyin .bashrc. terminalsEn sevdiğiniz terminallerle değiştirin ve kendinizinkine exportkomut verin.

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

Bu, gnome-terminal'in sunucu-istemci modeliyle çalışmaz.
egmont
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.