Поиск по сайту:

Как использовать команды и расширения Bash History на Linux VPS


Введение

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

Во время сеанса терминала вы, вероятно, будете часто повторять некоторые команды и еще чаще вводить варианты этих команд. Хотя повторный ввод каждой команды может быть хорошей практикой в начале, в какой-то момент он переходит черту и становится разрушительным и раздражающим.

К счастью, в оболочке bash есть несколько довольно хорошо разработанных функций истории. Изучение того, как эффективно использовать историю bash и манипулировать ею, позволит вам тратить меньше времени на ввод текста и больше времени на выполнение реальной работы. Многие разработчики знакомы с DRY философией Не повторяйтесь. Эффективное использование истории bash позволяет приблизиться к этому принципу и ускорит рабочий процесс.

Предпосылки

Чтобы следовать этому руководству, вам потребуется доступ к компьютеру с операционной системой на базе Linux. Это может быть либо виртуальный частный сервер, к которому вы подключились с помощью SSH, либо ваша локальная машина. Обратите внимание, что это руководство было проверено с использованием сервера Linux с Ubuntu 20.04, но приведенные примеры должны работать на компьютере с любой версией любого дистрибутива Linux.

Если вы планируете использовать удаленный сервер, чтобы следовать этому руководству, мы рекомендуем вам сначала выполнить наше руководство по начальной настройке сервера. Это создаст для вас безопасную серверную среду, включая пользователя без полномочий root с привилегиями sudo и брандмауэр, настроенный с помощью UFW, которые вы сможете использовать для развития своих навыков работы с Linux.

Настройка истории по умолчанию

Прежде чем вы начнете фактически использовать свою историю команд, вам может быть полезно настроить некоторые параметры bash, чтобы сделать ее более полезной. Эти шаги необязательны, но они могут упростить поиск и выполнение команд, которые вы запускали ранее.

Bash позволяет настроить количество команд, которые он хранит в истории. На самом деле у него есть две отдельные опции для этого: параметр HISTFILESIZE настраивает, сколько команд хранится в файле истории, а HISTSIZE управляет числом, хранящимся в памяти для текущего сеанса. .

Это означает, что вы можете установить разумный предел размера истории в памяти для текущего сеанса и сохранить еще большую историю на диск, которую вы сможете просмотреть позже. По умолчанию bash устанавливает очень консервативные значения для этих параметров, но вы можете расширить их, чтобы воспользоваться преимуществами более крупной истории. Некоторые дистрибутивы уже увеличивают настройки истории bash по умолчанию, добавляя немного более щедрые значения.

Откройте файл ~/.bashrc в предпочитаемом вами текстовом редакторе, чтобы изменить эти настройки. Здесь мы будем использовать nano:

  1. nano ~/.bashrc

Найдите параметры HISTSIZE и HISTFILESIZE. Если они установлены, не стесняйтесь изменять значения. Если этих параметров нет в вашем файле, добавьте их сейчас. Для целей этого руководства сохранение 10000 строк на диск и загрузка последних 5000 строк в память будут работать нормально. Это консервативная оценка для большинства систем, но вы можете уменьшить эти цифры, если заметите влияние на производительность:

. . .

# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=5000
HISTFILESIZE=10000

. . .

По умолчанию bash записывает свою историю в конце каждого сеанса, перезаписывая существующий файл обновленной версией. Это означает, что если вы вошли в систему с несколькими сеансами bash, только последний из них сохранит свою историю.

Вы можете обойти это, установив параметр histappend, который будет добавлять, а не перезаписывать историю. Это может быть уже установлено, но если это не так, вы можете включить это, добавив эту строку:

. . .
shopt -s histappend
. . .

Если вы хотите, чтобы bash немедленно добавлял команды в вашу историю, а не ждал окончания каждого сеанса (чтобы команды в одном терминале были мгновенно доступны в другом), вы также можете установить или добавить историю -a в параметр PROMPT_COMMAND, содержащий команды, которые выполняются перед каждой новой командной строкой.

Чтобы настроить это правильно, вам нужно настроить PROMPT_COMMAND bash, чтобы изменить способ записи команд в файл истории и в память текущего сеанса оболочки:

  • Во-первых, вам нужно немедленно добавить файл истории с помощью history -a.
  • Затем вы должны очистить текущую историю в сеансе оболочки с помощью history -c.
  • Наконец, чтобы загрузить обновленную историю обратно в сеанс оболочки, используйте команду history -r.

Соединяя все эти команды по порядку в переменной оболочки PROMPT_COMMAND, вы получите следующее, которое вы можете вставить в свой файл .bashrc:

. . .
export PROMPT_COMMAND="history -a; history -c; history -r; $PROMPT_COMMAND"
. . .

Когда вы закончите, сохраните файл и выйдите. Если вы редактировали файл .bashrc с помощью nano, сделайте это, нажав CTRL + X, Y, а затем ВВОД.

Чтобы применить изменения, либо выйдите из системы и войдите снова, либо используйте файл, выполнив:

  1. source ~/.bashrc

Таким образом, вы настроили то, как ваша оболочка обрабатывает историю команд. Теперь вы можете попрактиковаться в поиске ваших предыдущих команд с помощью команды history.

Просмотр вашей предыдущей истории Bash

Чтобы просмотреть историю bash, используйте команду history. Это распечатает наши последние команды, по одной команде в строке. Это должно вывести не более того количества строк, которое вы выбрали для переменной HISTSIZE. На данный момент, вероятно, будет меньше:

  1. history
Output
. . . 43 man bash 44 man fc 45 man bash 46 fc -l -10 47 history 48 ls -a 49 vim .bash_history 50 history 51 man history 52 history 10 53 history

Каждая команда, возвращаемая history, связана с числом для удобства поиска. В этом руководстве будет рассказано, как это может быть полезно позже.

Вы можете обрезать вывод, указав число после команды. Например, если вы хотите вернуть только последние 5 выполненных команд, вы можете ввести:

  1. history 5
Output
50 history 51 man history 52 history 10 53 history 54 history 5

Чтобы найти все команды history, содержащие определенную строку, вы можете направить результаты в команду grep, которая ищет заданную строку в каждой строке. Например, вы можете найти строки, содержащие cd, набрав:

  1. history | grep cd
Output
33 cd Pictures/ 37 cd .. 39 cd Desktop/ 61 cd /usr/bin/ 68 cd 83 cd /etc/ 86 cd resolvconf/ 90 cd resolv.conf.d/

Есть много ситуаций, когда возможность получить список команд, которые вы ранее запускали, может быть полезной. Если вы хотите снова запустить одну из этих команд, вы можете скопировать одну из команд из вашего вывода и вставить ее в свое приглашение. Это работает, но bash поставляется с несколькими ярлыками, которые позволяют вам извлекать, а затем автоматически выполнять команды из вашей истории.

Выполнение команд из вашей истории Bash

Печать истории команд может быть полезной, но на самом деле это не поможет вам получить доступ к этим командам, кроме как в качестве справки.

Вы можете вызвать и немедленно выполнить любую из команд, возвращаемых операцией history, по ее номеру, перед которым стоит восклицательный знак (!). Предполагая, что ваши результаты history совпадают с результатами из предыдущего раздела, вы можете быстро просмотреть справочную страницу для команды history, набрав:

  1. !51

Это немедленно вызовет и выполнит команду, связанную с номером истории 51.

Вы также можете выполнять команды относительно вашего текущего положения, используя синтаксис !-n, где \n заменяется количеством предыдущих команд, которые вы хотите вызвать.

В качестве примера предположим, что вы выполнили следующие две команды:

  1. ls /usr/share/common-licenses
  2. echo hello

Если вы хотите вспомнить и выполнить команду, которую вы запускали перед самой последней (команда ls), вы можете ввести !-2:

  1. !-2

Чтобы повторно выполнить последнюю запущенную команду, вы можете запустить !-1. Однако bash предоставляет ярлык, состоящий из двух восклицательных знаков, который заменяет самую последнюю команду и выполняет ее:

  1. !!

Многие люди используют это, когда вводят команду, но забывают, что для ее выполнения им нужны привилегии sudo. Ввод sudo !! повторно выполнит команду с sudo перед ней:

  1. touch /etc/hello
Output
touch: cannot touch `/etc/hello': Permission denied
  1. sudo !!
Output
sudo touch /etc/hello [sudo] password for sammy:

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

Прокрутка истории Bash

Есть несколько способов прокручивать историю bash, помещая каждую последующую команду в командную строку для редактирования.

Наиболее распространенный способ сделать это — нажать клавишу со стрелкой вверх в командной строке. Каждое дополнительное нажатие клавиши со стрелкой вверх возвращает вас в историю командной строки.

Если вам нужно пойти в другом направлении, клавиша со стрелкой вниз перемещает историю в противоположном направлении, наконец, возвращая вас к текущему пустому приглашению.

Если перемещение руки полностью к клавишам со стрелками кажется большой проблемой, вы можете переместиться назад по истории команд, используя комбинацию CTRL + P и использовать CTRL + N комбинация, чтобы снова двигаться вперед по вашей истории.

Если вы хотите вернуться к текущей командной строке, вы можете сделать это, нажав META + >. В большинстве случаев клавиша «мета» — это клавиша ALT, поэтому META + > будет означать нажатие ALT + SHIFT + .. Это полезно, если вы оказались далеко в своей истории и хотите вернуться к своей пустой подсказке.

Вы также можете перейти к первой строке истории команд, выполнив обратный маневр и набрав META + <. Обычно это означает нажатие ALT + SHIFT + .

Подводя итог, вот некоторые клавиши и комбинации клавиш, которые вы можете использовать для прокрутки истории и перехода к любому концу:

  • Клавиша со стрелкой ВВЕРХ: прокрутка истории назад.
  • CTRL + P: прокрутка истории назад.
  • Клавиша со стрелкой ВНИЗ: прокрутка истории вперед.
  • CTRL + N: прокрутить историю вперед.
  • ALT + SHIFT + .: перейти к концу истории (самому последнему).
  • ALT+SHIFT+,: перейти к началу истории (самому дальнему)

Поиск по истории Bash

Хотя передача команды history через grep может быть полезным способом сузить результаты, во многих ситуациях это не идеально.

Bash включает функцию поиска по своей истории. Типичный способ использования этого — поиск в истории назад (самые последние результаты возвращаются первыми) с помощью комбинации клавиш CTRL + R.

Например, вы можете ввести CTRL + R и начать вводить часть предыдущей команды. Вам нужно только ввести часть команды. Если вместо этого он соответствует нежелательной команде, вы можете снова нажать CTRL + R для получения следующего результата.

Если вы случайно передали нужную команду, вы можете двигаться в противоположном направлении, набрав CTRL + S. Это также может быть полезно, если вы перешли к другому моменту в своей истории с помощью клавиш в последнем разделе и хотите выполнить поиск вперед.

Имейте в виду, что во многих терминалах комбинация CTRL + S отображается для приостановки сеанса терминала. Это перехватит любые попытки передать CTRL + S в bash и «заморозит» ваш терминал. Чтобы разморозить, введите CTRL + Q, чтобы разблокировать сеанс.

Эта функция приостановки и возобновления не нужна в большинстве современных терминалов, и вы можете без проблем отключить ее, выполнив следующую команду:

  1. stty -ixon

stty — это утилита, которая позволяет вам изменять настройки вашего терминала из командной строки. Вы можете добавить эту команду stty -ixon в конец файла ~/.bashrc, чтобы сделать это изменение постоянным.

Если вы сейчас снова попытаетесь выполнить поиск с помощью CTRL + S, он должен работать так, как ожидалось, чтобы вы могли выполнять поиск вперед.

Поиск после ввода части команды

Обычный сценарий, в котором вы можете оказаться, состоит в том, чтобы ввести часть команды только для того, чтобы потом понять, что вы выполнили ее ранее и можете искать ее в истории.

Правильный способ поиска с использованием того, что уже находится в вашей командной строке, — переместить курсор в начало строки с помощью CTRL + A, вызвать обратную историю с помощью CTRL + R, вставьте текущую строку в поиск с помощью CTRL + Y, а затем снова используйте CTRL + R для поиска в обратном порядке.

Например, предположим, что вы хотите обновить кэш пакетов в системе Ubuntu. Вы уже набирали это недавно, но не думали об этом, пока снова не набрали sudo в командной строке:

  1. sudo

В этот момент вы понимаете, что это операция, которую вы определенно проделали в последний день или около того. Вы можете нажать CTRL + A, чтобы переместить курсор в начало строки. Затем нажмите CTRL + R, чтобы вызвать обратный добавочный поиск в истории. Побочным эффектом этого является копирование всего содержимого командной строки, которое было после позиции курсора, и помещение его в буфер обмена.

Затем нажмите CTRL + Y, чтобы вставить сегменты команд, которые вы только что скопировали из командной строки, в поиск. Наконец, нажмите CTRL + R, чтобы вернуться назад по истории и выполнить поиск команд, содержащих только что вставленный контент.

Поначалу использование таких ярлыков может показаться утомительным, но когда вы к ним привыкнете, они могут оказаться весьма полезными. Это чрезвычайно полезно, когда вы оказываетесь в ситуации, когда вы набрали половину сложной команды и знаете, что вам понадобится история, чтобы закончить остальные.

Вместо того, чтобы думать о них как об отдельных комбинациях клавиш, может помочь вам думать о них как об одной составной операции. Вы можете просто удерживать нажатой клавишу CTRL, а затем нажимать A, R, Y, а затем R нажмите клавишу последовательно.

Знакомство с более продвинутым расширением истории

В этом руководстве уже были затронуты некоторые из наиболее фундаментальных методов расширения истории, которые предоставляет bash. Вот некоторые из них, которые мы уже рассмотрели:

  • !!: расширить до последней команды
  • !n: развернуть команду с номером истории \n.
  • !-n: расширить до команды, которая была за \n количество команд до текущей команды в истории.

Обозначения событий

Приведенные выше три примера являются экземплярами указателей событий. Как правило, это способы вызова предыдущих команд истории с использованием определенных критериев. Они являются частью выбора доступных операций.

Например, вы можете выполнить последнюю команду ssh, которую вы выполнили, набрав что-то вроде:

  1. !ssh

Это ищет строки в вашей истории команд, которые начинаются с ssh. Если вы хотите найти строку, которая не находится в начале команды, вы можете окружить ее символами ?. Например, чтобы повторить предыдущую команду apt-cache search, вы, вероятно, могли бы запустить следующую команду, чтобы найти и выполнить ее:

  1. !?search?

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

  1. ^original^replacement^

Это вызовет предыдущую команду (точно так же, как !!), найдет экземпляр original в командной строке и заменит его на <замена. Затем он выполнит команду, используя строку замены.

Это полезно для работы с такими вещами, как орфографические ошибки. Например, предположим, что вы по ошибке запустили эту команду при попытке прочитать содержимое файла /etc/hosts:

  1. cat /etc/hosst
Output
cat: /etc/hosst: No such file or directory

Вместо того, чтобы переписывать всю команду, вы можете запустить следующее:

  1. ^hosst^hosts^

Это исправит ошибку в предыдущей команде и успешно выполнит ее.

Обозначения слов

После указателей событий можно добавить двоеточие (:), за которым следует обозначение слова, чтобы выбрать часть соответствующей команды.

Он делает это, разделяя команду на «слова», которые определяются как любой фрагмент, разделенный пробелом. Это дает вам некоторые интересные возможности для взаимодействия с параметрами вашей команды.

Нумерация слов начинается с начальной команды как \0, первого аргумента как \1 и продолжается оттуда.

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

  1. ls /usr/share/common-licenses
  2. cd !!:1

В таких случаях, когда вы работаете с последней командой, вы можете сократить ее, удалив второй !, а также двоеточие:

  1. cd !1

Это будет работать таким же образом.

Вы можете обратиться к первому аргументу с помощью знака вставки (^), а к последнему аргументу — со знаком доллара ($), если это имеет смысл для ваших целей. Они более полезны при использовании диапазонов вместо конкретных чисел. Например, у вас есть три способа передать все аргументы из предыдущей команды в новую команду:

  1. !!:1*
  2. !!:1-$
  3. !!:*

Одиночный * расширяется до всех частей вызываемой команды, кроме исходной команды. Точно так же вы можете использовать число, за которым следует *, чтобы указать, что все после указанного слова должно быть включено.

Модификаторы

Еще одна вещь, которую вы можете сделать, чтобы улучшить поведение строки истории, которую вы вызываете, — это изменить поведение отзыва, чтобы манипулировать самим текстом. Для этого вы можете добавить модификаторы после двоеточия (:) в конце раскрытия.

Например, вы можете отрезать путь, ведущий к файлу, используя модификатор h (он означает \head), который удаляет путь до последней косой черты (/ ). Имейте в виду, что это не будет работать так, как вы хотите, если вы используете это для усечения пути к каталогу, и путь заканчивается косой чертой.

Обычный вариант использования этого — если вы изменяете файл и понимаете, что хотите перейти в каталог файла, чтобы выполнять операции со связанными файлами.

Например, предположим, что вы запускаете эту команду, чтобы распечатать содержимое лицензии на программное обеспечение с открытым исходным кодом на своем выходе:

  1. cat /usr/share/common-licenses/Apache-2.0

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

  1. cd !!:$:h

Если вы запустите pwd, который распечатает ваш текущий рабочий каталог, вы обнаружите, что перешли в каталог, включенный в предыдущую команду:

  1. pwd
Output
/usr/share/common-licenses

Оказавшись там, вы можете снова открыть этот файл лицензии, чтобы перепроверить, на этот раз в пейджере, таком как less.

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

  1. less !cat:$:t

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

Другим чрезвычайно полезным модификатором является модификатор r, который удаляет завершающее расширение. Это может быть полезно, если вы используете tar для извлечения файла и хотите впоследствии перейти в результирующий каталог. Предполагая, что созданный каталог имеет то же имя, что и файл, вы можете сделать что-то вроде:

  1. tar xzvf long-project-name.tgz
  2. cd !!:$:r

Если в вашем архиве используется расширение tar.gz вместо tgz, вы можете просто передать модификатор дважды:

  1. tar xzvf long-project-name.tgz
  2. cd !!:$:r:r

Аналогичный модификатор, e, удаляет все, кроме конечного расширения.

Если вы не хотите выполнять команду, которую вы вызываете, а хотите только найти ее, вы можете использовать модификатор p, чтобы bash повторил команду вместо ее выполнения.

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

Например, представьте, что вы запустили команду find в своем домашнем каталоге, а затем поняли, что хотите запустить ее из корневого (/) каталога. Вы можете проверить правильность подстановки следующим образом (при условии, что исходная команда связана с номером 119 в вашей истории):

  1. find ~ -name "file1"
  2. !119:0:p / !119:2*:p
Output
find / -name "file1"

Если возвращенная команда верна, вы можете выполнить ее с помощью комбинации клавиш CTRL + P .

Вы также можете делать замены в своей команде, используя синтаксис s/исходный/новый/.

Например, вы могли бы добиться этого, набрав:

  1. !119:s/~/\//

Это заменит первый экземпляр шаблона поиска (~).

Вы можете заменить каждое совпадение, также передав флаг g с s. Например, если вы хотите создать файлы с именами file1, file2 и file3, а затем хотите создать каталоги с именами dir1, dir2, dir3, вы можете сделать это:

  1. touch file1 file2 file3
  2. mkdir !!:*:gs/file/dir/

Конечно, в этом случае может быть более интуитивно просто запустить mkdir dir1 dir2 dir3. Однако, когда вы освоитесь с модификаторами и другими инструментами расширения истории bash, вы сможете значительно расширить свои возможности и производительность в командной строке.

Заключение

Прочитав это руководство, вы теперь должны иметь хорошее представление о том, как вы можете использовать доступные вам операции с историей. Некоторые из них, вероятно, будут более полезными, чем другие, но полезно знать, что в bash есть эти возможности на случай, если вы окажетесь в ситуации, когда было бы полезно их выкопать.

По крайней мере, команда history сама по себе, обратный поиск и основные расширения истории могут многое сделать, чтобы помочь вам ускорить рабочий процесс.