Thoát khỏi thiết bị đầu cuối sau khi chạy tập lệnh bash


18

Tôi đang cố gắng viết một bashtập lệnh để mở một số tệp nhất định (chủ yếu là tệp pdf) bằng gnome-openlệnh. Tôi cũng muốn thiết bị đầu cuối thoát khi nó mở tệp pdf.

Tôi đã cố gắng thêm exitvào cuối tập lệnh của mình tuy nhiên điều đó không đóng thiết bị đầu cuối. Tôi đã cố gắng tìm kiếm câu trả lời trực tuyến cho câu hỏi của mình nhưng tôi không thể tìm thấy câu trả lời nào phù hợp, tôi thực sự sẽ đánh giá cao nếu các bạn có thể giúp đỡ.

Tôi cần một câu trả lời chỉ giết chết thiết bị đầu cuối mà tôi chạy lệnh mà không phải tất cả các thiết bị đầu cuối này sẽ có thể? Câu trả lời trước đó tôi chấp nhận sẽ giết tất cả các cửa sổ đầu cuối đang mở. Tôi đã không nhận ra đây là trường hợp cho đến ngày hôm nay.


Bạn đang chạy tập lệnh trong thiết bị đầu cuối ở nơi đầu tiên? Nghiêm khắc từ dòng lệnh, không có lý do để mở terminal để làm như vậy.
Jacob Vlijm

Có tôi chạy tập lệnh từ thiết bị đầu cuối. Tôi không nhận ra có sự khác biệt giữa thiết bị đầu cuối và dòng lệnh
Rumesh

Tôi đã thay thế gnome-openbằng xdg-opentrong kịch bản của mình nhưng không có thay đổi. Nhà ga vẫn mở
Rumesh

@Tim Wow, nó hoạt động =) +1
AB

@Tim Nhưng giải pháp của tôi cũng không tệ. ;)
AB

Câu trả lời:


12

Nếu bạn chỉ mở một tệp, bạn không thực sự cần sử dụng tập lệnh, bởi vì tập lệnh có nghĩa là một cách dễ dàng để chạy nhiều lệnh liên tiếp, trong khi ở đây bạn chỉ cần chạy hai lệnh (bao gồm exit) .

Nếu bạn muốn chạy exittheo một lệnh hoặc sau một chuỗi lệnh, bạn có thể xâu chuỗi nó với những gì bạn đã có bằng cách sử dụng &&toán tử (thành công của lệnh / chuỗi lệnh trước đó sẽ thực hiện lệnh tiếp theo) hoặc bằng cách sử dụng lệnh ;toán tử (cả thành công và thất bại của lệnh / chuỗi lệnh trước sẽ thực thi lệnh tiếp theo).

Trong trường hợp này, nó sẽ là một cái gì đó như thế:

gnome-open <path_to_pdf_file> && exit

* <path_to_pfd_file> = đường dẫn của tệp pdf

exitđặt ở cuối tập lệnh không hoạt động vì nó chỉ thoát khỏi bashthể hiện trong đó tập lệnh được chạy, đây là một bashthể hiện khác với thể hiện bên trong của Terminal bash.

Nếu bạn muốn sử dụng tập lệnh nào, cách đơn giản nhất là chỉ gọi tập lệnh như vậy:

<path_to_script> && exit

Hoặc nếu tập lệnh nằm trong thư mục làm việc hiện tại của Terminal như vậy:

./<script> && exit

Nếu bạn thực sự không muốn / không thể làm điều đó, cách đơn giản thứ hai là thêm dòng này vào cuối tập lệnh của bạn:

kill -9 $PPID

Điều này sẽ gửi SIGKILLtín hiệu đến tiến trình cha của tập lệnh ( bashthể hiện được liên kết với Terminal). Nếu chỉ có một bashphiên bản được liên kết với Terminal, việc bị giết đó sẽ khiến Terminal tự đóng. Nếu nhiều bashtrường hợp được liên kết với Terminal, việc bị giết sẽ không khiến Terminal tự đóng.


2
Tín hiệu SIGTERM được gửi đến một quy trình để yêu cầu chấm dứt. Không giống như tín hiệu SIGKILL, nó có thể bị bắt và giải thích hoặc bỏ qua bởi quy trình. Điều này cho phép quá trình thực hiện chấm dứt tốt đẹp giải phóng tài nguyên và lưu trạng thái nếu thích hợp. SIGINT gần giống với SIGTERM.
AB

@AB Bạn nói đúng, SIGTERMở đây là không đủ.
kos

Cảm ơn vi đa trả lơi. Tôi đoán là chỉ cần sử dụng một lệnh duy nhất mà bạn đã đưa ra trong câu trả lời của mình
Rumesh

giết $ PPID giống như thoát - không có gì. Và tiêu diệt -9 $ PPID đóng tất cả các cửa sổ con cùng với cha mẹ.
SDsolar

5

Kịch bản này chấm dứt thiết bị đầu cuối và do đó shell và chính mình.

Nó giết chết không thương tiếc tất cả các quá trình. Nếu bạn có nhiều tab mở trong một thiết bị đầu cuối, thì những tab này cũng được đóng lại.

Vấn đề là, nếu một số thiết bị đầu cuối được mở và đây là các quy trình con của gnome-terminal-server, tất cả các thiết bị đầu cuối sẽ bị giết.

Trong trường hợp này, tập lệnh nên được bắt đầu trong một thiết bị đầu cuối độc lập, ví dụ: xterm

<your_command> & disown

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

    PPID là id tiến trình cha, trong trường hợp này là shell ( e.g. /bin/bash)

  • PPPID

    PPPID là id tiến trình cha của PPID, trong trường hợp này là cửa sổ đầu cuối

  • <your_command> & disown

    Trong bash shell, lệnh dựng sẵn bị từ chối được sử dụng để xóa các công việc khỏi bảng công việc hoặc để đánh dấu các công việc để tín hiệu SIGHUP không được gửi đến chúng nếu shell cha nhận được nó (ví dụ: nếu người dùng đăng xuất).

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

    Nhận giá trị của cột thứ tư của tệp /proc/$PPID/stat(ví dụ: /proc/1/statnó trả về 0)


Tôi nghĩ rằng lệnh $$ có được vị trí của thiết bị đầu cuối ... Đó có phải là một sự thay thế không? Bạn cũng có thể giải thích làm thế nào để từ chối?
Tim

Làm thế nào để kịch bản này làm điều đó? Tôi vẫn chưa quen với shell scripting vì vậy tôi không thể thực sự hiểu các lệnh đó. Bạn có thể giải thích cách nó đóng thiết bị đầu cuối
Rumesh

1
@Tim Không, nó trả lại vỏ trong một thiết bị đầu cuối: ps xa | grep $$=> 4381 pts/0 Ss 0:01 /usr/bin/zsh
AB

1
@RumeshSudhaharan Nó giết toàn bộ cửa sổ đầu cuối trong đó tập lệnh được khởi động, nhưng không có cửa sổ đầu cuối nào khác.
AB

3
@AB trước đây bạn đã nói rằng điều này chỉ giết chết cửa sổ terminal hiện tại chứ không phải bất kỳ cái nào khác. Tôi đã sử dụng tập lệnh này ngày hôm nay với hai cửa sổ đầu cuối mở và cả hai đều bị giết khi tôi chạy tập lệnh.
Rumesh

4

Bạn có thể sử dụng .exec ./your-script

Trình giả lập thiết bị đầu cuối như Gnome Terminal thoát khi quá trình ban đầu chạy bên trong nó - thường là trình bao - thoát.

Nếu bạn đã ở trong một thiết bị đầu cuối và điều duy nhất bạn muốn làm trước khi thoát thiết bị đầu cuối đó là chạy một tập lệnh (hoặc chương trình) cụ thể, thì điều này có nghĩa là bạn không còn thực sự cần cái vỏ đang chạy trong đó nữa. Do đó, bạn có thể sử dụng hàm execdựng sẵn của shell để làm cho shell tự thay thế bằng quy trình được tạo bởi lệnh của bạn.

  • Trong trường hợp tập lệnh của bạn, đó là một quy trình shell khác - giống như cách quy trình shell thứ hai được tạo khi bạn chạy tập lệnh mà không có exec.

Cú pháp là , ví dụ , .exec commandexec ./your-script

exec: một ví dụ

Ví dụ: giả sử tôi có một tập lệnh shell được gọi count, được đánh dấu thực thi và nằm trong thư mục hiện tại. Nó chứa:

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

Và, trong một thiết bị đầu cuối, tôi chạy:

exec ./count

Đây in các chữ số 5, 4, 3, 2, và 1, mỗi thứ hai, và sau đó đóng cửa sổ terminal.

Nếu bạn chạy cái này từ một cái gì đó khác với quy trình đầu tiên chạy trong thiết bị đầu cuối của bạn - ví dụ, nếu bạn chạy bashtrước để bắt đầu một phiên bản shell khác - thì điều này sẽ đưa bạn trở lại trình bao đã tạo ra quy trình đó , thay vì thoát khỏi thiết bị đầu cuối. (Thông báo trước này áp dụng như nhau cho exitcác phương pháp dựa trên.)

Bạn có thể sử dụng ../your-script; exit

Nếu bạn không muốn bảo trình bao của mình thay thế chính nó bằng quy trình mới (thông qua exec), bạn có thể bảo nó bám xung quanh nhưng tự thoát ra ngay sau khi quy trình mới kết thúc.

Để làm điều này, hãy chạy lệnh của bạn và exitlệnh, cách nhau ;để chúng có thể được cung cấp trên một dòng.

Cú pháp là command; exit, ví dụ , ../your-script; exit

command; exit so với command && exit

Bạn có thể nhận thấy điều này trông tương tự như phương pháp được đề xuất trong câu trả lời của kosheemayl . Sự khác biệt là:./your-script && exit

  • &&chỉ chạy lệnh thứ hai nếu lệnh đầu tiên báo cáo rằng nó đã thành công bằng cách trả về mã thoát bằng không.
  • ; chạy lệnh thứ hai bất kể lệnh đầu tiên có báo cáo thành công hay không.

Cái nào bạn muốn phụ thuộc vào tình hình cụ thể. Nếu lệnh thất bại, bạn có muốn shell gọi (và thiết bị đầu cuối lưu trữ) ở lại không? Nếu vậy, sử dụng &&; nếu không, sử dụng ;.

Ngoài ra command || exit, cũng chỉ thoát khỏi vỏ gọi nếu commandbáo cáo thất bại .


2

Bạn có thể nguồn kịch bản của mình thay vì chạy nó, vd

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

1

Cá nhân tôi sẽ thực thi lệnh để mở pdf hoặc các tệp khác trong subshell, đặt một độ trễ để cho các tệp mở và sau đó thoát. Về cơ bản, đây là những gì tôi đã thử nghiệm(nohup gnome-open *.pdf &); sleep 2; exit

Sự thay đổi về điều này sẽ là nohup gnome-open *.pdf && sleep 2 && exit


Trong trường hợp của tôi, vì nohupbỏ qua tín hiệu gác máy, nohup xdg-open some_programlàm việc cho tôi và exitkhông cần thiết. nohupchuyển hướng tin nhắn đến một nohup.outtập tin:nohup: ignoring input and appending output to nohup.out
nick indiessance

0

Giải pháp đơn giản nhất sẽ là:

xdg-open file.pdf && exit

Không giống như các lệnh tương tự khác nohuplà không cần thiết để làm cho lệnh bỏ qua SIGHUP, lý do xdg-opensẽ thoát khỏi việc sinh ra một tiến trình con là ứng dụng ưa thích để mở tệp pdf. Vì quá trình thực tế bắt đầu từ thiết bị đầu cuối không còn bị giết nữa, nohupnên không cần thiết.

&&cho biết lệnh tiếp theo sẽ được chạy nếu lệnh trước đó thành công tức là trả về mã thoát 0( $?=0) và exitchỉ cần đóng thiết bị đầu cuối.


Tôi nghĩ rằng anh ấy nói lối ra không hoạt động ...
Tim

@Tim: Có lẽ OP đã không sử dụng nó đúng cách, từ câu hỏi rất rõ ràng với tôi làm thế nào mà anh ấy / cô ấy đặt exitở cuối và không hoạt động ..
heemayl

1
@Tim Bởi vì OP đặt exitbên trong tập lệnh, điều này không đáng tin vì nó có tác dụng thoát khỏi bashthể hiện trong đó tập lệnh đang được thực thi thay vì phiên bản cha bash(liên kết với Terminal), điều này sẽ khiến Terminal đóng
kos

1
Dù sao, xdg-opennó đã chạy trong nền và được liên kết khỏi Terminal, vì vậy bạn không cần nohupở đây, cộng với những gì tôi hiểu OP chạy xdg-opennhiều lần trong một tập lệnh để mở nhiều tệp, sử dụng xdg-opennhư vậy trong tập lệnh sẽ gây ra tập lệnh để thoát ra ở lần xdg-openxuất hiện đầu tiên
kos

@kos: Không, tôi không chạy xdg-opentrong backgr, ngay cả khi tôi có nohupvì một lý do khác & phải ở đó..tất cả quá trình nền từ thiết bị đầu cuối sẽ bị giết khi bạn sẽ giết thiết bị đầu cuối cha mẹ .. nohupcó ở đó để ngăn chặn nó..như tôi không cần phải sử dụng thiết bị đầu cuối một cách tương tác một lần nữa, không cần phải đưa quá trình vào bg..trên điểm thứ 2 của bạn cũng có thể được ngăn chặn bằng cách chạy từng cái xdg-open && exittrong một mạng con ..
heemayl

0

Để trả lời rõ ràng câu hỏi tiêu đề,

"Thoát khỏi thiết bị đầu cuối sau khi chạy tập lệnh bash" :

Chỉ chạy tập lệnh của bạn trong thiết bị đầu cuối

Không cần nhìn vào chi tiết tập lệnh làm gì, tập lệnh có thể được chạy trực tiếp bên trong một thiết bị đầu cuối với tùy chọn -e( --command), mà không cần khởi động trình bao - nó được sử dụng thay cho trình bao sau đó:

gnome-terminal -e ./script.sh

Sử dụng tùy chọn -x( --execute) khi bạn muốn cung cấp đối số cho tập lệnh. Với điều này, toàn bộ phần còn lại của dòng lệnh được lấy làm lệnh và đối số.

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

Nếu tập lệnh của bạn thoát, không có trình bao tương tác nào có thể chứa bất cứ thứ gì bằng cách chờ người dùng nhập liệu.

Ví dụ

Teminal sẽ chỉ thoát sau khi lệnh chạy trong nó thoát - như thế này, đóng sau khi sleepđã chạy 4 giây, không có vỏ:

gnome-terminal -x sleep 4

Tất nhiên, bạn có thể sử dụng kịch bản shell, vì tập lệnh của bạn đang sử dụng một thể hiện shell khác.

Ngoài ra, bạn có thể chạy shell với tập lệnh rõ ràng - nó sẽ không tương tác:

gnome-terminal -x bash -c "echo 'Hello!'; sleep 4"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.