Bagaimana menjalankan perintah beberapa kali, menggunakan bash shell?

153

Apakah ada cara untuk menjalankan perintah (misalnya ps aux|grep someprocess) untuk n kali?

Sesuatu seperti:

run -n 10  'ps aux|grep someprocess'

Saya ingin menggunakannya secara interaktif, tolong jangan memposting skrip.

Pembaruan: Alasan saya menanyakan hal ini adalah, bahwa saya bekerja pada banyak mesin dan saya tidak ingin mengimpor semua skrip saya yang diadaptasi, dll ke dalam setiap kotak untuk mendapatkan fungsi yang sama di setiap mesin.

mahatmanich
sumber
1
stackoverflow.com/questions/3737740/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Jawaban:

197

Saya tidak berpikir perintah atau shell builtin untuk ini ada, karena itu adalah subset sepele dari apa forloop Bourne dirancang untuk dan mengimplementasikan perintah seperti ini sendiri karena itu cukup sederhana.

Sebagai permulaan, Anda dapat menggunakan forloop dummy :

for i in `seq 10`; do command; done

Atau sesuai dengan saran JimB, menggunakan Bash bawaan untuk menghasilkan urutan:

for i in {1..10}; do command; done

Ini mengulangi sepuluh kali mengeksekusi commandsetiap kali - itu bisa berupa pipa atau serangkaian perintah yang dipisahkan oleh ;atau &&. Anda bisa menggunakan $ivariabel untuk mengetahui iterasi tempat Anda berada.

Jika Anda menganggap skrip satu baris ini dan karenanya untuk beberapa alasan yang tidak ditentukan (tapi mungkin valid) tidak diinginkan, Anda dapat mengimplementasikannya sebagai perintah, mungkin seperti ini pada .bashrc (belum diuji):

#function run
run() {
    number=$1
    shift
    for i in `seq $number`; do
      $@
    done
}

Pemakaian:

run 10 command

Contoh:

run 5 echo 'Hello World!'
Eduardo Ivanec
sumber
16
@mahatmanich, Loop bukan skrip. Tidak ada yang mencegah Anda menggunakan untuk ... di terminal interaktif.
Zoredache
3
Nah, satu-liner di atas adalah jenis cara standar untuk melakukannya dan itu cukup sederhana. Mengapa ini tidak baik untukmu? Mungkin Anda mengajukan pertanyaan yang salah? Apa tujuan utama dari skrip Anda atau tindakan Anda yang ingin Anda ulangi beberapa kali? Mungkin ada solusi yang lebih baik jika kita menempatkan masalahnya dengan cara yang berbeda.
Patkos Csaba
6
@mahatmanich - for adalah bash built-in untuk iterasi.
JimB
3
@Eduardo Ivanec - FYI, bash memiliki jangkauan seq{1..10}
bawaan
1
Tampaknya urutan braket bawaan tidak mendukung substitusi variabel (lihat stackoverflow.com/a/3737773/713554 ). Fungsi yang Anda berikan bekerja dengan sempurna saat ditempatkan di .bashrcjika {1..$number} ditukar `seq $number`.
Leo
29

ps aux | grep someprocessSepertinya Anda ingin menonton perubahan program untuk waktu yang tetap. Eduardo memberikan jawaban yang menjawab pertanyaan Anda dengan tepat tetapi ada alternatif watch::

watch 'ps aux | grep someprocess'

Perhatikan bahwa saya telah menempatkan perintah dalam tanda kutip tunggal untuk menghindari shell dari menafsirkan perintah sebagai "jalankan watch ps aux" dan pipa hasilnya grep someprocess. Cara lain untuk melakukan perintah sebelumnya adalah:

watch ps aux \| grep someprocess

Secara default, watchmenyegarkan setiap dua detik, yang dapat diubah menggunakan -nopsi. Misalnya, jika ingin memiliki interval 1 detik:

watch -n 1 'ps aux | grep someprocess'
Lekensteyn
sumber
21

Hanya untuk bersenang-senang

pgrep ssh ;!!;!!;!!;!!;!!;!!
hdaz
sumber
Bisakah seseorang menjelaskan hal ini? Terlihat sangat menarik.
Daniel Vartanov
4
; hanya pemisah perintah. !! memutar ulang perintah terakhir di bash. Jadi jalankan 'pgrep ssh' dan kemudian putar ulang 6 kali.
Piotr Kukielka
Sementara yang bersifat instruktif tidak sangat intuitif. One-liner forsepertinya cara terbaik. Pokoknya terima kasih atas jawabannya.
erm3nda
1
Bukankah cmd ;!!pada satu baris cukup ulangi perintah yang dimasukkan sebelum baris saat ini? Itu harus dua historyentri terpisah .
Joel Purra
ganti ;dengan &&untuk berhenti pada kegagalan pertama.
user881300
16

mirip dengan balasan sebelumnya, tetapi tidak memerlukan for loop:

seq 10 | xargs -I -- echo "hello"

output pipa seq ke xargs tanpa argumen atau opsi

nils-holmberg
sumber
2
Ini hanya akan melakukan satu eksekusi echo "hello" 1 2 3 4 5 6 7 8 9 10. Anda perlu menjalankan xargs dengan -n 1untuk satu proses untuk setiap input (angka) dan dengan -P 10untuk eksekusi paralel (10 proses paralel). Berakhir dengan seq 10 | xargs -n 1 -P 10 echo.
Alexander Klimetschek
16

Coba ini:

yes ls | head -n5 | bash

Ini membutuhkan perintah untuk dieksekusi dalam sub-shell, penalti kinerja sedikit. YMMV. Pada dasarnya, Anda mendapatkan perintah "ya" untuk mengulang string "ls" N kali; sementara "head -n5" mengakhiri loop pada 5 pengulangan. Pipa terakhir mengirim perintah ke shell pilihan Anda.

cshKerang mirip- kebetulan memiliki repeatperintah bawaan. Anda bisa menggunakannya untuk mengeksekusi perintah Anda dalam sub-shell bash!

android42
sumber
5

Cara POSIX

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_04_01

x=10
while [ $x -gt 0 ]; do
    command
    x=$(($x-1))
done

yang tentu saja dapat dibuat menjadi satu liner:

x=10; while [ $x -gt 0 ]; do command; x=$(($x-1)); done

dan tampaknya menjadi cara yang paling portabel, dan dengan demikian lebih sedikit membuat Anda menginstal program.

Berikut ini kurang portabel:

  • brace expansion {1..10}: spesifik bash, dan akan menghasilkan garis besar jika argumennya besar
  • seq: GNU
  • yes: GNU

Dan jika Anda bosan dengan portabilitas, pertimbangkan GNU parallel:

sudo apt-get install parallel
seq 100 | parallel echo {}

yang menjalankan perintah secara paralel dan memiliki banyak opsi keren.

Lihat juga: https://stackoverflow.com/questions/169511/how-do-i-iterate-over-a-range-of-numbers-defined-by-variables-in-bash

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
sumber
GNU Parallel dibuat sangat portabel. sh, zsh, ksh, dan bashsemuanya didukung dengan baik di sebagian besar platform. csh, tcsh, fishmemiliki beberapa dukungan. Menggunakan parallel --embedAnda bahkan dapat membuat skrip yang dapat dengan mudah dipindahkan ke sistem lain yang tidak memiliki GNU Paralel yang diinstal.
Ole Tange
2

Implementasi fish shell dari runfungsi @ eduardo-ivanec di atas

function run
  set number $argv[1]
  for i in (seq $number)
    eval $argv[2..-1]
  end
end
masukomi
sumber
0

Itu akan menjadi 'tontonan' - harus menjadi bagian dari hampir setiap sistem unix menggunakan procps

Anda dapat melihat perubahan fs atau gerakan menarik dalam suatu sistem. Sebagai contoh,

watch "df -hP | grep /tmp" 

Masukkan saja perintah Anda sebagai argumen (lihat man watch)

Chris Arnu
sumber
Sudah ada jawaban dengan arloji ... lihat di bawah ...
mahatmanich
0

Di macOS Anda dapat menggunakan repeatperintah.

repeat 10 ps aux | grep someprocess
Neil
sumber