ออกจากเทอร์มินัลหลังจากรันสคริปต์ทุบตี


18

ฉันพยายามเขียนbashสคริปต์เพื่อเปิดไฟล์บางไฟล์ (ส่วนใหญ่เป็นไฟล์ pdf) โดยใช้gnome-openคำสั่ง ฉันต้องการให้เทอร์มินัลออกเมื่อเปิดไฟล์ pdf

ฉันได้ลองเพิ่มexitในตอนท้ายของสคริปต์ของฉัน แต่ที่ไม่ปิด terminal ฉันพยายามค้นหาคำตอบสำหรับคำถามของฉันทางออนไลน์ แต่ฉันไม่สามารถหาคำตอบที่เหมาะสมได้ฉันจะขอบคุณถ้าคุณช่วยได้

ฉันต้องการคำตอบที่จะฆ่าเทอร์มินัลที่ฉันรันคำสั่งไม่ใช่เทอร์มินัลทั้งหมดจะเป็นไปได้หรือไม่ คำตอบก่อนหน้าซึ่งฉันยอมรับฆ่า windows terminal ทั้งหมดที่เปิดอยู่ ฉันไม่ได้ตระหนักถึงสิ่งนี้เป็นกรณีจนถึงวันนี้


คุณกำลังรันสคริปต์ในเทอร์มินัลตั้งแต่แรกไหม? อย่างเคร่งครัดจากบรรทัดคำสั่งไม่มีเหตุผลที่จะเปิดเทอร์มินัล
Jacob Vlijm

ใช่ฉันเรียกใช้สคริปต์จากเทอร์มินัล ฉันไม่ทราบว่ามีความแตกต่างระหว่างเทอร์มินัลและบรรทัดคำสั่ง
Rumesh

ฉันแทนที่gnome-openด้วยxdg-openในสคริปต์ของฉัน แต่ไม่มีการเปลี่ยนแปลง เทอร์มินัลยังคงเปิดอยู่
Rumesh

@Tim Wow มันใช้งานได้ =) +1
AB

@ Tim แต่ทางออกของฉันก็ไม่ได้แย่เหมือนกัน ;)
AB

คำตอบ:


12

หากคุณกำลังเปิดไฟล์เพียงไฟล์เดียวคุณไม่จำเป็นต้องใช้สคริปต์จริงๆเพราะสคริปต์มีความหมายว่าเป็นวิธีที่ง่ายในการเรียกใช้หลายคำสั่งในหนึ่งแถวขณะที่คุณเพียงแค่เรียกใช้สองคำสั่ง (รวมถึงexit) .

หากคุณต้องการเรียกใช้exitหลังจากคำสั่งหรือหลังคำสั่งกลุ่มคุณสามารถเชื่อมโยงกับสิ่งที่คุณมีอยู่แล้วโดยใช้ตัว&&ดำเนินการ (ซึ่งในความสำเร็จของคำสั่งก่อนหน้า / กลุ่มคำสั่งจะเรียกใช้คำสั่งถัดไป) หรือโดยใช้;โอเปอเรเตอร์ (ซึ่งประสบความสำเร็จและล้มเหลวของคำสั่งก่อนหน้า / เชนคำสั่งจะดำเนินการคำสั่งถัดไป)

ในกรณีนี้มันจะเป็นอย่างนั้น:

gnome-open <path_to_pdf_file> && exit

* <path_to_pfd_file> = พา ธ ของไฟล์ pdf

exitใส่ในตอนท้ายของสคริปต์ไม่ทำงานเพราะมันเพียงออกจากbashอินสแตนซ์ที่มีการเรียกใช้สคริปต์ซึ่งเป็นอีกหนึ่งbashตัวอย่างกว่าbashอินสแตนซ์ด้านในของเทอร์มินัล

หากคุณต้องการใช้สคริปต์วิธีที่ตรงไปตรงมาที่สุดคือเพียงเรียกใช้สคริปต์ดังนี้:

<path_to_script> && exit

หรือถ้าสคริปต์อยู่ในไดเรกทอรีการทำงานปัจจุบันของเทอร์มินัล:

./<script> && exit

หากคุณจริงๆไม่ต้องการ / ไม่สามารถทำเช่นนั้นวิธีที่ง่ายที่สุดที่สองคือการเพิ่มบรรทัดนี้ในตอนท้ายของสคริปต์ของคุณ:

kill -9 $PPID

สิ่งนี้จะส่งSIGKILLสัญญาณไปยังกระบวนการหลักของสคริปต์ ( bashอินสแตนซ์ที่เชื่อมโยงกับเทอร์มินัล) หากมีเพียงbashอินสแตนซ์เดียวที่เชื่อมโยงกับเทอร์มินัลการฆ่านั้นจะทำให้เทอร์มินัลปิดตัวเอง หากมีหลายbashอินสแตนซ์เชื่อมโยงกับเทอร์มินัลการฆ่านั้นจะไม่ทำให้เทอร์มินัลปิดตัวเอง


2
สัญญาณ SIGTERM ถูกส่งไปยังกระบวนการเพื่อร้องขอการยกเลิก ซึ่งแตกต่างจากสัญญาณ SIGKILL ก็สามารถจับและตีความหรือละเว้นโดยกระบวนการ สิ่งนี้อนุญาตให้กระบวนการดำเนินการเลิกจ้างอย่างดีปล่อยทรัพยากรและสถานะการบันทึกตามความเหมาะสม SIGINT ใกล้เคียงกับ SIGTERM
AB

@AB ถูกต้องSIGTERMที่นี่ไม่เพียงพอ
kos

ขอบคุณสำหรับการตอบกลับ. ฉันเดาไม่ดีแค่ใช้คำสั่งเดียวที่คุณให้ไว้ในคำตอบของคุณ
Rumesh

kill $ PPID ทำเช่นเดียวกันกับ exit - ไม่มีอะไรเลย และฆ่า -9 $ PPID จะปิดหน้าต่างลูกทั้งหมดพร้อมกับพาเรนต์
SDsolar

5

สคริปต์นี้ยุติเทอร์มินัลและทำให้เชลล์และตัวเขาเอง

มันฆ่ากระบวนการทั้งหมดอย่างไร้ความปราณี หากคุณเปิดหลายแท็บในเทอร์มินัลแท็บเหล่านี้ก็จะถูกปิดเช่นกัน

ปัญหาคือถ้าเทอร์มินัลหลายตัวถูกเปิดและสิ่งเหล่านี้เป็นกระบวนการลูกของgnome-terminal-serverเทอร์มินัลทั้งหมดจะถูกฆ่า

ในกรณีนี้สคริปต์ควรเริ่มทำงานในเทอร์มินัลอิสระเช่น xterm

<your_command> & disown

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

    PPID เป็น id กระบวนการหลักในกรณีนี้เชลล์ ( e.g. /bin/bash)

  • PPPID

    PPPID เป็น id กระบวนการหลักของ PPID ในกรณีนี้หน้าต่างเทอร์มินัล

  • <your_command> & disown

    ใน bash shell คำสั่ง disown builtin จะใช้เพื่อลบงานออกจากตารางงานหรือทำเครื่องหมายงานเพื่อให้สัญญาณ SIGHUP ไม่ถูกส่งไปยังพวกเขาหาก parent parent ได้รับ (เช่นถ้าผู้ใช้ล็อกเอาต์)

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

    รับค่าของคอลัมน์ที่สี่ของไฟล์/proc/$PPID/stat(เช่น/proc/1/statส่งคืน 0)


ฉันคิดว่าคำสั่ง $$ รับเป็น pid ของเทอร์มินัล ... นั่นเป็นทางเลือกหรือไม่? คุณสามารถอธิบายวิธีการปฏิเสธได้อย่างไร
ทิม

สคริปต์นี้ทำเช่นนั้นได้อย่างไร ฉันยังใหม่กับการเขียนสคริปต์เชลล์ดังนั้นฉันจึงไม่สามารถเข้าใจคำสั่งเหล่านั้นได้ คุณช่วยอธิบายวิธีปิดเทอร์มินัลได้อย่างไร
Rumesh

1
@Tim ไม่มันส่งคืนเชลล์ในเทอร์มินัล: ps xa | grep $$=> 4381 pts/0 Ss 0:01 /usr/bin/zsh
AB

1
@RumeshSudhaharan มันฆ่าหน้าต่างเทอร์มินัลทั้งหมดที่สคริปต์เริ่มทำงาน แต่ไม่มีหน้าต่างเทอร์มินัลอื่น
AB

3
@AB ก่อนหน้านี้คุณบอกว่านี่เป็นการฆ่าหน้าต่างเทอร์มินัลปัจจุบันเท่านั้น ฉันใช้สคริปต์นี้วันนี้โดยเปิดหน้าต่างเทอร์มินัลสองหน้าต่างและทั้งคู่ถูกฆ่าเมื่อฉันรันสคริปต์
Rumesh

4

คุณสามารถใช้exec ./your-script

เครื่องมือจำลองเทอร์มินัลเช่น GNOME ออกจากโปรแกรมเมื่อกระบวนการเริ่มต้นทำงานอยู่ภายในซึ่งโดยปกติจะเป็นเชลล์

หากคุณอยู่ในเทอร์มินัลแล้วและสิ่งเดียวที่คุณต้องการทำก่อนที่จะออกจากเทอร์มินัลนั้นคือการเรียกใช้สคริปต์ (หรือโปรแกรม) โดยเฉพาะนั่นหมายความว่าคุณไม่จำเป็นต้องใช้เชลล์ที่ทำงานอยู่อีกต่อไป ดังนั้นคุณสามารถใช้execbuiltin ของเชลล์เพื่อให้เชลล์แทนที่ตัวเองด้วยกระบวนการที่สร้างโดยคำสั่งของคุณ

  • ในกรณีของสคริปต์ของคุณว่าเป็นกระบวนการของเชลล์ - เช่นเดียวกับวิธีการที่สองexecกระบวนการเปลือกถูกสร้างขึ้นเมื่อคุณเรียกใช้สคริปต์โดยไม่ต้อง

ไวยากรณ์เช่นexec commandexec ./your-script

exec: ตัวอย่าง

ตัวอย่างเช่นสมมติว่าฉันมีเชลล์สคริปต์ชื่อcountทำเครื่องหมายเรียกใช้และอยู่ในไดเรกทอรีปัจจุบัน มันมี:

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

และใน terminal ฉันทำงาน:

exec ./count

พิมพ์นี้เลข5, 4, 3, 2และ1หนึ่งต่อวินาทีและจากนั้นสถานีปิดหน้าต่าง

หากคุณทำงานนี้จากสิ่งอื่นนอกเหนือจากขั้นตอนการทำงานครั้งแรกของคุณในขั้ว - ตัวอย่างเช่นถ้าคุณวิ่งbashคนแรกที่จะเริ่มต้นเช่นเปลือกอีก - แล้วนี้จะนำคุณกลับไปยังเปลือกที่สร้างว่ากระบวนการมากกว่าการเลิกขั้ว (คำเตือนนี้ใช้กับexitวิธีการแบบอิง)

คุณสามารถใช้./your-script; exit

หากคุณไม่ต้องการบอกให้เชลล์แทนที่ตัวเองด้วยกระบวนการใหม่ (ผ่านexec) คุณสามารถบอกให้มันติดอยู่ แต่ออกจากตัวเองทันทีหลังจากกระบวนการใหม่เสร็จสิ้น

หากต้องการทำสิ่งนี้ให้เรียกใช้คำสั่งและคำสั่งของคุณexitโดยคั่นด้วย;เพื่อให้พวกเขาสามารถได้รับในบรรทัดเดียว

ไวยากรณ์เช่นcommand; exit./your-script; exit

command; exit เมื่อเทียบกับ command && exit

คุณอาจสังเกตเห็นว่าสิ่งนี้ดูคล้ายกับวิธีที่แนะนำในคำตอบของkosและheemayl ความแตกต่างคือ:./your-script && exit

  • &&รันคำสั่งที่สองก็ต่อเมื่อคำสั่งแรกรายงานว่าประสบความสำเร็จโดยส่งคืนโค้ดออกจากศูนย์
  • ; รันคำสั่งที่สองไม่ว่าคำสั่งแรกจะรายงานความสำเร็จหรือไม่ก็ตาม

สิ่งที่คุณต้องการขึ้นอยู่กับสถานการณ์ที่เฉพาะเจาะจง หากคำสั่งล้มเหลวคุณต้องการให้เชลล์การโทร (และโฮสติ้งเทอร์มินัล) อยู่ต่อไปหรือไม่? ถ้าเป็นเช่นนั้นใช้&&; ;หากไม่ได้ใช้งาน

นอกจากนี้ยังมีcommand || exitซึ่งจบการทำงานเปลือกโทรเฉพาะในกรณีที่commandรายงานความล้มเหลว


2

คุณสามารถแหล่งสคริปต์ของคุณแทนที่จะเรียกใช้เช่น

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

1

โดยส่วนตัวแล้วฉันจะใช้คำสั่งเพื่อเปิดไฟล์ pdf หรือไฟล์อื่น ๆ ใน subshell, ทำการหน่วงเวลาเพื่อให้ไฟล์เปิดและออกจาก นี่คือสิ่งที่ฉันทดสอบ(nohup gnome-open *.pdf &); sleep 2; exit

การเปลี่ยนแปลงในครั้งนี้ก็จะเป็น nohup gnome-open *.pdf && sleep 2 && exit


ในกรณีของฉันเนื่องจากnohupไม่สนใจสัญญาณ Hangup nohup xdg-open some_programทำงานสำหรับฉันและexitไม่จำเป็น nohupเปลี่ยนเส้นทางข้อความไปยังnohup.outไฟล์:nohup: ignoring input and appending output to nohup.out
nick indiessance

0

ทางออกที่ง่ายที่สุดคือ:

xdg-open file.pdf && exit

ไม่เหมือนกับคำสั่งที่คล้ายกันอื่น ๆ ที่nohupไม่ต้องการให้คำสั่งเพิกเฉยSIGHUPเหตุผลที่xdg-openจะออกจากการวางไข่กระบวนการลูกซึ่งเป็นแอพพลิเคชั่นที่ต้องการเพื่อเปิดไฟล์ pdf เนื่องจากกระบวนการจริงที่เริ่มต้นจากเทอร์มินัลไม่มีการฆ่าอีกต่อไปnohupจึงไม่จำเป็น

&&บ่งชี้ว่าคำสั่งถัดไปจะทำงานหากคำสั่งก่อนหน้านี้ประสบความสำเร็จเช่นส่งคืนรหัสออก0( $?=0) และexitจะปิดสถานี


ฉันคิดว่าเขาบอกว่าทางออกไม่ทำงาน ...
ทิม

@ ทิม: บางที OP ไม่ได้ใช้มันอย่างถูกต้องจากคำถามที่ไม่ชัดเจนสำหรับฉันเขา / เธอทำอย่างไรexitในตอนท้ายและไม่ทำงาน ..
heemayl

1
@Tim เนื่องจาก OP ใส่exitสคริปต์ไว้ซึ่งไม่ได้ผลเพราะมีผลในการออกจากbashอินสแตนซ์ที่สคริปต์ถูกดำเนินการค่อนข้างจะเป็นbashอินสแตนซ์หลัก(อันที่เชื่อมโยงกับเทอร์มินัล) ซึ่งจะทำให้เทอร์มินัลปิดแทน
kos

1
อย่างไรก็ตามxdg-openทำงานอยู่ในพื้นหลังและยกเลิกการเชื่อมโยงจากสถานีเพื่อให้คุณไม่จำเป็นต้องnohupที่นี่บวกจากสิ่งที่ฉันเข้าใจ OP ทำงานxdg-openหลายครั้งภายในสคริปต์ชุดเปิดไฟล์หลายไฟล์โดยใช้xdg-openที่ต้องการที่อยู่ภายในสคริปต์ที่จะทำให้เกิดสคริปต์ เพื่อออกเมื่อxdg-openเกิดขึ้นครั้งแรก
kos

@kos: ไม่ฉันไม่ได้ทำงานxdg-openใน backgr แม้ว่าฉันnohupจะมีเหตุผลที่แตกต่างกันและจะต้องมี .. กระบวนการพื้นหลังใด ๆ จากอาคารผู้โดยสารต้นทางจะถูกฆ่าเมื่อคุณจะฆ่าผู้ปกครองสถานี .. nohupจะมีการป้องกัน มัน .. ฉันไม่ต้องการใช้เทอร์มินัลแบบโต้ตอบอีกครั้งไม่จำเป็นต้องใส่กระบวนการใน bg .. ณ จุดที่ 2 ของคุณที่สามารถป้องกันได้ด้วยการทำงานแต่ละอย่างxdg-open && exitใน subshell ..
heemayl

0

เพื่อตอบคำถามคำถามอย่างชัดเจน

"ออกจากเทอร์มินัลหลังจากรันสคริปต์ทุบตี" :

เรียกใช้สคริปต์ของคุณเฉพาะในเทอร์มินัล

โดยไม่ดูรายละเอียดสิ่งที่สคริปต์ทำสคริปต์สามารถเรียกใช้โดยตรงภายในเทอร์มินัลด้วยตัวเลือก-e( --command) โดยไม่ต้องเริ่มเชลล์ - มันถูกใช้แทนเชลล์แล้ว:

gnome-terminal -e ./script.sh

ใช้ตัวเลือก-x( --execute) เมื่อคุณต้องการระบุอาร์กิวเมนต์ของสคริปต์ ด้วยสิ่งนี้ส่วนที่เหลือทั้งหมดของ commandline จึงถูกใช้เป็นคำสั่งและอาร์กิวเมนต์

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

หากสคริปต์ของคุณออกมาจะไม่มีเชลล์แบบโต้ตอบที่สามารถระงับสิ่งใด ๆ ได้โดยรอการป้อนข้อมูลจากผู้ใช้

ตัวอย่าง

เทอร์มินัลจะออกจากหลังจากที่คำสั่งรันอยู่ - เช่นนี้การปิดหลังจากsleepรัน 4 วินาทีโดยไม่มีเชลล์:

gnome-terminal -x sleep 4

แน่นอนคุณสามารถใช้เชลล์สคริปต์ได้เนื่องจากสคริปต์ของคุณใช้เชลล์อินสแตนซ์อื่นอยู่ดี

นอกจากนี้คุณสามารถเรียกใช้เชลล์ด้วยสคริปต์ที่ชัดเจน - มันจะไม่ทำงานแบบโต้ตอบ:

gnome-terminal -x bash -c "echo 'Hello!'; sleep 4"
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.