Shell: apakah mungkin untuk menunda perintah tanpa menggunakan `sleep`?

21

Apakah ada pengganti, alternatif, atau trik bash untuk menunda perintah tanpa menggunakan sleep? Misalnya, menjalankan perintah di bawah tanpa benar-benar menggunakan sleep:

$ sleep 10 && echo "This is a test"
pengguna321697
sumber
42
Ada apa dengan ini sleep?
muru
5
Tidak ada alasan sebenarnya selain rasa ingin tahu. Saya pikir akan menarik untuk mempelajari beberapa solusi alternatif. Saya pikir atmungkin satu, tetapi saya tidak dapat menemukan contoh penggunaan.
user321697
1
@ user321697 "at" adalah untuk menjadwalkan pekerjaan tunggal. mereka dieksekusi oleh layanan atd, sehingga mereka tidak akan menjeda skrip shell Anda. satu use case untuk at adalah untuk membuatnya melakukan sesuatu pada waktu yang ditentukan (async) dan membuat file marker ketika sudah selesai, sementara skrip Anda sedang menunggu file itu muncul dalam loop sementara. Anda dapat mencapai efek yang sama dengan menjadwalkan pekerjaan untuk mengirim skrip Anda SIGCONT dan kemudian membekukan skrip Anda dengan mengirimkan sendiri SIGSTOP.
Grega Bremec
1
Saya datang ke sini mengharapkan semua orang menyarankan spinlock. Saya terkejut dengan semua jawaban.
Daan van Hoek
3
Re: "Keingintahuan" - di unix.stackexchange.com/help/dont-ask , perhatikan persyaratan bahwa "Anda hanya boleh mengajukan pertanyaan praktis, yang dapat dijawab berdasarkan masalah aktual yang Anda hadapi. " - bahwa ini telah berhasil diterima meskipun bertentangan dengan pedoman yang membuatnya menjadi pengecualian yang agak jarang.
Charles Duffy

Jawaban:

17

Anda memiliki alternatif untuk sleep: Mereka adalah atdan cron. Berlawanan dengan sleepini, Anda perlu menyediakan waktu untuk menjalankannya.

  • Pastikan atdlayanan berjalan dengan mengeksekusi service atd status.
    Sekarang misalkan tanggal 11:17 UTC; jika Anda perlu untuk menjalankan perintah di 11:25 UTC, sintaks adalah: echo "This is a test" | at 11:25.
    Sekarang perlu diingat bahwa atdsecara default tidak akan mencatat penyelesaian pekerjaan. Untuk lebih banyak merujuk tautan ini . Lebih baik aplikasi Anda memiliki pencatatan sendiri.

  • Anda dapat menjadwalkan pekerjaan di cron, untuk referensi lebih lanjut: man cronuntuk melihat opsi-opsi atau crontab -euntuk menambah pekerjaan baru. /var/log/crondapat diperiksa untuk info tentang eksekusi pada pekerjaan.

FYI sleep system call menunda eksekusi saat ini dan menjadwalkannya dengan argumen yang diteruskan ke sana.

EDIT:

Seperti yang disebutkan @ Gayus, Anda juga dapat menambahkan menit waktu untuk atmemberi perintah. Tetapi katakanlah waktunya sudah 12:30:30dan sekarang Anda menjalankan scheduler now +1 minutes. Meskipun 1 menit, yang diterjemahkan menjadi 60 detik telah ditentukan, attetapi tidak benar-benar menunggu sampai 12:31:30untuk mengeksekusi pekerjaan, melainkan mengeksekusi pekerjaan di 12:31:00. Unit waktu dapat minutes, hours, days, or weeks. Untuk referensi lebih lanjutman at

misalnya: echo "ls" | at now +1 minutes

ss_iwe
sumber
7
Ini tidak benar, Anda dapat menjadwalkan suatu pekerjaan untuk mengatakan sekarang +1 menit, untuk berjalan dalam waktu beberapa menit
Gayus
29

Dengan bashbuiltin, Anda dapat melakukan:

coproc read -t 10 && wait "$!" || true

Tidur selama 10 detik tanpa menggunakan sleep. Yang coprocharus dibuat agar readstdin adalah pipa tempat tidak akan ada yang keluar. || truekarena waitstatus keluar akan mencerminkan pengiriman SIGALRM yang akan menyebabkan shell keluar jika errexitopsi disetel.

Dalam cangkang lain:

mkshdan ksh93memiliki sleepbuilt-in, tidak ada gunanya menggunakan apa pun di sana (meskipun mereka berdua juga mendukung read -t).

zshjuga mendukung read -t, tetapi juga memiliki pembungkus bawaan select(), sehingga Anda juga dapat menggunakan:

zmodload zsh/zselect
zselect -t 1000 # centiseconds

Jika yang Anda inginkan adalah menjadwalkan hal-hal yang akan dijalankan dari sesi shell interaktif, lihat juga zsh/schedmodul dizsh .

Stéphane Chazelas
sumber
Apakah Anda akan mempertimbangkannya read -t 10 < /dev/zero || true?
Jeff Schaller
5
@ JeffSchaller Saya akan menghindarinya karena itu adalah lingkaran sibuk.
Stéphane Chazelas
@ StéphaneChazelas Saya tidak akan berharap itu menjadi loop sibuk - Saya berharap shell readakan diimplementasikan menggunakan select (2) atau yang serupa (menyiratkan bahwa read-with-timeout akan menjadi jawaban yang baik untuk pertanyaan ini). Saya mengungkapkan keterkejutan alih-alih bertentangan dengan Anda, tetapi dapatkah Anda mengarahkan diskusi lebih lanjut tentang ini?
Norman Grey
5
@NormanGray, /dev/zeroadalah file yang berisi jumlah data tak terbatas (NUL byte). Jadi readakan membaca sebanyak mungkin selama 10 detik itu. Untungnya, dalam kasus bashyang tidak mendukung penyimpanan byte NUL dalam variabelnya, itu tidak akan menggunakan memori apa pun, tetapi itu masih akan memakan banyak sumber daya CPU.
Stéphane Chazelas
1
@NormanGray, jika dijalankan dari terminal, /dev/stdoutakan menjadi perangkat tty, sehingga akan memiliki efek samping (seperti menghentikan skrip jika dijalankan di latar belakang) dan akan kembali jika pengguna menekan masuk misalnya. read -t 10 /dev/stdout | :akan bekerja di Linux, tetapi hanya di Linux, sementara coprocharus bekerja terlepas dari OS.
Stéphane Chazelas
7

Beberapa ide lain.

top -d10 -n2 >/dev/null

vmstat 10 2 >/dev/null

sar 10 1 >/dev/null

timeout 10s tail -f /dev/null
steve
sumber
1
Anda "mencuri" ide saya tentang timelimit / timeout .... +1
Rui F Ribeiro
1
Ohhhh, terima kasih, saya berada dalam situasi tanpa tidur, top luar biasa!
Fire-Dragon-DoL
6

Karena ada jawaban yang menyarankan untuk menggunakan non-standar -t delaypilihan read, di sini adalah cara untuk melakukan waktunya-out dibaca di shell standar:

{ ss=`stty -g`; stty -icanon min 0 time 20; read foo; stty "$ss"; }

Argumen untuk stty timeberada dalam sepersepuluh detik.

mosvy
sumber
5

Menggunakan variabel bawaan bash $SECONDSdan loop sibuk:

for((target=$((SECONDS + 10)); SECONDS < target; true)); do :; done
Jeff Schaller
sumber
2
Itu pada dasarnya akan berhenti untuk jangka waktu berkisar antara 9 dan 10 detik (karena bug dibash ; zshdan mkshmemiliki masalah yang sama tetapi telah diperbaiki sejak)
Stéphane Chazelas
7
Cara yang baik untuk membuat panas.
ctrl-alt-delor
6
tidak akan menjadi pertama kalinya saya dituduh penuh dengan udara panas! :)
Jeff Schaller
4

trik tertua dalam buku:

read && echo "This is a test"

Tekan saja Enterdan itu akan terus!

Fabby
sumber
Ini tidak akan terjadi jika proses perlu menjalankan interaksi bebas atau di latar belakang kan?
ss_iwe
Benar: Tapi itu bukan salah satu persyaratan OP sesuai pertanyaan awal, jadi masih merupakan jawaban yang valid ... ;-)> :-)
Fabby
1
OP secara khusus memberikan contoh (dengan sleep) dan meminta alternatif yang setara tanpa. Jadi readjangan parse, maaf. ;)
AnoE
@AnoE Stéphane jawaban tentu saja yang terbaik, milikku hanya yang tertua --- press «enter» to continue --- ;-)
Fabby
4

Kembali pada zaman mikrokomputer yang menjalankan BASIC, penundaan biasanya diselesaikan dengan loop kosong:

FOR I = 1 TO 10000:NEXT

Prinsip yang sama dapat digunakan untuk memasukkan penundaan dalam skrip shell:

COUNTER=0; while [ $COUNTER -lt 10000 ]; do :; let COUNTER=COUNTER+1; done

Tentu saja, masalah dengan pendekatan ini adalah bahwa panjang penundaan akan bervariasi dari mesin ke mesin sesuai dengan kecepatan prosesornya (atau bahkan pada mesin yang sama di bawah beban yang berbeda). Tidak seperti sleepitu, ia mungkin juga akan memaksimalkan CPU Anda (atau salah satu dari intinya).

Psychonaut
sumber
2
Cara yang baik untuk membuat panas.
ctrl-alt-delor
2
Delay-loop adalah ide yang mengerikan untuk apa pun kecuali yang paling singkat dari tidur (beberapa nanodetik atau siklus clock pada driver perangkat) pada CPU modern yang dapat menjalankan OS seperti Unix. yaitu tidur yang begitu singkat sehingga Anda tidak dapat menggunakan CPU untuk melakukan hal lain sambil menunggu, seperti menjadwalkan proses lain atau memasuki kondisi tidur rendah daya sebelum terbangun dengan penghenti waktu. Frekuensi CPU dinamis membuat bahkan tidak mungkin untuk mengkalibrasi loop tunda untuk hitungan per detik, kecuali sebagai penundaan minimum yang berpotensi tidur jauh lebih lama pada kecepatan clock rendah sebelum naik.
Peter Cordes
Komputer kuno memiliki konsumsi daya yang jauh lebih sedikit bergantung pada beban kerja. CPU modern perlu secara dinamis mematikan bagian-bagian berbeda dari chip sebanyak mungkin untuk tidak meleleh (misalnya mematikan bagian-bagian FPU atau unit eksekusi SIMD sementara hanya kode integer yang berjalan, atau setidaknya gerbang sinyal jam ke bagian-bagian chip) yang tidak perlu beralih). Dan memasuki kondisi tidur berdaya rendah saat idle (alih-alih berputar dalam putaran tak terbatas menunggu penghentian waktu) juga lebih baru daripada komputer kuno yang Anda sebutkan.
Peter Cordes
Untuk informasi lebih lanjut tentang sejarah CPU, lihat Panduan Modern Mikroprosesor 90-Menit! - lighterra.com/papers/modernmicroprocessors .
Peter Cordes
3

Tidak ada built-in, yang melakukan hal yang sama sleep(kecuali sleepada built-in). Namun ada beberapa perintah lain yang akan menunggu.

Beberapa di antaranya.

  • atdan cron: digunakan untuk menjadwalkan tugas pada waktu tertentu.

  • inotifywait: digunakan untuk menunggu file, atau file yang akan diubah / dihapus / ditambahkan / dll

ctrl-alt-delor
sumber
Terima kasih untuk ini. Bisakah Anda memberikan contoh untuk melakukan tugas yang dijadwalkan (10 detik dari sekarang) dengan at?
user321697
1
sunting dan upvote! ;-)
Fabby
cronmenyimpan tugas crontab, kan? Di mana atmenyimpan data yang dijadwalkan?
user321697
@ user321697 Sudah dijawab di sini
Fabby
Maaf untuk mengembalikan suntingan Anda ke Q: Anda mengubah tujuan utama pertanyaan OPs yang akan membatalkan jawaban paling sederhana dari semua ... ¯ \ _ (ツ) _ / ¯
Fabby
3

Klasik dari Land of Windows and Batches:

ping -c 11 localhost >/dev/null && echo "This is a test"
Joker_vD
sumber
Kesalahan konfigurasi sistem firewall atau nama mungkin menimbulkan kesulitan tambahan yang signifikan.
spektrum
1
127.0.0.1 ... @spectras
AnoE
1
Untungnya tidak lagi diperlukan, karena Windows sekarang mendukung tidur secara native.
Baldrickk
1
@AnoE> memecahkan bagian sistem nama, bukan bagian firewall. Meskipun tidak umum, dapat dikonfigurasi untuk secara diam-diam menjatuhkan ping ke antarmuka lokal. Itu akan menyebabkan ping menunggu lebih lama.
spektrum
+1 untuk kenangan "suka"
AC
0

Jika Anda ingin menunggu baris baru dalam file secara interaktif, maka

tail -f
.

Menunggu perubahan pada sistem file? Kemudian gunakan mis

inotify / inoticoming
.

Dan ada opsi lain, tergantung pada apa yang Anda maksud dengan "tunggu".

Edheldil
sumber