Как запустить команду несколько раз, используя оболочку bash?

153

Есть ли способ выполнить команду (например ps aux|grep someprocess) для n раз?

Что-то вроде:

run -n 10  'ps aux|grep someprocess'

Я хочу использовать его в интерактивном режиме, пожалуйста, не размещайте сценарии.

Обновление: причина, по которой я спрашиваю об этом, заключается в том, что я работаю на многих машинах и не хочу импортировать все свои адаптированные сценарии и т. Д. В каждую коробку, чтобы получить одинаковую функциональность на каждой машине.

mahatmanich
источник
1
stackoverflow.com/questions/3737740/…
Сиро Сантилли 新疆 改造 中心 法轮功 六四 事件

Ответы:

197

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

Для начала вы можете использовать фиктивный 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, цикл это не скрипт. Ничто не мешает вам использовать for ... на интерактивном терминале.
Зоредаче
3
Ну, однострочник выше - это стандартный способ сделать это, и он довольно прост. Почему это не хорошо для вас? Может быть, вы задаете не тот вопрос? Какова основная цель ваших сценариев или ваших действий, чтобы вы хотели повторять их несколько раз? Может быть, есть лучшее решение, если мы поставим проблему по-другому.
Паткос Чаба
6
@mahatmanich - for это Баш встроенный для итерации.
ДжимБ
3
@Eduardo Ivanec - к вашему сведению, 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'
Lekensteyn
источник
21

Просто для удовольствия

pgrep ssh ;!!;!!;!!;!!;!!;!!
hdaz
источник
Может кто-нибудь объяснить это, пожалуйста? Выглядит очень интригующе.
Даниэль Вартанов
4
; это просто разделитель команд. !! повторить последнюю команду в bash. Так что запустите 'pgrep ssh', а затем воспроизведите его 6 раз.
Петр Кукелька
Пока это поучительно, но не очень интуитивно понятно. Однострочник forкажется лучшим способом. В любом случае спасибо за ответ.
erm3nda
1
Не cmd ;!!в одной ли строке просто повторить команду, введенную перед текущей строкой? Это должны быть две отдельные historyзаписи.
Джоэл Пурра
замените ;на, &&чтобы остановить при первом сбое.
user881300
16

похож на предыдущие ответы, но не требует цикла for:

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

конвейерный вывод seq to 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. По сути, вы получаете команду «yes» для повторения строки «ls» N раз; в то время как "head -n5" завершил цикл на 5 повторений. Последний канал отправляет команду в оболочку по вашему выбору.

Между прочим, cshкак у снарядов есть встроенная repeatкоманда. Вы можете использовать это для выполнения вашей команды в под-оболочке bash!

android42
источник
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: GNU
  • yes: GNU

И если вы устали от переносимости, рассмотрите 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

Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
источник
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
masukomi
источник
0

Это было бы «смотреть» - должно быть частью почти любой Unix-системы, использующей procps

Вы можете увидеть изменения фс или другие интересные движения в системе. Например,

watch "df -hP | grep /tmp" 

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

Крис Арну
источник
Уже есть ответ с часами ... см. Прямо ниже ...
Махатманич
0

В macOS вы можете использовать repeatкоманду.

repeat 10 ps aux | grep someprocess
Нил
источник