Saya tahu saya bisa menunggu dengan syarat untuk menjadi kenyataan di bash dengan melakukan:
while true; do
test_condition && break
sleep 1
done
Tapi itu menciptakan 1 sub-proses di setiap iterasi (tidur). Saya bisa menghindarinya dengan melakukan:
while true; do
test_condition && break
done
Tetapi menggunakan banyak CPU (sibuk menunggu). Untuk menghindari sub-proses dan menunggu sibuk, saya datang dengan solusi di bawah, tapi saya merasa jelek:
my_tmp_dir=$(mktemp -d --tmpdir=/tmp) # Create a unique tmp dir for the fifo.
mkfifo $my_tmp_dir/fifo # Create an empty fifo for sleep by read.
exec 3<> $my_tmp_dir/fifo # Open the fifo for reading and writing.
while true; do
test_condition && break
read -t 1 -u 3 var # Same as sleep 1, but without sub-process.
done
exec 3<&- # Closing the fifo.
rm $my_tmp_dir/fifo; rmdir $my_tmp_dir # Cleanup, could be done in a trap.
Catatan: dalam kasus umum, saya tidak bisa begitu saja menggunakan read -t 1 var
tanpa fifo, karena akan mengkonsumsi stdin, dan tidak akan berfungsi jika stdin bukan terminal atau pipa.
Bisakah saya menghindari sub-proses dan sibuk menunggu dengan cara yang lebih elegan?
bash
shell-script
sleep
jfg956
sumber
sumber
true
adalah builtin dan tidak membuat sub proses dalam bash. penantian yang sibuk akan selalu buruk.true
, pertanyaan diperbarui.read -t 1 var
.sleep
seperti pada contoh pertama. Yang kedua, meskipun mungkin berhasil, tidak akan mudah bagi siapa pun untuk menyesuaikan diri di masa depan. Kode sederhana juga memiliki potensi lebih besar untuk aman.Jawaban:
Dalam versi terbaru
bash
(setidaknya v2), builtin dapat dimuat (viaenable -f filename commandname
) saat runtime. Sejumlah builtin yang dapat dimuat tersebut juga didistribusikan dengan sumber bash, dansleep
ada di antara mereka. Ketersediaan mungkin berbeda dari OS ke OS (dan bahkan mesin ke mesin), tentu saja. Sebagai contoh, pada openSUSE, bawaan ini didistribusikan melalui paketbash-loadables
.Edit: perbaiki nama paket, tambahkan versi bash minimum.
sumber
sleep
sebagai builtin. Terima kasih.Membuat banyak subproses adalah hal yang buruk di loop dalam. Membuat satu
sleep
proses per detik adalah OK. Tidak ada yang salah dengan ituJika Anda benar-benar ingin menghindari proses eksternal, Anda tidak perlu membiarkan fifo tetap terbuka.
sumber
mkdir
seperti yang dilakukan olehmktemp
(jika tidak, ini adalah kondisi balapan)). Juga benar tentangwhile ! test_condition;
yang lebih bagus daripada solusi awal saya.Saya baru-baru ini perlu melakukan ini. Saya datang dengan fungsi berikut yang akan memungkinkan bash untuk tidur selamanya tanpa memanggil program eksternal apa pun:
CATATAN: Saya sebelumnya memposting versi ini yang akan membuka dan menutup deskriptor file setiap kali, tetapi saya menemukan bahwa pada beberapa sistem melakukan ini ratusan kali per detik akhirnya akan terkunci. Dengan demikian solusi baru membuat deskriptor file antara panggilan ke fungsi. Bash akan membersihkannya saat keluar.
Ini bisa disebut seperti / bin / sleep, dan itu akan tidur untuk waktu yang diminta. Disebut tanpa parameter, itu akan menggantung selamanya.
Ada langganan dengan rincian berlebihan di blog saya di sini
sumber
read -t 10 < <(:)
kembali segera sambilread -t 10 <> <(:)
menunggu 10 detik penuh, tapi saya masih belum mengerti.read -t 10 <> <(:)
apa<>
stand for?Di
ksh93
ataumksh
,sleep
adalah shell builtin, jadi alternatifnya mungkin menggunakan shell itu alih-alihbash
.zsh
juga memilikizselect
builtin (sarat denganzmodload zsh/zselect
) yang dapat tidur selama beberapa ratus detikzselect -t <n>
.sumber
Seperti kata pengguna yoi , jika dalam skrip Anda dibuka stdin , maka alih-alih tidur 1 Anda cukup menggunakan:
Dalam Bash versi 4.1 dan yang lebih baru Anda dapat menggunakan nomor float, mis
read -t 0.3 ...
Jika dalam skrip, stdin ditutup (skrip dipanggil
my_script.sh < /dev/null &
), maka Anda perlu menggunakan deskriptor terbuka lainnya, yang tidak menghasilkan output saat membaca dijalankan, mis. stdout :Jika dalam naskah semua deskriptor ditutup ( stdin , stdout , stderr ) (misalnya karena disebut sebagai daemon), maka Anda perlu menemukan file yang ada yang tidak menghasilkan output:
sumber
read -t 1 3<&- 3<&0 <&3
sama denganread -t 0
. Hanya membaca dari stdin dengan timeout.Ini berfungsi dari shell login dan juga shell non-interaktif.
sumber
read -t 10 <> <(:)
.Apakah Anda benar-benar membutuhkan fifo? Mengarahkan stdin ke deskriptor file lain juga harus berfungsi.
Terinspirasi oleh: Baca input dalam bash di dalam loop sementara
sumber
Sedikit perbaikan pada solusi yang disebutkan di atas (yang saya telah berdasarkan ini).
Mengurangi kebutuhan untuk fifo dan karenanya tidak perlu melakukan pembersihan.
sumber
read -t 10 <> <(:)
.