Як запустити команду кілька разів, використовуючи bash shell?


153

Чи є спосіб запустити команду (наприклад ps aux|grep someprocess) протягом n разів?

Щось на зразок:

run -n 10  'ps aux|grep someprocess'

Я хочу використовувати його інтерактивно, будь ласка, не публікуйте сценарії.

Оновлення: Причина, про яку я прошу, полягає в тому, що я працюю на багатьох машинах і не хочу імпортувати всі свої адаптовані сценарії тощо в кожен ящик, щоб отримати однакову функціональність на всіх машинах.


Відповіді:


197

Я не думаю, що команда або оболонка, побудована для цього, не існує, оскільки це тривіальне підмножина того, для чого forпризначений цикл оболонок Bourne та самостійно реалізувати таку команду, як це досить просто.

Для початку ви можете використовувати фіктивну forпетлю:

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

Або еквівалентно згідно з пропозицією JimB, використовуючи вбудований Bash для генерації послідовностей:

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

Це повторюється десять разів виконувати commandкожен раз - це може бути труба або ряд команд, розділених ;або &&. Ви можете використовувати $iзмінну, щоб знати, в якій ітерації ви перебуваєте.

Якщо ви вважаєте цей однолінійний скрипт і тому з певної (але, можливо, дійсною) причини непотрібною, ви можете реалізувати його як команду, можливо, щось подібне у вашому .bashrc (неперевірене):

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

Використання:

run 10 command

Приклад:

run 5 echo 'Hello World!'

16
@mahatmanich, цикл - це не сценарій. Ніщо не заважає вам скористатися для ... на інтерактивному терміналі.
Зоредаче

3
Що ж, однолінійний вище стандартний спосіб зробити це, і це досить просто. Чому це вам не добре? Можливо, ви ставите неправильне запитання? Яка головна мета ваших сценаріїв чи ваших дій, щоб ви хотіли повторити їх кілька разів? Можливо, є краще рішення, якщо ми поставимо проблему по-іншому.
Паткос Чаба

6
@mahatmanich - for це вбудований баш для ітерації.
JimB

3
@Eduardo Ivanec - FYI, bash має вбудований діапазон на кшталт seq: {1..10}
JimB

1
Здається, вбудована дужка послідовності не підтримує заміну змінної (див. Stackoverflow.com/a/3737773/713554 ). Функція, яку ви надали, прекрасно працює, коли її розміщують, .bashrcякщо {1..$number} її `seq $number`замінюють.
Лев

29

ps aux | grep someprocessсхоже, ви хочете спостерігати за змінами програми протягом певного часу. Едуардо дав відповідь, яка точно відповідає на ваше запитання, але є альтернатива watch:

watch 'ps aux | grep someprocess'

Зауважте, що я поставив команду в єдині лапки, щоб оболонка не інтерпретувала команду як "run watch ps aux" і передає результат наскрізь grep someprocess. Ще один спосіб зробити попередню команду:

watch ps aux \| grep someprocess

За замовчуванням watchоновляється кожні дві секунди, що можна змінити за допомогою -nпараметра. Наприклад, якщо ви хочете мати інтервал в 1 секунду:

watch -n 1 'ps aux | grep someprocess'

21

Задля розваги

pgrep ssh ;!!;!!;!!;!!;!!;!!

Може хтось пояснить це, будь ласка? Виглядає дуже інтригуюче.
Даніель Вартанов

4
; це просто роздільник команд. !! повторна команда в bash. Отже, запустіть 'pgrep ssh', а потім повторіть його 6 разів.
Пьотр Кукієлка

Хоча це повчально, це не дуже інтуїтивно. Однокласинка forздається найкращим способом. Все одно дякую за відповідь.
erm3nda

1
Не буде cmd ;!!в одному рядку просто повторити команду, введену перед поточним рядком? Це мали б бути дві окремі historyзаписи.
Джоель Пурра

замінити ;з &&зупинятися на першій невдачі.
user881300

16

аналогічно попереднім відповідям, але не вимагає циклу:

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

висновок труби seq до xargs без аргументів чи параметрів


2
Це просто зробить одне виконання echo "hello" 1 2 3 4 5 6 7 8 9 10. Вам потрібно запустити xargs з -n 1для одного процесу на кожен вхід (число) та з -P 10для паралельного виконання (10 паралельних процесів). Закінчується с seq 10 | xargs -n 1 -P 10 echo.
Олександр Климечек

16

Спробуйте це:

yes ls | head -n5 | bash

Для цього потрібно, щоб команда виконувалась у підрозділі, незначне виконання покарання. YMMV. В основному, ви отримуєте команду "так", щоб повторити рядок "ls" N разів; в той час як "head -n5" завершив цикл у 5 повторів. Кінцева труба відправляє команду на обрану вами оболонку.

До речі, cshподібні снаряди мають вбудовану repeatкоманду. Ви можете використовувати це для виконання вашої команди в bash-під-оболонці!


5

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

що, звичайно, можна перетворити на один вкладиш:

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

і, здається, найбільш портативний спосіб, і, таким чином, менше шансів змусити вас встановлювати програми.

Наступні менш портативні:

  • розширення {1..10}дужок: специфічний bash і створив би величезну лінію, якщо аргумент великий
  • seq: ГНУ
  • yes: ГНУ

А якщо вам набридло портативність, врахуйте GNU parallel:

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

який паралельно виконує команди і має безліч крутих варіантів.

Дивіться також: https://stackoverflow.com/questions/169511/how-do-i-iterate-over-a-range-of-numbers-defined-by-variables-in-bash


GNU Parallel створений, щоб бути дуже портативним. sh, zsh, ksh, і bashвсі вони добре підтримуються на більшості платформ. csh, tcsh, fishмає певну підтримку. Використовуючи parallel --embedнавіть, ви можете створити сценарій, який легко перемістити в іншу систему, на якій GNU Parallel не встановлено.
Оле Танге

2

Реалізація риби оболонки @ Eduardo-Ivanec в runфункції вище

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

0

Це було б "дивитися" - повинно бути частиною майже кожної системи Unix, яка використовує операційні системи

Ви можете побачити зміни fs або іншим чином цікавий рух у системі. Наприклад,

watch "df -hP | grep /tmp" 

Просто поставте свої команди як аргумент (див. man watch)


Уже є відповідь з
вахтою

0

На macOS можна використовувати repeatкоманду.

repeat 10 ps aux | grep someprocess
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.