[Из песочницы] Работаем в консоли быстро и эффективно
В сети можно встретить много советов по эффективной работе в консоли. В большинстве таких статей авторы рассказывают про банальности типа «выучите горячие клавиши» или »sudo !!
запустит последнюю команду под sudo». Я же расскажу о том, что делать, когда вы уже выучили горячие клавиши и знаете про sudo !!
.
Терминал должен запускаться мгновенно
Сколько времени вам нужно, чтобы запустить терминал? А ещё один? Долгое время мой терминал запускался сочетанием Ctrl+Alt+T и я думал, что это быстро. Но когда я переехал с Openbox на i3, то стал запускать терминал через Win+Enter, это сочетание было в конфиге по умолчанию. И знаете что? Я больше не считаю, что Ctrl+Alt + T — это быстро.
Разумеется, прикол не в выигрыше миллисекунд, а в том, что вы открываете терминал на уровне рефлексов, совершенно не замечая этого.
Если вы часто работаете в терминале, но для его запуска тянетесь к мышке, то попробуйте настроить удобную горячую клавишу. Я уверен, вам понравится.
Zsh вместо Bash
Это холиварная тема, знаю. Zsh стоит поставить хотя бы ради трёх фич: продвинутый автокомплит, коррекция опечаток и множественный pathname completition: когда один Tab превращает /u/s/d
в /usr/share/doc
. Arch Linux уже давно перешёл на zsh в своём установочном диске. Я надеюсь что однажды zsh станет дефолтным шеллом в Ubuntu. Это будет исторический момент.
Начать использовать zsh вообще не сложно. Установите его через менеджер пакетов и возьмите какой-нибудь готовый конфиг. Я рекомендую конфиг, который используется в Arch Linux:
wget -O ~/.zshrc https://git.grml.org/f/grml-etc-core/etc/zsh/zshrc
Осталось только поменять «шелл по-умолчанию» на zsh и перелогиниться.
chsh -s $(which zsh)
Всё, продолжайте работать как будто ничего не произошло.
Каким должен быть shell prompt
Shell prompt (приглашение командной строки) — это тот маленький текст, который выводится в терминале перед вашей командой. Его нужно настроить под свой характер работы. Воспринимайте его как приборную панель автомобиля. Поместите туда полезную информацию, пусть он будет помогать ориентироваться. Сделайте его удобным, особенно если видите его каждый день!
Shell prompt должен показывать текущий каталог шелла. Если текущий каталог не выводится в shell prompt, вам придётся держать его в голове и периодически проверять командой pwd
. Не надо так. Держите в голове более важные вещи и не тратьте время на команду pwd
.
Если вы периодически переключаетесь со своего пользователя на рута, вам нужна индикация текущего пользователя. Зачастую важно не конкретное имя пользователя, а его статус (обычный или рут). Проще всего это сделать цветом: красный shell prompt у рута, зелёный у своего пользователя. Так вы ни за что не спутаете рутовый шелл с обычным.
Если вы подключаетесь к серверам по ssh, то вам нужно как-то отличать свой локальный шелл от серверного. Для этого shell prompt должен содержать имя хоста, а ещё лучше — индикатор ssh-соединения.
Shell prompt умеет показывать код возврата последней команды. Напомню, что нулевой код возврата означает, что команда завершилась успешно, ненулевой — команда завершилась неуспешно. Код возврата последней команды можно узнать командой echo $?
, но набирать это всё на клавиатуре слишком долго. Пусть лучше shell prompt сообщит, если команда завершилась неуспешно.
Если вы работаете с git-репозиториями, то будет нелишним выводить в shell prompt статус репозитория: текущую ветку и состояние рабочей директории. Так вы сэкономите время на командах git status
и git branch
и не ошибётесь веткой при коммите.
Кто-то добавляет в свой shell prompt часы или имя виртуального терминала (tty), или какие-то произвольные закорючки. Это всё лишнее. Лучше оставить побольше места для команд.
Мой shell prompt в разных условиях выглядит так:
На скриншоте видно, что схожую задачу выполняет заголовок окна терминала. Это тоже кусок приборной панели и его тоже можно настроить.
Как это всё реализовать в своём .zshrc
? За левый prompt отвечает переменная PROMPT
, за правый — RPROMPT
. Определить статус пользователя (обычный или рут) поможет переменная EUID, а наличие ssh-соединения — SSH_CLIENT или SSH2_CLIENT. Получаем такую заготовку:
if [[ -n "$SSH_CLIENT" || -n "$SSH2_CLIENT" ]]; then
if [[ $EUID == 0 ]]; then
PROMPT=...
else
PROMPT=...
fi
else # not SSH
if [[ $EUID == 0 ]]; then
PROMPT=...
else
PROMPT=...
fi
fi
Я специально не указываю готовый к копипасту код, потому что конкретная реализация — это дело вкуса. Если же вы не хотите заморачиваться и мой скриншот не вызывает у вас отвращения, можете взять конфиг с гитхаба.
Резюме:
- Необходимый минимум — это текущий каталог.
- Рутовый шелл должен быть хорошо заметен.
- Имя пользователя не несёт полезной нагрузки, если вы всегда сидите под одним пользователем.
- Хостнэйм полезен, если вы подключаетесь к серверам по SSH. Не обязателен, если всегда работаете на одной машине.
- Неуспешное завершение последней команды полезно видеть сразу.
- Статус git-репозитория экономит время на командах
git status
иgit branch
и является дополнительной защитой от дурака.
Активное использование истории команд
Бо́льшую часть команд в своей жизни вы вводите больше одного раза, а значит было бы удобно выдёргивать их из истории вместо того, чтобы набирать заново. Все современные шеллы умеют запоминать историю команд и предоставляют несколько способов поиска по этой истории.
Возможно вы уже умеете копаться в истории сочетанием Ctrl+R. У него есть два существенных недостатка:
- Чтобы начать поиск, поле ввода должно быть пустым. Т.е. в случае «начал набирать команду — вспомнил про поиск» придётся стереть начатое, нажать Ctrl+R и повторить ввод. Это очень долго.
- Поиск «вперёд» по умолчанию не работает, т.к. Ctrl+S останавливает терминал.
Как работает самый быстрый и удобный поиск:
- вы начинаете набирать команду,
- вы вспоминаете про поиск,
- вы нажимаете хоткей и шелл предлагает команды из истории, которые начинались точно так же.
Например, вы хотите синхронизировать некий локальный каталог с удалённым с помощью rsync
. Вы уже делали это пару часов назад и хотите вытащить команду из истории. Набираете rsync
, один-два раза нажимате некую комбинацию, и вот заветная команда готова к запуску. Вам не надо предварительно включать режим поиска по истории, shell prompt не меняется на (reverse-i-search)':
, ничего никуда не прыгает. Вы просто перебираете команды из истории. Так же, как и стрелочками ↑↓ вы перебираете ранее введённые команды, только с фильтром по началу комады. Это чертовски удобно и экономит уйму времени.
В оболочках fish и ipython такой поиск уже назначен на стрелочки. Я думаю что многие перешли на fish только ради такого поведения стрелочек.
В bash и zsh по-умолчанию такой поиск не работает, его надо включить руками. Я настроил PgUp для поиска назад и PgDown для поиска вперёд. Далековато до них тянуться, но я уже привык. Возможно в будущем переназначу на что-нибудь поближе, например Ctrl+P и Ctrl+N.
Для bash надо добавить пару строк в /etc/inputrc
или ~/.inputrc
:
"\e[5~": history-search-backward
"\e[6~": history-search-forward
Если вы взяли готовый zshrc
, то там поиск скорее всего уже назначен на PgUp и PgDown. Если нет, то добавьте в ~/.zshrc
bindkey "^[[5~" history-beginning-search-backward # pg up
bindkey "^[[6~" history-beginning-search-forward # pg down
Любопытно, что со временем я стал писать команды из расчёта, что позже буду поднимать их из истории. Вот несколько приёмов:
Объединение команд, которые всегда выполняются друг за другом
ip link set eth1 up && dhclient eth1
mkdir /tmp/t && mount /dev/sdb1 /tmp/t
Абсолютные пути вместо относительных позволяют запускать команду, находясь в любом каталоге: vim ~/.ssh/config
вместо vim .ssh/config
, systemd-nspawn /home/chroot/stretch
вместо systemd-nspawn stretch
и т.д.
Подстановка по маске (wildcard) делает команды более универсальными. Обычно использую с chmod
и chown
.
chown root:root /var/www/*.sq && chmod 644 /var/www/*.sq
Горячие клавиши
Перечислю необходимый минимум.
Alt+. — подставляет последний аргумент предыдущей команды. Также можно набрать последовательность !$
.
Ctrl+A, Ctrl+E — переход к началу и концу редактируемой команды соответственно.
Ctrl+U, Ctrl+Y — вырезать всё в буфер обмена, вставить из буфера. Выручает, когда печатаешь сложную команду, а потом понимаешь, что перед ней надо выполнить другую. Хм, куда бы припрятать текущий ввод? Вот сюда и припрятать.
Ctrl+W — стирает одно слово слева от курсора. Если зажать и удерживать, быстро очищает командную строку. По умолчанию текст не удаляется, а помещается в буфер (который для Ctrl+Y).
Ctrl+K — удаляет от курсора и до конца строки. Ctrl+A, Ctrl+K быстро очищает командную строку.
PgUp, PgDown, Ctrl+R — поиск по истории.
Ctrl+L — очистить терминал.
Отзывчивость клавиатуры
Расскажу про маленькую настройку, которая позволяет быстрее скроллить, перемещаться по тексту или стирать. Что мы делаем, когда хотим стереть что-то длинное? Зажимаем Backspace и смотрим как курсор бежит назад, забирая лишние буквы. Что при этом происходит? При нажатии Backspace стирается один символ, затем идёт небольшая задержка, затем срабатывает автоповтор: Backspace убирает символы один за другим, как будто по нему постоянно стучат.
Я рекомендую отрегулировать задержку и частоту работы автоповтора под скорость своих пальцев. Задержка перед срабатыванием автоповтора нужна когда вы хотите удалить только один символ — она даёт вам время отпустить клавишу. Слишком долгая задержка заставляет ждать автоповтора. Не настолько долго, чтобы раздражать, но достаточно, чтобы тормозить перенос мыслей из головы в компьютер. Чем выше частота повтора, тем быстрее стирается текст, и тем сложнее вовремя остановить этот процесс. Суть настройки заключается в поиске золотой середины.
Итак, волшебная команда:
xset r rate 190 20
190 — длительность задержки в миллисекундах,
20 — частота в количестве повторений в секунду.
Я рекомендую начать с этих значений и понемногу уменьшать задержку до появления ложных срабатываний, затем чуть-чуть вернуть назад. Если установить очень короткую задержку, то клавиатурой станет невозможно пользоваться. Придётся перезагружать X-сервер или компьютер целиком. Так что будьте аккуратнее.
Чтобы сохранить параметры, добавьте эту команду куда-нибудь в автостарт иксов.
Индикатор завершения процесса
Мне довольно часто приходится запускать долгие процессы: какой-нибудь жирный бэкап, копирование по сети, распаковку/запаковку архивов, сборку пакетов и т.д. Обычно я запускаю такой процесс, переключаюсь на другую задачу и периодически поглядываю не завершился ли мой долгий процесс. Бывает, что я сильно погружаюсь в работу и забываю о нём. Решение — добавить нотификацию завершения процесса, которая выведет меня из транса.
Для этого можно использовать разные средства: notify-send, dzen2, beep, aplay. Все они по-своему хороши, но не работают по ssh. Поэтому я использую terminal beep:
long-running-command; echo $'\a'
В кодировке ASCII есть символ 0×7, именуемый bell. Он предназначен для того, чтобы пищать PC-спикером. PC-спикер — это несовременно, он не везде есть, а ещё его не слышно в наушниках. Поэтому некоторые терминалы применяют так называемый visual bell. Я использую urxvt, и он делает visual bell включением флага urgency. Это когда окно сообщает вам, что оно требует внимания.
Вы можете прямо сейчас проверить как ваш терминал реагирует на символ bell:
sleep 3; echo $'\a'
Три секунды даётся, чтобы вы успели переключиться на другое окно, иначе может не сработать.
К сожалению, visual bell через urgency есть не во всех терминалах. Я проверил самые популярные.
терминал | visual bell через urgency |
---|---|
konsole | включается в настройках |
urxvt | есть |
xfce4-terminal | включается в настройках |
xterm | нет |
cool-retro-term | нет |
lxterminal | нет |
gnome-terminal | нет |
Писать echo $'\a'
слишком долго, поэтому я сделал алиас wake
.
Алиасы
Команды cp
, scp
и rm
всегда должны работать рекурсивно. Аргумент -r
— это просто дурное легаси! У cp
ещё можно найти оправдание:
cp * foodir
скопирует в foodir только файлы, а с ключом -r
подумает, что вы решили скопировать foodir в самого себя. Но как часто вам нужна эта фича?
У rm
и scp
вообще нет оправданий, они просто зануды! Похожая ситуация с ключом -p
у команды mkdir
. Так что смело добавляем в ~/.zshrc
alias cp='cp -r'
alias scp='scp -r'
alias rm='rm -r'
alias mkdir='mkdir -p'
Ух, как же я раньше без этого жил! Можно пойти ещё дальше и добавить -f
у rm
, но на свой страх и риск. Я пока себя сдерживаю.
Разные вариации ls
вы скорее всего уже используете, ведь это самые популярные алиасы.
alias ls='ls -F --color=auto'
alias la='ls -A --color=auto'
alias ll='ls -l --color=auto -h'
alias lla='ll -A --color=auto -h'
Ну и цветной grep намного приятнее бесцветного:
alias grep='grep --colour=auto'
Не забывайте, что алиасы не работают в скриптах! Там надо указывать все ключи.
Слепой метод печати
Как бы банально это ни было, но слепой десятипальцевый метод печати позволяет быстрее печатать. Поначалу будет тяжело, но со временем вы разгонетесь до невиданных ранее скоростей.
Осваивать слепой метод печати лучше всего на каникулах или в отпуске, когда вас никто не торопит. В процессе обучения ни в коем случае нельзя спешить. Ваша задача — запомнить где какая буква находится. Причём не столько мозгом, сколько мышцами. Лучше набирать медленно, но без ошибок, чем быстро с ошибками. Помните: мастера добиваются высоких скоростей не за счёт быстрых пальцев, а потому что не делают ошибок.
Не стоит поначалу увлекаться клавогонками. Психологически тяжело оставаться хладнокровным во время соревнований. Учитесь на тренажёрах. Хорошо, когда тренажёр предлагает слова, которые можно мысленно произнести. Я учился на онлайн-тренажёрах vse10 и typingstudy. Известный тренажёр «Соло на клавиатуре» мне показался бестолковым.
Начинать стоит с центрального ряда «фывапролджэ». Только после того, как вы запомните где какая клавиша расположена, стоит двигаться дальше. Только после этого.
Делайте перерывы. Давайте отдых мозгу и пальцам. Чувствуете, что посыпались ошибки — пора делать перерыв.
Сначала я освоил слепой метод печати на русском языке и прифигел от ускорения. Сейчас совершенствую навык в английской раскладке.