Просто используйте pkill
. Хотя не стандартная команда, это найдено во многих Нельдах и выделено этому виду задач.
pkill -f 'vmstat 1'
Также обратите внимание что Ваш grep
будет соответствовать vmstat 1
но также и vmstat 10
и grep vmstat 1
(так был бы это pkill
выше), и awk
надмножество grep
. Чтобы быть более устойчивыми, Вы могли сделать вместо этого:
ps -Ao pid,args | awk '$2 == "vmstat" && $3 == "1" {print $1}' | xargs kill
Или
pkill -xf 'vmstat 1'
Вы также можете обратиться к bash
за помощью в ответе на эти вопросы, используя set -x
. Этот флаг указывает bash для отображения команды и ее расширенных аргументов перед запуском:
Сначала некоторые установки:
$ a=some-value
$ b=some-other-value
$ set -x
Теперь посмотрим, как оболочка интерпретирует эти команды:
$ a=b
+ a=b
Значение переменной a
устанавливать к литералу последовательности «b».
Теперь попробуем $ b
:
$ a=$b
+ a=some-other-value
Здесь мы попросим оболочку вычислить $ b
и вставить значение b
в команду.
Это показывает некоторые из значений оболочки - она интерпретирует переменные и подстановочные знаки вместо того, чтобы заставить отдельные команды выполнять работу. Например, ls
не должен знать, как интерпретировать «* .txt», потому что оболочка выполняет работу до запуска ls
:
$ ls *.txt
+ ls a.txt b.txt c.txt
a.txt b.txt c.txt
-121--246734- Да, мы видим ряд вещей, таких как:
while read line; do
echo $line | cut -c3
done
Или хуже:
for line in `cat file`; do
foo=`echo $line | awk '{print $2}'`
echo whatever $foo
done
(не смейтесь, я видел много таких).
Как правило, от начинающих сценариев оболочки. Это наивные буквенные переводы того, что бы вы делали в императивных языках, таких как C или python, но это не так, как вы делаете вещи в оболочках, и эти примеры очень неэффективны, совершенно ненадежны (потенциально приводят к проблемам безопасности), и если вам когда-нибудь удастся исправить большинство ошибок, ваш код становится неразборчивым.
В C или большинстве других языков компоновочные блоки представляют собой только один уровень над компьютерными инструкциями. Вы указываете процессору, что делать и что делать дальше. Вы берете свой процессор за руку и микроуправляете им: вы открываете тот файл, вы читаете, что много байтов, делаете это, вы делаете это с ним.
Оболочки являются языком более высокого уровня. Можно сказать, что это даже не язык. Они перед всеми интерпретаторами командной строки. Задание выполняется теми командами, которые вы выполняете, и оболочка предназначена только для их управления.
Одной из замечательных вещей, представленных Unix, был pipe и те потоки stdin/stdout/stderr по умолчанию, которые обрабатываются всеми командами.
За 50 лет мы не нашли лучшего, чем этот API, чтобы использовать силу команд и заставить их сотрудничать с задачей. Вероятно, это главная причина, почему люди до сих пор используют снаряды.
У вас есть режущий инструмент и транслитный инструмент, и вы можете просто сделать:
cut -c4-5 < in | tr a b > out
Оболочка просто делает сантехнику (открывает файлы, настраивает трубы, вызывает команды), и когда она готова, она просто течет, не делая ничего. Инструменты делают свою работу одновременно, эффективно в своем собственном темпе с достаточным буферизацией, чтобы не одно блокировало другое, это просто красиво и все же так просто.
Вызов инструмента, хотя и имеет стоимость (и мы разработаем это в точке производительности). Эти инструменты могут быть написаны с тысячами инструкций в C. Процесс должен быть создан, инструмент должен быть загружен, инициализирован, затем очищен, процесс уничтожен и ожидание.
Вызов cut
подобен открытию кухонного ящика,взять нож, использовать, вымыть, высушить, положить обратно в ящик. Когда вы делаете:
while read line; do
echo $line | cut -c3
done < file
Это как для каждой строки файла, получить читать
инструмент из кухонного ящика (очень неуклюжий, потому что он не был разработан для этого ), прочитать строку, вымыть свой инструмент чтения, положить его обратно в ящик. Затем назначьте встречу для эхо
и вырезать
инструмент, достать их из ящика, вызвать их, вымыть, высушить, положить обратно в ящик и так далее.
Некоторые из этих инструментов ( читать
и echo
) встроены в большинство оболочек, но это вряд ли имеет значение, поскольку echo
и cut
все еще должны выполняться в отдельных процессах.
Это как резать лук, но мыть нож и положить его обратно в кухонный ящик между каждым ломтиком.
Здесь очевидным способом является получить вырезать
инструмент из ящика, разрезать весь лук и положить его обратно в ящик после всей работы.
IOW, в раковинах, особенно чтобы обработать текст, вы призываете как можно меньше утилит и сделали, чтобы они сотрудничали к задаче, не управляют тысячами инструментов в последовательности, ждущей, чтобы каждый начал, пробег, вымылся прежде, чем управлять следующим.
Далее читайте в хорошем ответе Брюса . Внутренние инструменты обработки текста низкого уровня в оболочках (за исключением zsh
) ограничены, громоздки и обычно не подходят для общей обработки текста.
Как было сказано ранее, выполнение одной команды требует затрат. Огромная стоимость, если эта команда не builtin, но даже если они builtin, стоимость большая.
И оболочки не были разработаны, чтобы работать так, они не претендуют на то, чтобы быть performant языков программирования. Это не так, это просто интерпретаторы командной строки. Итак, на этом фронте была проведена небольшая оптимизация.
Кроме того, оболочки выполняют команды в отдельных процессах. Эти строительные блоки не имеют общей памяти или состояния. Когда вы делаете fgets ()
или fputs ()
в C, это функция в stdio. stdio хранит внутренние буферы для ввода и вывода для всех функций stdio, чтобы избежать слишком частого выполнения дорогостоящих системных вызовов.
Соответствующие утилиты оболочки ( читать
, эхо
, printf
) не могут этого сделать. читать
предназначено для чтения одной строки. Если он считывается после символа новой строки, это означает, что следующая команда будет пропущена. Таким образом, чтение
должно считывать входные данные по одному байту за раз (некоторые реализации имеют оптимизацию, если входные данные являются обычным файлом в том, что они считывают порции и ищут назад, но это работает только для обычных файлов и bash
, например, только считывает порции 128 байтов, что все еще намного меньше, чем это делают текстовые утилиты).
То же самое, что и на выходе, эхо
не может просто буферизировать его выход,он должен сразу же вывести его, так как следующая команда, которую вы выполняете, не будет использовать этот буфер совместно.
Очевидно, что выполнение команд последовательно означает, что вы должны ждать их, это небольшой танец планировщика, который дает управление от оболочки, к инструментам и обратно. Это также означает (в отличие от использования длинных экземпляров инструментов в конвейере), что нельзя использовать несколько процессоров одновременно, когда они доступны.
Между при чтении
цикла и (предположительно) эквивалентным вырезом -c3 < файл
в моем быстром тесте коэффициент времени ЦП составляет около 40000 в моих тестах (одна секунда против половины дня). Но даже если вы используете только сборки оболочки:
while read line; do
echo ${line:2:1}
done
(здесь с bash
), это все равно около 1:600 (одна секунда против 10 минут).
Очень трудно правильно подобрать код. Примеры, которые я привел, слишком часто встречаются в дикой природе, но у них много ошибок.
read
- это удобный инструмент, который может делать много разных вещей. Он может считывать входные данные от пользователя, разделять их на слова для хранения в различных переменных. строка считывания
делает не считывает строку ввода, или, возможно, считывает строку очень особым образом. Фактически из входных данных считываются слова , разделенные $ IFS
, где обратная косая черта может использоваться для удаления разделителей или символа новой строки.
При значении по умолчанию $ IFS
на входе, например,
foo\/bar \
baz
biz
строка чтения
сохранит «foo/bar baz»
в $ line
, а не «foo\/bar\»
, как ожидалось.
Чтобы прочитать строку, вам на самом деле нужно:
IFS= read -r line
Это не очень интуитивно, но так оно и есть, помните, раковины не предназначались для такого использования.
То же самое для эхо
. эхо
расширяет последовательности. Его нельзя использовать для произвольного содержимого, такого как содержимое случайного файла. Вместо этого требуется printf
.
И конечно, есть типичное забывание цитировать вашу переменную , в которую все попадают. Так что это больше:
while IFS= read -r line; do
printf '%s\n' "$line" | cut -c3
done < file
Теперь, еще несколько предостережений:
zsh
, что не работает, если ввод содержит символы NUL, в то время как по крайней мере GNU текстовые утилиты не будут иметь проблемы. Если мы хотим решить некоторые из этих проблем выше, это становится:
while IFS= read -r line <&3; do
{
printf '%s\n' "$line" | cut -c3 || exit
} 3<&-
done 3< file
if [ -n "$line" ]; then
printf '%s' "$line" | cut -c3 || exit
fi
Это становится все менее разборчивым.
Существует ряд других проблем с передачей данных командам через аргументы или извлечением их выходных данных в переменных:
-
(или +
иногда) expr
, test
... Когда вы начинаете работать с переменными оболочки и аргументами команд , вы вводите минное поле.
Если вы забудете процитировать ваши переменные , забудете конец маркера опций , работаете в языковых системах с многобайтовыми символами (норма в наши дни), вы наверняка внесете ошибки, которые рано или поздно станут уязвимыми.
TBD
До концептуальный и четкость идут, оболочки обычно интересуются файлами. Их "адресуемая единица" является файлом, и "адрес" является именем файла. Оболочки имеют все виды методов тестирования на существование файла, тип файла, форматирование имени файла (начинающийся globbing). Оболочки имеют очень немного примитивов для контакта с содержанием файла. Программисты Shell должны вызвать другую программу для контакта с содержанием файла.
из-за ориентации имени файла и имени файла, делая текстовое управление в оболочке является действительно медленным, как вы отметили, но также и требует неясного и искаженного стиля программирования.
существуют некоторые сложные ответы, предоставляя много интересной подробной информации для фанатов среди нас, но это действительно довольно просто - обработка большого файла в цикле оболочки является просто слишком медленной.
я думаю, что корреспондент интересен в типичном виде сценария оболочки, который может запуститься с некоторого парсинга командной строки, параметра среды, проверив файлы и каталоги и немного больше инициализации, прежде добирающийся до ее основного задания: прохождение через большого ориентированного на строку текстового файла.
Для первых частей ( инициализация
), обычно не имеет значения, что команды оболочки являются медленными - это только выполняет несколько дюжин команд, возможно, с несколькими короткими циклами.
Даже если мы пишем ту часть неэффективно,это обычно собирается взять меньше, чем секунда, чтобы сделать всю эту инициализацию, и это прекрасно - это только происходит однажды.
, Но когда мы добираемся до обработки большого файла, который мог иметь тысячи или миллионы строк, это не прекрасно для сценария оболочки для взятия значительной части секунды (даже если это - только несколько дюжин миллисекунд) для каждой строки, поскольку это могло бы составить в целом часы.
Именно тогда мы должны использовать другие инструменты, и красота сценариев оболочки Unix состоит в том, что они делают очень легким для нас сделать это.
Вместо того, чтобы использовать цикл для рассмотрения каждой строки мы должны передать целый файл до конвейер команд . Это означает, что, вместо того, чтобы назвать команды тысячами или миллионы времени, оболочка называет их только однажды. Это верно, что те команды будут иметь циклы для обработки файла линию за линией, но они не сценарии оболочки, и они разработаны, чтобы быть быстрыми и эффективными.
Unix имеет многих замечательных созданный в инструментах, в пределах от простого к комплексу, который мы можем использовать для создания наших конвейеров. Я обычно запускал бы с простых и только использовал бы более сложные при необходимости.
я также попытался бы придерживаться стандартных инструментов, которые доступны в большинстве систем и пытаются сохранить мое использование портативным, хотя это не всегда возможно. И если вашим любимым языком будет Python или Ruby, то возможно, вы не будете возражать против дополнительного усилия по проверке, что это установлено на каждой платформе, ваше программное обеспечение должно работать на инструментах :-)
Simple, включают голова
, хвост
, grep
, , вид
, сократил
, tr
, sed
, соединение
(при слиянии 2 файлов), и awk
остроты, среди многих других.
Удивительно, что некоторые люди могут сделать с сопоставлением с образцом и команды sed
.
, Когда это становится более сложным, и действительно необходимо применить некоторую логику к каждой строке, , awk
является хорошим вариантом - любой острота (некоторые люди помещают целые awk сценарии в 'одну строку', хотя это не очень читаемо), или в коротком внешнем сценарии.
Как awk
является интерпретируемым языком (как ваша оболочка), удивительно, что это может сделать линию за линией обработку так эффективно, но это является специальным для этого, и это действительно очень быстро.
И затем существует Perl
и огромное количество других языков сценариев, которые очень хороши в обработке текстовых файлов и также идут с большим количеством полезных библиотек.
И наконец, существует старый добрый C, если вам нужно максимальная скорость и высокая гибкость (хотя обработка текста немного утомительна). Но это - вероятно, очень плохое использование вашего времени для записи новой программы C для каждой различной обрабатывающей файл задачи, с которой вы сталкиваетесь. Я работаю с файлами CSV много, таким образом, я записал несколько универсальных утилит в C, который я могу снова использовать во многих различных проектах. В действительности это разворачивает диапазон 'простого,быстрые инструменты Unix, которые я могу назвать из своих сценариев оболочки, таким образом, я могу обработать большинство проектов только пишущий сценарии, который намного быстрее, чем запись и сделанный на заказ C отладки, кодируют каждый раз!
Некоторые заключительные подсказки:
LANG=C
экспорта, или много инструментов будут рассматривать ваши файлы простого ASCII, поскольку Unicode, делая их намного намного медленнее LC_ALL=C
экспорта, если вы хотите вид
произвести последовательное упорядочивание, независимо от среды! вид
ваши данные, которые, вероятно, займут больше времени (и ресурсы: ЦП, память, диск), чем все остальное так попытка минимизировать количество вид
команды и размер файлов, которые они сортируют правильный ответ Стефана Шазеласа основан на концепции оболочки делегирования каждой текстовой операции определенным двоичным файлам, таким как grep
, awk
, sed
и другие.
Так как bash может многое делать самостоятельно, удаление вилок может стать более быстрым (даже чем запуск другого интерпретатора для выполнения всей работы).
Образец см. В этом сообщении:
https://stackoverflow.com/a/38790442/1765658
и
https://stackoverflow.com/a/7180078/1765658
проверить и сравнить ...
Нет никакого внимания к пользовательскому вводу и безопасности !
Не пишите веб-приложение под bash !!
Но для множества задач администрирования сервера, где bash может использоваться вместо оболочки , использование встроенных команд bash может быть очень эффективным.
Инструменты для написания, такие как bin utils , - это не тот же вид работы, что и системное администрирование.
Так не те же люди!
Если системные администраторы должны знать оболочку
, они могут написать прототипы , используя его предпочитаемый (и самый известный) инструмент.
Если эта новая утилита (прототип) действительно полезна, некоторые другие люди могли бы разработать специальный инструмент, используя более подходящий язык.