วิธีรันคำสั่งหลังจากที่รันไปแล้วคำสั่งที่มีอยู่เสร็จสิ้นแล้ว?


32

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

ตัวอย่างเช่นถ้าฉันวิ่ง:

really_long_script.sh

และกด Enter ... ฉันจะเรียกใช้คำสั่งอื่นได้อย่างไรเมื่อมันเสร็จสิ้น?

คำตอบ:


45

คุณสามารถแยกหลายคำสั่งได้โดย;ดำเนินการตามลำดับเช่น:

really_long_script.sh ; echo Finished

หากคุณต้องการรันโปรแกรมถัดไปเฉพาะเมื่อสคริปต์จบด้วยโค้ดส่งคืน 0 (ซึ่งโดยปกติจะหมายความว่าสคริปต์ทำงานได้อย่างถูกต้อง) จากนั้น:

really_long_script.sh && echo OK

หากคุณต้องการตรงกันข้าม (เช่นดำเนินการต่อเฉพาะเมื่อคำสั่งปัจจุบันล้มเหลว) กว่า:

really_long_script.sh || echo FAILED

คุณสามารถเรียกใช้สคริปต์ของคุณในพื้นหลัง (แต่ระวังเอาท์พุทสคริปต์ ( stdoutและstderr) จะยังคงไปที่เทอร์มินัลของคุณจนกว่าคุณจะเปลี่ยนเส้นทางที่อื่น) และจากนั้นwait:

really_long_script.sh &
dosomethingelse
wait; echo Finished

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

fg ; echo Finished

ที่fgทำให้กระบวนการที่ถูกระงับไปอยู่เบื้องหน้า ( bgจะทำให้มันทำงานในพื้นหลังเหมือนเริ่มต้นด้วย&)


@mlissner ขยายคำตอบของฉันเพื่อให้ครอบคลุมกรณีนี้
Aland

8
เนื่องจากfgส่งคืนค่าของงานที่ดำเนินการต่อคุณสามารถใช้fg && echo Finishedหากคุณต้องการให้แน่ใจว่าคำสั่งสำเร็จก่อนที่จะดำเนินการคำสั่งอื่น
palswim

13

นอกจากนี้คุณยังสามารถใช้การควบคุมงานของ bash ถ้าคุณเริ่ม

$ really_long_script.sh

จากนั้นกด ctrl + z เพื่อระงับ:

^Z
[1]+  Stopped                 really_long_script.sh
$ bg

เพื่อเริ่มงานในพื้นหลัง (เช่นถ้าเริ่มต้นด้วยreally_long_script.sh &) จากนั้นคุณสามารถรองานพื้นหลังนี้ด้วย

$ wait N && echo "Successfully completed"

โดยที่ N คือ ID งาน (อาจเป็น 1 ถ้าคุณไม่ได้เรียกใช้งานพื้นหลังอื่น ๆ ) ซึ่งจะแสดงตาม[1]ด้านบน


11

หากกระบวนการไม่ทำงานบน tty ปัจจุบันให้ลองทำดังนี้:

watch -g ps -opid -p <pid>; mycommand

2
watchฉันรักการใช้ความคิดสร้างสรรค์ของ คำตอบสั้น ๆ สุดยอดและหนึ่งเรียนรู้วิธีการใช้นาฬิกาที่มีประโยชน์ใหม่
Piotr Czapla

2

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

ฉันเดาว่ามันมีวิธีที่สง่างามกว่า แต่มันก็ใช้งานได้ดี

การแก้ไขเพื่อเพิ่มว่าถ้าคุณต้องการเรียกใช้การแจ้งเตือนหลังจากที่คำสั่งเสร็จสิ้นคุณสามารถสร้างนามแฝงเหล่านี้ใน. bashrc จากนั้นเรียกใช้alertขณะที่มันกำลังทำงานอยู่:

 alias alert_helper='history|tail -n1|sed -e "s/^\s*[0-9]\+\s*//" -e "s/;\s*alert$//"'
 alias alert='notify-send -i gnome-terminal "Finished Terminal Job" "[$?] $(alert_helper)"'

7
ยกเว้นว่าสคริปต์ที่รันอยู่จะคาดว่าอินพุตในจุดเดียว
Daniel Beck

@Daniel - ใช่ ... นั่นเป็นปัญหา ยิง.
mlissner

1

ไม่นานมานี้ฉันได้เขียนสคริปต์เพื่อรอการสิ้นสุดของกระบวนการอื่น NOISE_CMDอาจเป็นสิ่งที่ต้องการnotify-send ...เนื่องจากDISPLAYมีการตั้งค่าไว้อย่างถูกต้อง

#!/bin/bash

NOISE_CMD="/usr/bin/mplayer -really-quiet $HOME/sfx/alarm-clock.mp3"

function usage() {
    echo "Usage: $(basename "$0") [ PROCESS_NAME [ PGREP_ARGS... ] ]"
    echo "Helpful arguments to pgrep are: -f -n -o -x"
}

if [ "$#" -gt 0 ] ; then
    PATTERN="$1"
    shift
    PIDS="$(pgrep "$PATTERN" "$@")"

    if [ -z "$PIDS" ] ; then
        echo "No process matching pattern \"$PATTERN\" found."
        exit
    fi

    echo "Waiting for:"
    pgrep -l "$PATTERN" "$@"

    for PID in $PIDS ; do
        while [ -d "/proc/$PID" ] ; do
            sleep 1
        done
    done
fi

exec $NOISE_CMD

โดยไม่มีข้อโต้แย้งใด ๆ เพียงทำเสียงดังทันที พฤติกรรมนี้อนุญาตให้ใช้สิ่งนี้เพื่อความสะดวก (บอกว่าคุณเรียกสคริปต์ด้านล่างalarm.sh):

apt-get upgrade ; ~/bin/alarm.sh

แน่นอนว่าคุณสามารถทำสิ่งต่าง ๆ ที่ตลก ๆ ด้วยสคริปต์เช่นปล่อยให้เป็นตัวอย่างของการalarm.shรอตัวอย่างalarm.shซึ่งกำลังรอคำสั่งอื่นอยู่ หรือดำเนินการคำสั่งทันทีหลังจากงานของผู้ใช้ที่เข้าสู่ระบบรายอื่นเสร็จสิ้นแล้ว ... >: D

เวอร์ชันเก่าของสคริปต์ด้านบนอาจน่าสนใจถ้าคุณต้องการหลีกเลี่ยงการพึ่งพาpgrepและยอมรับการค้นหา ID กระบวนการด้วยตัวคุณเอง:

#!/bin/bash

if [ "$#" -lt 2 -o ! -d "/proc/$1" ] ; then
  echo "Usage: $(basename "$0") PID COMMAND [ ARGUMENTS... ]"
  exit
fi

while [ -d "/proc/$1" ] ; do
  sleep 1
done

shift
exec "$@"

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.