web-dev-qa-db-fra.com

Comment exécuter une commande plusieurs fois, en utilisant le shell bash?

Existe-t-il un moyen d'exécuter une commande (par exemple ps aux|grep someprocess) pour n fois?

Quelque chose comme:

run -n 10  'ps aux|grep someprocess'

Je veux l'utiliser de manière interactive, veuillez ne pas publier de scripts.

Mise à jour: La raison pour laquelle je pose cette question est que je travaille sur beaucoup de machines et que je ne veux pas importer tous mes scripts adaptés, etc. dans chaque boîte pour obtenir la même fonctionnalité sur chaque machine. =

167
mahatmanich

Je ne pense pas qu'il existe une commande ou un shell intégré pour cela, car c'est un sous-ensemble trivial de ce pour quoi la boucle Bourne Shell for est conçue et l'implémentation d'une commande comme celle-ci est donc assez simple.

Pour commencer, vous pouvez utiliser une boucle fictive for:

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

Ou de manière équivalente selon la suggestion de JimB, en utilisant le Bash intégré pour générer des séquences:

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

Cela répète dix fois l'exécution de command à chaque fois - il peut s'agir d'un canal ou d'une série de commandes séparées par ; ou &&. Vous pouvez utiliser le $i variable pour savoir dans quelle itération vous vous trouvez.

Si vous considérez ce one-liner comme un script et donc pour une raison non spécifiée (mais peut-être valide) indésirable, vous pouvez l'implémenter comme une commande, peut-être quelque chose comme ça sur votre .bashrc (non testé):

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

Usage:

run 10 command

Exemple:

run 5 echo 'Hello World!'
219
Eduardo Ivanec

ps aux | grep someprocess on dirait que vous voulez regarder les changements d'un programme pendant une durée fixe. Eduardo a donné une réponse qui répond exactement à votre question mais il existe une alternative: watch :

watch 'ps aux | grep someprocess'

Notez que j'ai mis la commande entre guillemets simples pour éviter que le shell interprète la commande comme "exécuter watch ps aux" et diriger le résultat via grep someprocess. Une autre façon d'exécuter la commande précédente serait:

watch ps aux \| grep someprocess

Par défaut, watch est actualisé toutes les deux secondes, ce qui peut être modifié à l'aide de -n option. Par exemple, si vous souhaitez avoir un intervalle de 1 seconde:

watch -n 1 'ps aux | grep someprocess'
32
Lekensteyn

Juste pour le fun

pgrep ssh ;!!;!!;!!;!!;!!;!!
25
hdaz

Essaye ça:

yes ls | head -n5 | bash

Cela nécessite que la commande soit exécutée dans un sous-shell, une légère pénalité de performance. YMMV. Fondamentalement, vous obtenez la commande "yes" pour répéter la chaîne "ls" N fois; tandis que "head -n5" terminait la boucle à 5 répétitions. Le canal final envoie la commande au shell de votre choix.

Soit dit en passant csh - comme les shells ont une commande repeat intégrée. Vous pouvez l'utiliser pour exécuter votre commande dans un sous-shell bash!

16
android42

similaire aux réponses précédentes, mais ne nécessite pas la boucle for:

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

diriger la sortie de seq vers xargs sans arguments ni options

16
nils-holmberg

Méthode 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

qui pourrait bien sûr être transformé en un seul revêtement:

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

et semble être le moyen le plus portable, et donc moins susceptible de vous faire installer des programmes.

Les éléments suivants sont moins portables:

  • expansion de l'accolade {1..10}: spécifique à bash, et générerait une énorme ligne si l'argument est grand
  • seq: GNU
  • yes: GNU

Et si vous en avez assez de la portabilité, pensez à GNU parallel:

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

qui exécute des commandes en parallèle et possède de nombreuses options intéressantes.

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

Une implémentation Fish Shell de la fonction run de @ eduardo-ivanec ci-dessus

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

Ce serait "regarder" - devrait faire partie de presque tous les systèmes Unix utilisant procps

Vous pouvez voir les changements fs ou tout autre mouvement intéressant dans un système. Par exemple,

watch "df -hP | grep /tmp" 

Mettez simplement vos commandes en argument (voir man watch)

0
Chris Arnu

Sur macOS, vous pouvez utiliser la commande repeat.

repeat 10 ps aux | grep someprocess
0
Neil