Trong tập lệnh shell, làm thế nào tôi (1) có thể bắt đầu một lệnh trong nền (2) chờ x giây (3) chạy lệnh thứ hai trong khi lệnh đó đang chạy?


11

Đây là những gì tôi cần phải xảy ra:

  1. bắt đầu quá trình A trong nền
  2. chờ trong x giây
  3. bắt đầu quá trình B ở phía trước

Làm thế nào tôi có thể làm cho sự chờ đợi xảy ra?

Tôi đang thấy rằng 'giấc ngủ' dường như dừng mọi thứ lại và tôi thực sự không muốn 'chờ đợi' để quá trình A hoàn thành. Tôi đã thấy một số vòng lặp dựa trên thời gian nhưng tôi tự hỏi nếu có cái gì đó sạch hơn.


4
Tôi đề nghị bạn tăng cường câu hỏi này bằng cách cung cấp một ví dụ đơn giản về những gì bạn đã thử.
Andy Dalton

10
Nơi nào bạn có ấn tượng sleepdừng quá trình-A? Bạn có thể hiển thị quá trình kiểm tra bạn đang sử dụng, hoặc chỉ ra đầu ra của điều này? Nếu tiến trình A đang tạm dừng, nhiều khả năng nó đang cố đọc từ thiết bị đầu cuối trong khi chạy ở chế độ nền và bị tạm dừng vì lý do đó, hơn là bất cứ điều gì liên quan sleep.
Charles Duffy

3
... Nếu đó trường hợp, process_a </dev/null &sẽ đính kèm stdin của nó /dev/nullchứ không phải TTY, và điều đó có thể đủ để tránh vấn đề.
Charles Duffy

Theo kinh nghiệm của tôi, giấc ngủ sẽ chỉ chặn quá trình hiện tại và do đó, không phải quá trình trước đó đã bắt đầu trong nền với &
MADforFUNandHappy

Câu trả lời:


28

Trừ khi tôi hiểu nhầm câu hỏi của bạn, đơn giản là có thể đạt được với kịch bản ngắn này:

#!/bin/bash

process_a &
sleep x
process_b

(và thêm một phần bổ sung waitvào cuối nếu bạn muốn tập lệnh của mình đợi process_akết thúc trước khi thoát).

Bạn thậm chí có thể làm điều này như một lớp lót, mà không cần tập lệnh (như được đề xuất bởi @BaardKopperud):

process_a & sleep x ; process_b

6
Lưu ý rằng bạn không cần bashđiều đó, bất kỳ trình bao nào cũng sẽ bao gồm cả hệ thống của bạn sh, vì vậy bạn không cần thêm phụ thuộc vào bash cho tập lệnh của mình.
Stéphane Chazelas

4
Hoặc đơn giản là: process_a & ngủ x; process_b
Baard Kopperud

9

Bạn có thể sử dụng toán tử điều khiển nền (&) để chạy một tiến trình trong nền và sleeplệnh chờ trước khi chạy tiến trình thứ hai, tức là:

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

command1 &
sleep x
command2

Dưới đây là một ví dụ về hai lệnh in ra một số thông điệp có dấu thời gian:

#!/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

Chạy nó để xác minh rằng nó thể hiện hành vi mong muốn:

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
Câu hỏi yêu cầu "bắt đầu quá trình B ở phía trước ".
Sparhawk

1
@Sparhawk Wow. Hoàn toàn hiểu sai rằng - không có lời giải thích. Cảm ơn các head-up - mã đã được sửa. Nỗi nhớ nghiêm túc từ tên người dùng của bạn, btw.
igal

1
Đừng lo lắng! (Ngoài ra tên người dùng ban đầu là một tham chiếu đến chap này , nhưng sau đó tôi chỉ nhận ra đó là một nhân vật Eddings! Và khiến tôi muốn đọc lại những cuốn sách đó)
Sparhawk

5

Tôi thích câu trả lời của @ dr01 nhưng anh ấy không kiểm tra mã thoát và vì vậy bạn không biết mình có thành công hay không.

Đây là một giải pháp kiểm tra các mã thoát.

#!/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}

thông thường tôi lưu trữ các PID trong một mảng bash và sau đó kiểm tra pid là một vòng lặp for.


2
Bạn có thể muốn phản ánh các mã thoát đó trong trạng thái thoát của tập lệnh của mình nhưA & sleep x; B; ret=$?; wait "$!" || exit "$ret"
Stéphane Chazelas

1
@ StéphaneChazelas ý tưởng tốt. tôi đã cập nhật mã để đảm bảo mã thoát khác không được trả về nếu một hoặc cả hai không thành công.
Trevor Boyd Smith

OP muốn process_bchạy ở phía trước. Có lẽ process_acó thể thoát trong khi process_bđang chạy, nhưng bạn vẫn có thể waitcho nó và nhận trạng thái thoát sau khi bạn đã thu thập trạng thái thoát của tiền cảnh process_btheo cách thông thường, với $?trực tiếp.
Peter Cordes
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.