ในเชลล์สคริปต์ฉันจะ (1) เริ่มคำสั่งในพื้นหลังได้อย่างไร (2) รอ x วินาที (3) เรียกใช้คำสั่งที่สองขณะที่คำสั่งนั้นกำลังทำงานอยู่


11

นี่คือสิ่งที่ฉันต้องเกิดขึ้น:

  1. เริ่มกระบวนการ A ในพื้นหลัง
  2. รอ x วินาที
  3. เริ่มกระบวนการ B ในเบื้องหน้า

ฉันจะรอให้เกิดขึ้นได้อย่างไร

ฉันเห็นว่า 'หลับ' ดูเหมือนว่าจะหยุดทุกอย่างและฉันไม่ต้องการ 'รอ' เพื่อให้กระบวนการ A สิ้นสุดโดยสิ้นเชิง ฉันเคยเห็นลูปเป็นระยะเวลาหนึ่งแล้ว แต่ฉันสงสัยว่ามีบางอย่างที่สะอาดกว่านี้หรือไม่


4
ฉันขอแนะนำให้คุณปรับปรุงคำถามนี้โดยแสดงตัวอย่างง่ายๆของสิ่งที่คุณได้ลองไปแล้ว
Andy Dalton

10
คุณจะได้รับการแสดงผลที่sleepหยุดกระบวนการ - ที่ไหน คุณสามารถแสดงกระบวนการทดสอบที่คุณใช้หรือแสดงผลลัพธ์ของสิ่งนี้ได้หรือไม่ หากกระบวนการ-A เป็นsleepง่อยก็มากขึ้นโอกาสที่มันพยายามที่จะอ่านจากขั้วในขณะที่ทำงานในพื้นหลังและได้รับการหยุดด้วยเหตุผลที่มากกว่าสิ่งที่เกี่ยวข้องกับ
Charles Duffy

3
... หากเป็นกรณีนี้process_a </dev/null &จะแนบ stdin เข้ากับ/dev/nullแทนที่จะเป็น TTY และนั่นอาจเพียงพอที่จะหลีกเลี่ยงปัญหา
Charles Duffy

จากประสบการณ์การนอนหลับของฉันจะบล็อกกระบวนการปัจจุบันเท่านั้นและไม่ใช่กระบวนการที่เริ่มต้นก่อนหน้านี้ในพื้นหลังด้วย &
MADforFUNandHappy

คำตอบ:


28

เว้นแต่ฉันจะเข้าใจผิดคำถามของคุณก็สามารถทำได้ด้วยสคริปต์สั้น ๆ นี้:

#!/bin/bash

process_a &
sleep x
process_b

(และเพิ่มwaitส่วนท้ายถ้าคุณต้องการให้สคริปต์ของคุณรอprocess_aให้เสร็จก่อนออก)

คุณสามารถทำสิ่งนี้ในฐานะหนึ่งซับในโดยไม่จำเป็นต้องใช้สคริปต์ (ตามที่แนะนำโดย @BaardKopperud):

process_a & sleep x ; process_b

6
โปรดทราบว่าคุณไม่ต้องการbashสิ่งนั้นเชลล์จะรวมถึงระบบของshคุณดังนั้นคุณไม่จำเป็นต้องเพิ่มการพึ่งพา bash สำหรับสคริปต์ของคุณ
Stéphane Chazelas

4
หรือเพียงแค่: process_a & sleep x; process_b
Baard Kopperud

9

คุณสามารถใช้โอเปอเรเตอร์ควบคุมพื้นหลัง (&)เพื่อเรียกใช้โปรเซสในแบ็คกราวน์และsleepคำสั่งรอก่อนที่จะรันโปรเซสที่สองเช่น:

#!/usr/bin/env bash
# script.sh

command1 &
sleep x
command2

นี่คือตัวอย่างของสองคำสั่งที่พิมพ์ข้อความประทับเวลา:

#!/usr/bin/env bash

# Execute a process in the background
echo "$(date) - Running first process in the background..."
for i in {1..1000}; do
    echo "$(date) - I am running in the background";
    sleep 1;
done &> background-process-output.txt &

# Wait for 5 seconds
echo "$(date) - Sleeping..."
sleep 5 

# Execute a second process in the foreground
echo "$(date) - Running second process in the foreground..."
for i in {1..1000}; do
    echo "$(date) - I am running in the foreground";
    sleep 1;
done

เรียกใช้เพื่อตรวจสอบว่ามันแสดงพฤติกรรมที่ต้องการ:

user@host:~$ bash script.sh

Fri Dec  1 13:41:10 CST 2017 - Running first process in the background...
Fri Dec  1 13:41:10 CST 2017 - Sleeping...
Fri Dec  1 13:41:15 CST 2017 - Running second process in the foreground...
Fri Dec  1 13:41:15 CST 2017 - I am running in the foreground
Fri Dec  1 13:41:16 CST 2017 - I am running in the foreground
Fri Dec  1 13:41:17 CST 2017 - I am running in the foreground
Fri Dec  1 13:41:18 CST 2017 - I am running in the foreground
Fri Dec  1 13:41:19 CST 2017 - I am running in the foreground
Fri Dec  1 13:41:20 CST 2017 - I am running in the foreground
...
...
...

2
คำถามที่ถามว่า "กระบวนการเริ่มต้น B ในเบื้องหน้า "
Sparhawk

1
@Sparhawk ว้าว ผิดทั้งหมด - ไม่มีคำอธิบาย ขอบคุณสำหรับ heads-up - แก้ไขรหัสแล้ว ความคิดถึงอย่างจริงจังจากชื่อผู้ใช้ของคุณ btw
igal

1
ไม่ต้องห่วง! (เช่นเดิมชื่อผู้ใช้เป็นข้อมูลอ้างอิงของบทนี้แต่ฉันเพิ่งรู้ว่ามันเป็นตัวละครของ Eddings! และทำให้ฉันต้องการอ่านหนังสือเหล่านั้นอีกครั้ง ... )
Sparhawk

5

ฉันชอบคำตอบของ @ dr01 แต่เขาไม่ตรวจสอบรหัสออกดังนั้นคุณจึงไม่รู้ว่าคุณประสบความสำเร็จหรือไม่

นี่คือทางออกที่ตรวจสอบ exitcodes

#!/bin/bash

# run processes
process_a &
PID1=$!
sleep x
process_b &
PID2=$!
exitcode=0

# check the exitcode for process A
wait $PID1    
if (($? != 0)); then
    echo "ERROR: process_a exited with non-zero exitcode" >&2
    exitcode=$((exitcode+1))
fi

# check the exitcode for process B
wait $PID2
if (($? != 0)); then
    echo "ERROR: process_b exited with non-zero exitcode" >&2
    exitcode=$((exitcode+1))
fi
exit ${exitcode}

ฉันมักจะเก็บ PIDs ในอาเรย์ของ bash และจากนั้นการตรวจสอบ pid นั้นจะใช้สำหรับลูป


2
คุณอาจต้องการแสดงรหัสการออกในสถานะการออกของสคริปต์เช่นA & sleep x; B; ret=$?; wait "$!" || exit "$ret"
Stéphane Chazelas

1
@ StéphaneChazelasเป็นความคิดที่ดี ฉันอัปเดตรหัสเพื่อให้แน่ใจว่ามีการส่งคืน exitcode ที่ไม่เป็นศูนย์หากหนึ่งหรือทั้งสองล้มเหลว
เทรเวอร์บอยด์สมิ ธ

OP ต้องการให้process_bทำงานในเบื้องหน้า สันนิษฐานว่าprocess_aสามารถออกได้ในขณะที่process_bกำลังทำงานอยู่ แต่คุณยังคงสามารถทำได้waitและรับสถานะการออกหลังจากที่คุณได้รวบรวมสถานะการออกของเบื้องหน้าprocess_bด้วยวิธีปกติด้วย$?โดยตรง
Peter Cordes
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.