Ulangi perintah setiap x interval waktu di terminal?

143

Bagaimana saya bisa mengulangi perintah setiap interval waktu, sehingga akan memungkinkan saya untuk menjalankan perintah untuk memeriksa atau memantau direktori?

Tidak perlu skrip, saya hanya perlu perintah sederhana untuk dieksekusi di terminal.

muru
sumber

Jawaban:

220

Anda dapat menggunakan watchperintah, arloji digunakan untuk menjalankan perintah yang ditunjuk secara berkala.

Buka Terminal dan ketik:

watch -n x <your command>

ubah x menjadi waktu dalam detik yang Anda inginkan.

Untuk bantuan lebih lanjut menggunakan watchperintah dan opsinya, jalankan man watchatau kunjungi Tautan ini .

Sebagai contoh: daftar berikut ini, setiap 60 - an , di Terminal yang sama, isi direktori Desktop sehingga Anda dapat mengetahui jika ada perubahan yang terjadi:

watch -n 60 ls -l ~/Desktop
nux
sumber
34
Beri +1 tapi hati-hati saat menggunakan ekspansi. Misalnya, coba perbedaan antara watch -n 1 'echo $COLUMNS'dan watch -n 1 echo $COLUMNSketika mengubah ukuran terminal Anda - yang pertama diperluas setiap detik, tetapi yang terakhir diperluas hanya sekali sebelum watch dimulai.
l0b0
Ini berfungsi seperti pesona! Ty nux
Masalah yang saya miliki dengan solusi ini adalah Anda tidak dapat menjalankan arloji sebagai proses dan membiarkannya berjalan di latar belakang (misalnya dengan &
disown
2
Apakah ada cara untuk menggunakan watchdengan perintah tipe "history enabled"? Saya suka menggunakan watch, tetapi kadang-kadang saya lebih suka melihat log dari eksekusi sebelumnya juga, bukan hanya yang terakhir. Dan ya, saya tahu saya bisa menggunakan scripting ( while true) untuk mencapai ini, tetapi menggunakan watchutilitiy jauh lebih bersih!
rinogo
ini bekerja untuk perintah yang lebih sederhana tetapi dengan chaining pipelined perintah ini tidak bekerja untuk saya .. berikut adalah perintah yang saya coba => cat api.log | grep 'calling' | wc-l
Sudip Bhandari
90

Anda juga dapat menggunakan perintah ini di terminal, terlepas dari jawaban nux:

while true; do <your_command>; sleep <interval_in_seconds>; done

Contoh

while true; do ls; sleep 2; done

Perintah ini akan mencetak output lspada interval 2 detik.

Gunakan Ctrl+ Cuntuk menghentikan proses.

Ada beberapa kekurangan watch

  • Itu tidak dapat menggunakan perintah alias.
  • Jika output dari perintah apa pun cukup panjang, bergulir tidak berfungsi dengan baik.
  • Ada beberapa masalah untuk mengatur interval waktu maksimum di luar nilai tertentu.
  • watchakan menafsirkan urutan warna ANSI yang melewati karakter melarikan diri menggunakan -catau --coloropsi. Misalnya output pygmentizeakan berfungsi tetapi akan gagal untuk ls --color=auto.

Dalam keadaan di atas ini mungkin muncul sebagai opsi yang lebih baik.

souravc
sumber
watchada untuk itu, ini agak tidak berguna saya akan katakan
Bruno Pereira
14
Saya tidak mengklaim jawaban ini harus digunakan di tempat pertama. watchbagus dalam banyak kasus. Itu sebabnya saya sebutkan "terlepas dari jawaban nux" di awal. Tetapi ada beberapa masalah dengan watchmisalnya Seseorang tidak dapat menggunakan perintah alias denganwatch . Ambil contoh llyang alias ls -laFtapi tidak bisa digunakan watch. Juga dalam kasus jika output dari perintah apa pun cukup lama Anda akan kesulitan dalam menggulir menggunakan watch. Dalam beberapa kasus khusus ini jawaban ini mungkin muncul pilihan yang lebih baik.
souravc
@souravc versi saya watchsetidaknya memungkinkan -catau --colorpilihan untuk output berwarna.
Lily Chung
8
while sleep xlebih baik - lebih mudah untuk dibunuh.
d33tah
3
Ini adalah alternatif yang bagus dan, tidak seperti watchitu, ia menyimpan sejarah perintah.
adelriosantiago
34

Hanya ingin memberikan jawaban souravc dan nux :

  1. Walaupun watchakan bekerja dengan baik di Ubuntu, Anda mungkin ingin menghindari itu jika Anda ingin "Unix-fu" Anda menjadi murni - di FreeBSD misalnya, arloji adalah perintah untuk "mengintai jalur tty lain".
  2. while true; do command; sleep SECONDS; donejuga memiliki peringatan - perintah Anda mungkin sulit untuk membunuh menggunakan CTR + C . Anda mungkin ingin memilih while sleep SECONDS; do command; done- tidak hanya lebih pendek, tetapi juga lebih mudah untuk diinterupsi. Peringatannya adalah ia akan tidur lebih dulu, kemudian jalankan perintah Anda, jadi Anda harus menunggu beberapa saat SECONDSsebelum kemunculan pertama perintah itu terjadi.
d33tah
sumber
2
Mudah-mudahan ini dapat diterima sebagai jawaban alih-alih komentar - Saya ingin menunjukkan solusi lain di sini dan berkomentar benar-benar akan memberi saya sedikit perhatian.
d33tah
Mengapa sebenarnya penting di mana Anda meletakkannya sleepdi whileloop? Saya tidak dapat menemukan perbedaan, Ctrl + C memutus loop langsung tidak peduli apa.
hidangan penutup
essert essert on: tergantung pada apa yang Anda coba keluar dari kurasa. Biasanya, ctrl + c hanya akan membunuh Anda commanddan sleepdan hanya istirahat jika Anda membunuh true.
d33tah
11

Kedengarannya seperti tugas ideal untuk crondaemon yang memungkinkan untuk menjalankan perintah periodik. Jalankan crontab -eperintah untuk mulai mengedit konfigurasi cron pengguna Anda. Formatnya didokumentasikan dalam crontab (5) . Pada dasarnya Anda memiliki lima bidang yang berkaitan dengan waktu dan dipisahkan oleh ruang diikuti oleh perintah:

The time and date fields are:

       field          allowed values
       -----          --------------
       minute         0-59
       hour           0-23
       day of month   1-31
       month          1-12 (or names, see below)
       day of week    0-7 (0 or 7 is Sunday, or use names)

Misalnya, jika Anda ingin menjalankan skrip Python setiap hari Selasa, jam 11 pagi:

0 11 * * 1 python ~/yourscript.py

Ada juga beberapa nama khusus yang menggantikan waktu, seperti @reboot. Sangat membantu jika Anda perlu membuat direktori sementara. Dari crontab saya (tercantum dengan crontab -l):

# Creates a temporary directory for ~/.distcc at boot
@reboot ln -sfn "$(mktemp -d "/tmp/distcc.XXXXXXXX")" "$HOME/.distcc"
Lekensteyn
sumber
4
Pertanyaannya adalah bagaimana menjalankan sesuatu secara berkala di terminal. cronberjalan di belakang layar daripada di terminal
north-bradley
5

Jika Anda memantau sistem file, maka inotifywaititu brilian dan tentu saja menambahkan lebih sedikit beban pada sistem Anda.

Contoh:

Pada terminal 1 ketik perintah ini:

$ inotifywait .

Kemudian di terminal ke-2 , perintah apa pun yang memengaruhi direktori saat ini,

$ touch newfile

Kemudian di terminal asli inotifywait akan bangun dan melaporkan acara tersebut

./ CREATE newfile2

Atau dalam satu lingkaran

$ while true ; do inotifywait . ; done
Setting up watches.  
Watches established.
./ OPEN newfile2
Setting up watches.  
Watches established.
./ OPEN newfile2
Setting up watches.  
Watches established.
./ DELETE newfile
Setting up watches.  
Watches established.
./ CREATE,ISDIR newdir
Setting up watches.  
Watches established.
X Tian
sumber
pengguna mengatakan kepada Anda, tidak ada skrip, dan mungkin dia tidak ingin memantau apa pun
nux
3
Saya tidak menyuruhnya untuk menulis skrip, saya menyarankan bahwa jika mereka mengulangi inorder untuk menonton acara sistem file tertentu, maka inotifywait berguna, dan menggunakan lebih sedikit sumber daya daripada mengulangi perintah. Saya sering menjalankan beberapa perintah pada baris perintah misalnya grep something InALogFile|lessapakah itu skrip?
X Tian
itu jawaban yang bagus, cobalah untuk mengeditnya agar terlihat lebih sederhana.
nux
3
Apa yang bisa lebih sederhana daripada .saya tidak bisa mengabaikan perintah.
X Tian
Terima kasih @XTian, ​​perintah yang bagus. Saya juga sekarang melihat di halaman manual yang dapat Anda tambahkan -muntuk terus memantau tanpa loop.
yoniLavi
4

Anda dapat membuat repeatperintah sendiri dengan melakukan langkah-langkah berikut; kredit di sini :

Pertama, buka .bash_aliasesfile Anda :

$ xdg-open ~/.bash-aliases

Kedua, rekatkan baris ini di bagian bawah file dan simpan:

repeat() {
n=$1
shift
while [ $(( n -= 1 )) -ge 0 ]
do
    "$@"
done
}

Ketiga, tutup dan buka kembali terminal Anda, atau ketik:

$ source ~/.bash_aliases

Dan lagi! Anda sekarang dapat menggunakannya seperti ini:

$ repeat 5 echo Hello World !!!

atau

$ repeat 5 ./myscript.sh
Blufter
sumber
ada kesalahan ketik kecil di baris xdg-open ~ / .bash-alias. seharusnya: xdg-open ~ / .bash_aliases (yaitu: garis bawah)
ssinfod
4

Anda bisa menggunakan crontab. jalankan perintah crontab -edan buka dengan editor teks pilihan Anda, lalu tambahkan baris ini

*/10 * * * *  /path-to-your-command

Ini akan menjalankan perintah Anda setiap 10 menit

* */4 * * *  /path-to-your-command

Ini akan menjalankan perintah Anda setiap 4 jam

Solusi lain yang mungkin

$ ..some command...; for i in $(seq X); do $cmd; sleep Y; done

X beberapa kali untuk mengulang.

Y waktu menunggu untuk mengulang.

Contoh:

$ echo; for i in $(seq 5); do $cmd "This is echo number: $i"; sleep 1;done
Maythux
sumber
Mengapa ini merupakan perbaikan? Anda baru saja menambahkan langkah ekstra, tidak perlu, dengan menyimpan perintah sebagai variabel. Satu-satunya hal yang dilakukan adalah i) membuatnya lebih lama untuk mengetik ii) memaksa Anda untuk hanya menggunakan perintah sederhana, tidak ada pipa atau redirect dll.
terdon
Hapus variabel tambahan
Maythux
3

Kekhawatiran lain dengan pendekatan "jam tangan" yang diusulkan di atas adalah bahwa ia hanya menampilkan hasilnya ketika proses dilakukan. "date; sleep 58; date" akan menampilkan 2 tanggal hanya setelah 59 detik ... Jika Anda memulai sesuatu yang berjalan selama 4 menit, yang menampilkan secara perlahan beberapa halaman konten, Anda tidak akan benar-benar melihatnya.

Di sisi lain, kekhawatiran dengan pendekatan "sementara" adalah bahwa ia tidak mempertimbangkan durasi tugas.

while true; do script_that_take_between_10s_to_50s.sh; sleep 50; done

Dengan ini, skrip akan dijalankan kapan saja setiap menit, kadang-kadang membutuhkan waktu 1m40. Jadi, bahkan jika sebuah cron akan dapat menjalankannya setiap menit, di sini, itu tidak akan berjalan.

Jadi untuk melihat output pada shell seperti yang dihasilkan dan menunggu waktu permintaan yang tepat, Anda perlu melihat waktu sebelumnya, dan sesudahnya, dan loop dengan while.

Sesuatu seperti:

while ( true ); do
  echo Date starting `date`
  before=`date +%s`
  sleep `echo $(( ( RANDOM % 30 )  + 1 ))`
  echo Before waiting `date`
  after=`date +%s`
  DELAY=`echo "60-($after-$before)" | bc`
  sleep $DELAY
  echo Done waiting `date`
done

Ini akan menampilkan ini:

Seperti yang Anda lihat, perintah dijalankan setiap menit:

Date starting Mon Dec 14 15:49:34 EST 2015
Before waiting Mon Dec 14 15:49:52 EST 2015
Done waiting Mon Dec 14 15:50:34 EST 2015

Date starting Mon Dec 14 15:50:34 EST 2015
Before waiting Mon Dec 14 15:50:39 EST 2015
Done waiting Mon Dec 14 15:51:34 EST 2015

Jadi ganti saja perintah "sleep echo $(( ( RANDOM % 30 ) + 1 ))" dengan apa yang Anda inginkan dan itu akan dijalankan, pada terminal / shell, tepat setiap menit. Jika Anda ingin jadwal lain, ubah saja "60" detik dengan apa pun yang Anda butuhkan.

Versi lebih pendek tanpa garis debug:

while ( true ); do
  before=`date +%s`
  sleep `echo $(( ( RANDOM % 30 )  + 1 ))` # Place you command here
  after=`date +%s`
  DELAY=`echo "60-($after-$before)" | bc`
  sleep $DELAY
done
jmspaggi
sumber
Membalas diri sendiri ... Jika perintah Anda membutuhkan lebih dari penundaan yang Anda konfigurasi, $ DELAY akan mendapatkan nilai negatif dan perintah tidur akan gagal sehingga skrip akan memulai kembali segera. Perlu sadar akan hal itu.
jmspaggi