Keluar dari terminal setelah menjalankan skrip bash

18

Saya mencoba menulis bashskrip untuk membuka file tertentu (kebanyakan file pdf) menggunakan gnome-openperintah. Saya juga ingin terminal keluar setelah membuka file pdf.

Saya telah mencoba menambahkan exitke akhir skrip saya tetapi itu tidak menutup terminal. Saya memang mencoba mencari jawaban untuk pertanyaan saya secara online tetapi saya tidak dapat menemukan jawaban yang tepat, saya akan sangat menghargainya jika kalian dapat membantu.

Saya membutuhkan jawaban yang hanya membunuh terminal dari mana saya menjalankan perintah tidak semua terminal akan mungkin? Jawaban sebelumnya yang saya terima membunuh semua jendela terminal yang terbuka. Saya tidak menyadari ini adalah masalahnya sampai hari ini.

Rumesh
sumber
Apakah Anda menjalankan skrip di terminal sejak awal? Ketat dari baris perintah, tidak ada alasan untuk membuka terminal untuk melakukannya.
Jacob Vlijm
Ya saya menjalankan skrip dari terminal. Saya tidak menyadari ada perbedaan antara terminal dan baris perintah
Rumesh
Saya mengganti gnome-opendengan xdg-opendalam skrip saya tetapi tidak ada perubahan. Terminal masih tetap terbuka
Rumesh
@ Tim Wow, berfungsi =) +1
AB
@Tim Tapi solusi saya juga tidak buruk. ;)
AB

Jawaban:

12

Jika Anda hanya membuka satu file, Anda tidak benar - benar perlu menggunakan skrip, karena skrip dimaksudkan untuk menjadi cara yang mudah untuk menjalankan banyak perintah dalam satu baris, sementara di sini Anda hanya perlu menjalankan dua perintah (termasuk exit) .

Jika Anda ingin menjalankan exitsetelah perintah atau setelah rantai perintah, Anda dapat rantai ke apa yang sudah Anda miliki dengan menggunakan &&operator (yang pada keberhasilan perintah / rantai perintah sebelumnya akan menjalankan perintah berikutnya) atau dengan menggunakan ;operator (yang sukses dan gagal pada perintah / rantai perintah sebelumnya akan menjalankan perintah berikutnya).

Dalam hal ini akan menjadi seperti itu:

gnome-open <path_to_pdf_file> && exit

* <path_to_pfd_file> = path file pdf

exitdiletakkan di akhir skrip tidak berfungsi karena ia hanya keluar dari bashcontoh di mana skrip dijalankan, yang merupakan bashcontoh lain dari instance dalam Terminal bash.

Jika Anda tetap ingin menggunakan skrip, cara paling mudah adalah dengan memanggil skrip seperti:

<path_to_script> && exit

Atau jika skrip ada di direktori kerja Terminal saat ini seperti:

./<script> && exit

Jika Anda benar - benar tidak ingin / tidak bisa melakukan itu, cara paling mudah kedua adalah menambahkan baris ini di akhir skrip Anda:

kill -9 $PPID

Ini akan mengirimkan SIGKILLsinyal ke ke proses induk skrip ( bashinstance terhubung ke Terminal). Jika hanya satu bashinstance yang terhubung ke Terminal, yang terbunuh akan menyebabkan Terminal menutup sendiri. Jika beberapa bashinstance ditautkan ke Terminal, yang terbunuh tidak akan menyebabkan Terminal menutup sendiri.

kos
sumber
2
Sinyal SIGTERM dikirim ke suatu proses untuk meminta penghentiannya. Berbeda dengan sinyal SIGKILL, sinyal dapat ditangkap dan ditafsirkan atau diabaikan oleh proses. Hal ini memungkinkan proses untuk melakukan penghentian bagus melepaskan sumber daya dan menyimpan keadaan jika perlu. SIGINT hampir identik dengan SIGTERM.
AB
@ AB Anda benar, SIGTERMini tidak cukup.
kos
Terima kasih balasannya. Saya kira sakit hanya menggunakan satu perintah yang Anda berikan dalam jawaban Anda
Rumesh
kill $ PPID melakukan hal yang sama dengan exit - tidak ada. Dan bunuh -9 $ PPID menutup semua jendela anak bersama dengan orang tua.
SDsolar
5

Script ini mengakhiri terminal dan dengan demikian shell dan dirinya sendiri.

Tanpa ampun membunuh semua proses. Jika Anda memiliki banyak tab terbuka di terminal, maka ini juga ditutup.

Masalahnya adalah, jika beberapa terminal dibuka dan ini adalah proses anak gnome-terminal-server, semua terminal akan terbunuh.

Dalam hal ini, skrip harus dimulai di terminal independen, misalnya xterm

<your_command> & disown

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

    PPID adalah id proses induk, dalam hal ini shell ( e.g. /bin/bash)

  • PPPID

    PPPID adalah id proses induk PPID, dalam hal ini, jendela terminal

  • <your_command> & disown

    Di bash shell, perintah builtin disown digunakan untuk menghapus pekerjaan dari tabel pekerjaan, atau untuk menandai pekerjaan sehingga sinyal SIGHUP tidak dikirim kepada mereka jika shell induk menerimanya (misalnya jika pengguna logout).

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

    Mendapat nilai kolom keempat file /proc/$PPID/stat(mis. Untuk /proc/1/statitu mengembalikan 0)

AB
sumber
Saya pikir perintah $$ dapatkan adalah pid dari terminal ... Apakah itu menjadi alternatif? Bisakah Anda menjelaskan bagaimana cara menolak?
Tim
Bagaimana skrip ini melakukan itu? Saya masih baru di shell scripting jadi saya benar-benar tidak mengerti perintah-perintah itu. Bisakah Anda jelaskan bagaimana terminal ditutup
Rumesh
1
@Tim Tidak, ini mengembalikan shell di terminal: ps xa | grep $$=> 4381 pts/0 Ss 0:01 /usr/bin/zsh
AB
1
@RumeshSudhaharan Membunuh seluruh jendela terminal tempat skrip dimulai, tetapi tidak ada jendela terminal lainnya.
AB
3
@ AB Anda sebelumnya mengatakan bahwa ini hanya membunuh jendela terminal saat ini dan bukan yang lain. Saya menggunakan skrip ini hari ini dengan dua jendela terminal terbuka dan keduanya terbunuh begitu saya menjalankan skrip.
Rumesh
4

Anda bisa menggunakannya .exec ./your-script

Emulator terminal seperti Terminal GNOME berhenti ketika proses awal berjalan di dalamnya - yang biasanya berupa shell - berhenti.

Jika Anda sudah berada di terminal dan satu-satunya hal yang ingin Anda lakukan sebelum berhenti dari terminal itu adalah menjalankan skrip (atau program) tertentu, maka ini berarti Anda tidak lagi benar-benar membutuhkan shell yang berjalan di dalamnya lagi. Dengan demikian Anda dapat menggunakan execbuiltin shell untuk membuat shell menggantinya dengan proses yang dibuat oleh perintah Anda.

  • Dalam hal skrip Anda, itu adalah proses shell lain - sama seperti cara proses shell kedua dibuat saat Anda menjalankan skrip tanpa exec.

Sintaksnya adalah , mis . , .exec commandexec ./your-script

exec: sebuah contoh

Sebagai contoh, misalkan saya memiliki skrip shell bernama count, ditandai executable, dan terletak di direktori saat ini. Itu mengandung:

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

Dan, di terminal, saya menjalankan:

exec ./count

Ini mencetak angka 5, 4, 3, 2, dan 1, satu per detik, dan kemudian menutup jendela terminal.

Jika Anda menjalankan ini dari sesuatu selain proses pertama berjalan di terminal Anda - misalnya, jika Anda berlari bashpertama untuk memulai contoh shell lain - maka ini membawa Anda kembali ke shell yang dibuat bahwa proses, bukan berhenti terminal. (Peringatan ini berlaku sama untuk exitmetode berbasis.)

Anda bisa menggunakannya ../your-script; exit

Jika Anda tidak ingin memberi tahu shell Anda untuk menggantinya dengan proses baru (via exec), Anda dapat menyuruh shell untuk tetap bertahan tetapi keluar sendiri segera setelah proses baru selesai.

Untuk melakukan ini, jalankan perintah dan exitperintah Anda, pisahkan dengan ;sehingga mereka dapat diberikan pada satu baris.

Sintaksnya adalah command; exit, mis . , ../your-script; exit

command; exit vs. command && exit

Anda mungkin memperhatikan ini mirip dengan metode yang disarankan dalam jawaban kos dan heemayl . Perbedaannya adalah:./your-script && exit

  • &&menjalankan perintah kedua hanya jika perintah pertama melaporkan bahwa ia berhasil dengan mengembalikan kode keluar nol.
  • ; menjalankan perintah kedua terlepas dari apakah perintah pertama dilaporkan berhasil atau tidak.

Yang mana yang Anda inginkan tergantung pada situasi spesifik. Jika perintah gagal, apakah Anda ingin shell panggilan (dan terminal hosting) tetap terjaga? Jika demikian, gunakan &&; jika tidak, gunakan ;.

Ada juga command || exit, yang keluar dari shell panggilan hanya jika commanddilaporkan gagal .

Eliah Kagan
sumber
2

Anda dapat sumber skrip Anda alih-alih menjalankannya misalnya

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

Secara pribadi saya akan menjalankan perintah untuk membuka file pdf atau lainnya dalam subshell, menunda untuk membiarkan file terbuka, dan kemudian keluar. Pada dasarnya, inilah yang saya uji(nohup gnome-open *.pdf &); sleep 2; exit

Variasi akan ini nohup gnome-open *.pdf && sleep 2 && exit

Sergiy Kolodyazhnyy
sumber
Dalam kasus saya, karena nohupmengabaikan sinyal hangup, nohup xdg-open some_programbekerja untuk saya, dan exittidak dibutuhkan. nohupmengalihkan pesan ke nohup.outfile:nohup: ignoring input and appending output to nohup.out
nick indiessance
0

Solusi paling sederhana adalah:

xdg-open file.pdf && exit

Tidak seperti perintah serupa lainnya nohuptidak diperlukan untuk membuat perintah mengabaikan SIGHUP, alasannya xdg-openakan keluar menelurkan proses anak yang merupakan aplikasi pilihan untuk membuka file pdf. Karena proses sebenarnya dimulai dari terminal tidak ada lagi di sana untuk dibunuh, nohuptidak diperlukan.

&&menunjukkan perintah berikutnya akan dijalankan jika perintah sebelumnya berhasil yaitu mengembalikan kode keluar 0( $?=0) dan exithanya akan menutup terminal.

heemayl
sumber
Kurasa dia bilang jalan keluar tidak berfungsi ...
Tim
@ Tim: Mungkin OP tidak menggunakannya dengan cara yang benar, dari pertanyaannya sangat tidak jelas bagi saya bagaimana ia meletakkannya exitdi akhir dan tidak bekerja ..
heemayl
1
@Tim Karena OP meletakkan exitdi dalam skrip, yang tidak berguna karena memiliki efek keluar dari bashcontoh di mana skrip dieksekusi daripada bashcontoh induk (yang ditautkan ke Terminal), yang akan menyebabkan Terminal untuk menutup sebagai gantinya
kos
1
Pokoknya xdg-opensudah berjalan di latar belakang dan tidak terhubung dari Terminal, jadi Anda tidak perlu di nohupsini, ditambah dari apa yang saya pahami OP berjalan xdg-openbeberapa kali di dalam skrip untuk membuka banyak file sekaligus, menggunakan xdg-openseperti itu di dalam skrip akan menyebabkan skrip untuk keluar pada xdg-openkejadian pertama
kos
@kos: Tidak, saya tidak menjalankan xdg-opendi backgr, bahkan jika saya punya nohupadalah untuk alasan yang berbeda & harus ada di sana .. setiap proses latar belakang dari terminal asal akan terbunuh ketika Anda akan membunuh terminal induk .. nohupada untuk mencegah it..saya tidak perlu menggunakan terminal lagi secara interaktif, tidak perlu memasukkan proses dalam bg..pada poin ke-2 Anda yang juga dapat dicegah dengan menjalankan masing-masing xdg-open && exitdalam sebuah subkulit ..
heemayl
0

Untuk secara eksplisit menjawab pertanyaan judul,

"Keluar dari terminal setelah menjalankan skrip bash" :

Jalankan hanya skrip Anda di terminal

Tanpa melihat detail apa yang dilakukan skrip, skrip dapat langsung dijalankan di dalam terminal dengan opsi -e( --command), tanpa memulai shell - itu digunakan sebagai ganti shell lalu:

gnome-terminal -e ./script.sh

Gunakan opsi -x( --execute) saat Anda ingin memberikan argumen ke skrip. Dengan ini, hanya seluruh sisa dari commandline diambil sebagai perintah dan argumen.

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

Jika skrip Anda keluar, tidak ada shell interaktif yang dapat menahan apa pun dengan menunggu input pengguna.

Contohnya

Teminal hanya akan keluar setelah perintah yang berjalan di dalamnya keluar - seperti ini, menutup setelah sleepberjalan 4 detik, tanpa shell:

gnome-terminal -x sleep 4

Tentu saja, Anda masih dapat menggunakan skrip shell, karena skrip Anda menggunakan contoh shell yang berbeda pula.

Anda juga dapat menjalankan shell dengan skrip eksplisit - itu tidak akan interaktif:

gnome-terminal -x bash -c "echo 'Hello!'; sleep 4"
Volker Siegel
sumber