Dalam skrip shell, bagaimana saya bisa (1) memulai perintah di latar belakang (2) menunggu x detik (3) menjalankan perintah kedua saat perintah itu sedang berjalan?


11

Inilah yang saya butuhkan untuk terjadi:

  1. mulai proses A di latar belakang
  2. tunggu x detik
  3. mulai proses B di latar depan

Bagaimana saya bisa membuat penantian terjadi?

Saya melihat bahwa 'tidur' sepertinya menghentikan segalanya dan saya tidak benar-benar ingin 'menunggu' proses A selesai sepenuhnya. Saya telah melihat beberapa loop berdasarkan waktu tetapi saya bertanya-tanya apakah ada sesuatu yang lebih bersih.


4
Saya menyarankan agar Anda meningkatkan pertanyaan ini dengan memberikan contoh sederhana tentang apa yang sudah Anda coba.
— Andy Dalton

10
Di mana Anda mendapatkan kesan yang sleepmenghentikan proses-A? Bisakah Anda menunjukkan proses pengujian yang Anda gunakan, atau menampilkan indikasi ini? Jika proses-A adalah tersendat-sendat, itu lebih mungkin bahwa itu mencoba membaca dari terminal sementara berjalan di latar belakang dan mendapatkan dihentikan karena alasan itu, bukan sesuatu yang berhubungan dengan sleep.
— Charles Duffy

3
... jika itu adalah kasus, process_a </dev/null &akan melampirkan stdin untuk /dev/nulldaripada TTY, dan yang mungkin cukup untuk menghindari masalah tersebut.
— Charles Duffy

Dari pengalaman saya, tidur hanya akan memblokir proses saat ini dan dengan demikian bukan proses yang sebelumnya dimulai di latar belakang dengan &
— MADforFUNandHappy

Jawaban:


28

Kecuali jika saya salah memahami pertanyaan Anda, itu bisa dicapai dengan skrip pendek ini:

#!/bin/bash

process_a &
sleep x
process_b

(dan tambahkan tambahan waitdi bagian akhir jika Anda ingin skrip Anda menunggu process_ahingga selesai sebelum keluar).

Anda bahkan dapat melakukan ini sebagai satu-liner, tanpa perlu skrip (seperti yang disarankan oleh @BaardKopperud):

process_a & sleep x ; process_b

6
Perhatikan bahwa Anda tidak perlu bashuntuk itu, shell apa pun akan termasuk sistem Anda sh, jadi Anda tidak perlu menambahkan ketergantungan pada bash untuk skrip Anda.
— Stéphane Chazelas

4
Atau cukup: process_a & sleep x; process_b
— Baard Kopperud

9

Anda dapat menggunakan operator kontrol latar belakang (&) untuk menjalankan proses di latar belakang dan sleepperintah untuk menunggu sebelum menjalankan proses kedua, yaitu:

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

command1 &
sleep x
command2

Berikut adalah contoh dari dua perintah yang mencetak beberapa pesan bertanda waktu:

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

Jalankan untuk memverifikasi bahwa ia menunjukkan perilaku yang diinginkan:

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
Pertanyaannya adalah untuk "memulai proses B di latar depan ".
— Sparhawk

1
@Sparhawk Wow. Benar-benar salah baca itu - tidak ada penjelasan. Terima kasih atas head-up - kode diperbaiki. Nostalgia serius dari nama pengguna Anda, btw.
— igal

1
Jangan khawatir! (Juga nama pengguna pada awalnya adalah referensi untuk bab ini , tetapi saya kemudian baru menyadari bahwa itu adalah karakter Eddings! Dan membuat saya ingin membaca kembali buku-buku itu ...)
— Sparhawk

5

Saya suka jawaban @ dr01 tetapi dia tidak memeriksa kode keluar dan jadi Anda tidak tahu apakah Anda berhasil atau tidak.

Inilah solusi yang memeriksa kode keluar.

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

biasanya saya menyimpan PID dalam array bash dan kemudian memeriksa pid adalah untuk loop.


2
Anda mungkin ingin mencerminkan kode keluar tersebut dalam status keluar dari skrip Anda sepertiA & sleep x; B; ret=$?; wait "$!" || exit "$ret"
— Stéphane Chazelas

1
@ StéphaneChazelas ide bagus. saya memperbarui kode untuk memastikan kode keluar yang tidak nol dikembalikan jika salah satu atau keduanya gagal.
— Trevor Boyd Smith

OP ingin process_bberjalan di latar depan. Agaknya process_abisa keluar saat process_bsedang berjalan, tetapi Anda masih bisa waituntuk itu dan mendapatkan status keluar setelah Anda mengumpulkan status keluar dari latar depan process_bdengan cara biasa, dengan $?langsung.
— Peter Cordes
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.