Bir bash betiği çalıştırdıktan sonra terminalden çık


18

Komutu bashkullanarak belirli dosyaları (çoğunlukla pdf dosyaları) açmak için bir komut dosyası yazmaya çalışıyorum gnome-open. Ben de pdf dosyasını açtıktan sonra terminal çıkmak istiyorum.

exitSenaryo sonuna eklemeyi denedim ancak bu terminali kapatmaz. Soruma bir cevap bulmak için çevrimiçi arama yapmaya çalıştım, ancak uygun bir cevap bulamadım, eğer siz yardımcı olabilirseniz gerçekten minnettar olurum.

Ben sadece komut çalıştırmak hangi terminali öldüren bir cevap gerekir tüm terminalleri mümkün değil mi? Kabul ettiğim bir önceki cevap açık olan tüm terminal pencerelerini öldürüyor. Bunun bugüne kadar böyle olduğunu fark etmedim.


Senaryoyu öncelikle terminalde mi çalıştırıyorsunuz? Kesinlikle komut satırından, terminali açmak için bir neden yoktur.
Jacob Vlijm

Evet komut dosyasını terminalden çalıştırıyorum. Terminal ve komut satırı arasında bir fark olduğunu fark
etmedim

Senaryomda gnome-openile değiştirdim xdg-openama değişiklik yok. Terminal hala açık
Rumesh

@Tim Wow, işe yarıyor =) +1
AB

@Tim Ama benim çözümüm de kötü değildi. ;)
AB

Yanıtlar:


12

Yalnızca bir dosya açıyorsanız, gerçekten bir komut dosyası kullanmanıza gerek yoktur , çünkü komut dosyası bir satırda birden çok komut çalıştırmanın kolay bir yoludur, burada sadece iki komut çalıştırmanız gerekir (dahil exit) .

exitBir komuttan sonra veya bir komut zincirinden sonra çalıştırmak istiyorsanız , &&operatörü kullanarak (önceki komutun / komut zincirinin başarılı olması durumunda bir sonraki komutu çalıştıracak) veya komutunuzu kullanarak sahip olduğunuza zincirleyebilirsiniz. ;operatörü (önceki komutun / komut zincirinin başarılı olması ve başarısız olması durumunda bir sonraki komutu yürütür).

Bu durumda böyle bir şey olurdu:

gnome-open <path_to_pdf_file> && exit

* <path_to_pfd_file> = pdf dosyasının yolu

exitbir komut dosyasının sonuna koymak bash, komut dosyasının çalıştırıldığı bashörnekten, Terminal'in iç bashörneğinden başka bir örnek olduğu için çalışmaz .

Yine de bir komut dosyası kullanmak istiyorsanız, en basit yol komut dosyasını şu şekilde çağırmaktır:

<path_to_script> && exit

Veya komut dosyası Terminal'in şu anki çalışma dizininde ise:

./<script> && exit

Bunu gerçekten yapmak istemiyorsanız / yapamıyorsanız, en basit ikinci yol bu satırı komut dosyanızın sonuna eklemektir:

kill -9 $PPID

Bu SIGKILLkomut dosyasının ana işlemine ( bashTerminal'e bağlı örnek) bir sinyal gönderir . bashTerminal'e yalnızca bir örnek bağlıysa , öldürülen Terminal'in kendisini kapatmasına neden olur. bashTerminal'e birden çok örnek bağlıysa , öldürülen Terminal'in kendini kapatmasına neden olmaz.


2
SIGTERM sinyali, sonlandırılmasını istemek için bir işleme gönderilir. SIGKILL sinyalinin aksine, işlem tarafından yakalanabilir ve yorumlanabilir veya yok sayılabilir. Bu, sürecin kaynakları serbest bırakmayı ve uygunsa durumu kaydetmeyi güzel bir şekilde sonlandırmasını sağlar. SIGINT neredeyse SIGTERM ile aynıdır.
AB

@AB Haklısın, SIGTERMişte yeterli değil.
kos

Cevap için teşekkürler. Sanırım cevabında verdiğin tek komutu kullanacağım
Rumesh

kill $ PPID çıkışla aynı şeyi yapar - hiçbir şey. Ve öldür -9 $ PPID ebeveyn ile birlikte tüm çocuk pencerelerini kapatır.
SDsolar

5

Bu komut dosyası terminali, dolayısıyla kabuğu ve kendisini sonlandırır.

Tüm süreçleri acımasızca öldürür. Bir terminalde açık birden fazla sekmeniz varsa, bunlar da kapatılır.

Sorun, eğer birkaç terminal açılırsa ve bunlar alt süreçler ise gnome-terminal-server, tüm terminaller öldürülür.

Bu durumda, komut dosyası bağımsız bir terminalde başlatılmalıdır, örn. xterm

<your_command> & disown

PPPID=$(awk '{print $4}' "/proc/$PPID/stat")
kill $PPPID
  • PPID

    PPID üst işlem kimliğidir, bu durumda shell ( e.g. /bin/bash)

  • PPPID

    PPPID, PPID'nin üst işlem kimliği, bu durumda terminal penceresi

  • <your_command> & disown

    Bash kabuğunda, reddetme yerleşik komutu, işleri iş tablosundan kaldırmak veya işleri işaretlemek için kullanılır; böylece üst kabuk bunu alırsa kendilerine bir SIGHUP sinyali gönderilmez (örneğin, kullanıcı oturumu kapatırsa).

  • awk '{print $4}' "/proc/$PPID/stat"

    Dosyanın dördüncü sütununun değerini alır /proc/$PPID/stat(örneğin, /proc/1/stat0 döndürür)


$$ get komutunun terminalin pid'i olduğunu düşünüyorum ... Bu bir alternatif olabilir mi? Ayrıca nasıl reddedileceğini açıklayabilir misiniz?
Tim

Bu senaryo bunu nasıl yapıyor? Komut dosyası oluşturmak için hala yeniyim, bu yüzden bu komutları gerçekten anlayamıyorum. Terminali nasıl kapattığını açıklayabilir misiniz
Rumesh

1
@ Hayır Zaman, bir terminalde kabuğu döndürür: ps xa | grep $$=> 4381 pts/0 Ss 0:01 /usr/bin/zsh
AB

1
@RumeshSudhaharan Komut dosyasının başlatıldığı tüm terminal penceresini öldürür, ancak başka terminal penceresi yoktur.
AB

3
@AB daha önce bunun sadece geçerli terminal penceresini öldürdüğünü söylediniz, diğerlerini değil. Bu senaryoyu bugün iki terminal penceresi açık olarak kullandım ve senaryoyu çalıştırdıktan sonra ikisi de öldürüldü.
Rumesh

4

Kullanabilirsiniz .exec ./your-script

GNOME Terminali gibi bir terminal emülatörü, içinde çalışan ilk işlem - genellikle bir kabuk olan - bırakıldığında kapanır.

Zaten bir terminaldeyseniz ve bu terminalden çıkmadan önce yapmak istediğiniz tek şey, belirli bir komut dosyasını (veya programı) çalıştırmaksa, artık artık içinde çalışan kabuğa ihtiyacınız olmadığı anlamına gelir. Böylece kabuğun execyerleşimini, kabuğun komutunuz tarafından oluşturulan işlemle değiştirmesini sağlamak için kullanabilirsiniz .

  • Senaryonuzda bu başka bir kabuk işlemi - tıpkı bir script çalıştırdığınızda ikinci bir kabuk işleminin nasıl oluşturulduğu gibi exec.

Sözdizimi örn .exec commandexec ./your-script

exec: Bir örnek

Örneğin count, geçerli dizinde adlandırılmış , yürütülebilir olarak işaretlenmiş ve bulunan bir kabuk komut dosyası olduğunu varsayalım . Bu içerir:

#!/usr/bin/env bash
for i in {5..1}; do echo $i; sleep 1; done

Ve bir terminalde koşuyorum:

exec ./count

Bu baskılar rakamları 5, 4, 3, 2, ve 1saniyede bir, ve daha sonra, terminal pencere kapanır.

Bunu, terminalinizdeki ilk işlemden başka bir şeyden çalıştırırsanız (örneğin, bashbaşka bir kabuk örneğini başlatmak için ilk kez çalıştırdıysanız), bu sizi terminalden çıkmak yerine bu işlemi oluşturan kabuğa geri getirir . (Bu uyarı exittemelli yöntemlere eşit olarak uygulanır .)

Kullanabilirsiniz ../your-script; exit

Kabuğunuza kendisini yeni işlemle (üzerinden exec) değiştirmesini söylemek istemiyorsanız, ona yapışmasını söyleyebilir, ancak yeni işlem bittikten hemen sonra kendini bırakabilirsiniz.

Bunu yapmak için, komutunuzu ve exitkomutu ;bir satırda verilebilecek şekilde birbirinden ayırarak çalıştırın .

Sözdizimi command; exitörn ../your-script; exit

command; exit vs. command && exit

Bunun kos ve heemayl'ın cevaplarında önerilen yönteme benzediğini fark edebilirsiniz . Fark şudur:./your-script && exit

  • &&ikinci komutu, yalnızca ilk komutun sıfır çıkış kodu döndürerek başarılı olduğunu bildirmesi durumunda çalıştırır .
  • ; ilk komutun başarılı olup olmadığına bakılmaksızın ikinci komutu çalıştırır.

Hangisini istediğiniz belirli duruma bağlıdır. Komut başarısız olursa, çağrılan kabuğun (ve barındırma terminalinin) kalmasını ister misiniz? Eğer öyleyse, kullanın &&; değilse kullanın ;.

Ayrıca command || exit, çağrılan kabuktan yalnızca başarısızlıkcommand bildirildiğinde çıkar .


2

Komut dosyanızı çalıştırmak yerine kaynaklayabilirsiniz.

$ cat run.sh
exit;
$ ./run.sh #will not close
$ . ./run.sh # will close

1

Şahsen, alt kabukta pdf veya diğer dosyaları açma komutunu yürütürüm, dosyaların açılmasına izin vermek için bir gecikme koyar ve sonra çıkar. Temel olarak, test ettiklerim(nohup gnome-open *.pdf &); sleep 2; exit

Bu varyasyon nohup gnome-open *.pdf && sleep 2 && exit


Benim durumumda, nohuphangup sinyalini göz ardı ettiğinden, nohup xdg-open some_programbenim için çalıştı ve exitgereksizdi. nohupmesajı bir nohup.outdosyaya yönlendirir :nohup: ignoring input and appending output to nohup.out
nick indiessance

0

En basit çözüm:

xdg-open file.pdf && exit

nohupKomutun göz ardı edilmesini sağlamak için diğer benzer komutlardan farklı olarak SIGHUP, bunun nedeni xdg-open, pdf dosyasını açmak için tercih edilen bir uygulama olan bir alt süreç yumurtlamadan çıkacaktır. Terminalden başlatılan asıl işlem artık öldürülecek nohupolmadığından gerekli değildir.

&&önceki komut başarılı olursa bir sonraki komutun çalıştırılacağını, yani çıkış kodunu 0( $?=0) döndürdüğünü exitve terminali kapatacağını belirtir .


Sanırım
Tim

@Tim: Belki OP doğru şekilde kullanmadı, sorudan bana ne kadar net olmadığı exitve sonunda nasıl koyduğu ve işe yaramadı ..
heemayl

1
@Tim Çünkü OP exitkomut dosyasının içine konur , çünkü bashkomut dosyasının yürütülmekte olduğu bashörnekten değil , Terminal'in kapanmasına neden olacak ana örnek yerine (Terminal'e bağlı olan) çıkma etkisi vardır.
kos

1
Zaten xdg-openarka planda zaten çalışıyor ve Terminal ile bağlantısı kesildi, bu yüzden nohupburada ihtiyacınız yok, ayrıca OP'nin xdg-openbirden fazla dosyayı toplu olarak açmak için bir kodun içinde birden çok kez çalıştığını anladığımdan xdg-open, betiğin içindeki komut dosyasının kullanılmasına neden olacak ilk başta çıkmak için xdg-openortaya çıkmasında
kos

@kos: Hayır, çalışan değilim xdg-openben olsaydı bile, backgr içinde nohupfarklı bir nedenden dolayı olduğunu ve Üst terminalini öldürecek ne zaman öldürülecek kaynak terminalden there..any arka plan işlemi olmalıdır .. nohuporada önlemektir terminali tekrar etkileşimli olarak kullanmam gerekmediği için, işlemi bg'ye koymaya gerek yok ... 2. noktanızda her xdg-open && exitbir alt kabukta
çalışarak

0

Başlık sorusunu açıkça cevaplamak için,

"Bir bash betiği çalıştırdıktan sonra terminalden çık" :

Terminalde yalnızca komut dosyanızı çalıştırın

Komut dosyasının ne yaptığının ayrıntılarına bakmadan, bir komut dosyası bir kabuk başlatmadan doğrudan option -e( --command) ile bir terminal içinde çalıştırılabilir - kabuk yerine kullanılır:

gnome-terminal -e ./script.sh

Komut dosyasına bağımsız değişkenler sağlamak istediğinizde -x( --execute) seçeneğini kullanın . Bununla, komut satırının sadece geri kalanı komut ve argümanlar olarak alınır.

gnome-terminal -x ./script.sh foo bar

Komut dosyanız çıkarsa, kullanıcı girdisini bekleyerek hiçbir şeyi tutabilecek etkileşimli bir kabuk yoktur.

Örnekler

Teminal, içinde çalışan komutun çıkmasından sonra çıkacaktır - bunun gibi, sleep4 saniye çalıştıktan sonra kapanma , kabuk olmadan:

gnome-terminal -x sleep 4

Elbette, kabuk komut dosyasını kullanabilirsiniz, çünkü komut dosyanız yine de farklı bir kabuk örneği kullanıyor.

Ayrıca, açık bir komut dosyasıyla bir kabuk çalıştırabilirsiniz - etkileşimli olmayacaktır:

gnome-terminal -x bash -c "echo 'Hello!'; sleep 4"
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.