[![Вступайте в англоязычный чат проекта https://gitter.im/jlevy/the-art-of-command-line](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/jlevy/the-art-of-command-line?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Продвинутому использованию командной строки зачастую не уделяют достаточного внимания. О терминале говорят, как о чем-то мистическом. На самом же деле, это умение очевидно (и не очевидно) увеличивает Вашу продуктивность в работе. Данный документ является подборкой заметок и советов, которые я нашел для себя полезными, работая с командной строкой в Linux. Некоторые из их них – простые и очевидные, но некоторые - довольно сложные. И предназначены для решения конкретных задач. Это небольшая публикация, но если Вы уже знаете обо всем, что тут написано, и можете вспомнить, как это все использовать – вы много знаете!
начав идею там, похоже, что стоит развить ее на Github, где обитают люди, которые талантливее меня и могут предлагать улучшения данной подборки. Если Вы заметили ошибки (во всех вариантах перевода), пожалуйста оставьте тикет или киньте пулл-реквест (заранее изучив описание и посмотрев на уже созданнные тикеты и пулл-реквесты).
- Данная публикация предназначена как для новичков, так и для опытных людей. Цели: *объемность* (собрать все важные аспекты использования командной строки), *практичность* (давать конкретные примеры для самых частых юзкейсов) и *краткость* (не стоит углубляться в неочевидные вещи, о которых можно почитать в другом месте).
- Этот документ написан для пользователей Linux, с единственным исключеним – секцией "[MacOS only](#macos-only)". Все остальное подходит и может быть установлено под все UNIX/MacOS системы (и даже Cygwin).
- Эта инструкция включает в себя стандартные Unix команды и те, для которых нужно устанавливать сторонние пакеты. Они настолько полезны, что стоят того, чтобы их установили.
- Для того, чтобы руководство оставалось одностраничным, вся информация вставлена прямо сюда. Вы достаточно умные для того, чтобы самостоятельно изучить вопрос более детально в другом месте. Используйте `apt-get`/`yum`/`dnf`/`pacman`/`pip`/`brew` (в зависимости от вашей системы управления пакетами) для установки новых программ.
- Выучите основы Баша. Просто возьмите и напечатайте `man bash` в терминале и хотя бы просмотрите его; он довольно просто читается и он не очень большой. Другие шеллы тоже могут быть хороши, но Баш – мощная программа, и Баш всегда под рукой (использование *исключительно* zsh, fish и т.д., которые наверняка круто выглядят на Вашем ноуте во многом Вас ограничивает, например Вы не сможете использовать возможности этих шеллов на уже существующем сервере).
- Выучите как использовать хотя бы один консольный редактор текста. Идеально Vim (`vi`), ведь у него нет конкурентов, когда вам нужно быстренько что-то подправить (даже если Вы постоянно сидите на Emacs/какой-нибудь тяжелой IDE или на каком-нибудь модном хипстерском редакторе)
- Знайте как читать документацию через `man` (для любознательных – `man man`; `man` по углам документа в скобках добавляет номер, например 1 – для обычных команд, 5 – для файлов, конвенций, 8 – для административных команд). Ищите мануалы через `apropos`, и помните, что некоторые команды – не бинарники, а встроенные команды Баша, и помощь по ним можно получить через `help` и `help -d`.
- Узнайте о том, как перенаправлять ввод и вывод через `>` и `<` и пайпы `|`. Помните, что `>` – переписывает выходной файл, а `>>` добавляет к нему. Узнайте побольше про stdout и stderr.
- Узнайте побольше про раскрытие file glob элементов `*` (а также `?` и `{`...`}`), кавычки, а также разницу между двойными `"` и одинарными `'` кавычками. (Больше о расширении переменных читайте ниже.)
- Основы работы с файлами: `ls` и `ls -l` (в частности, узнайте, что значит каждый столбец в `ls -l`), `less`, `head`, `tail` и `tail -f` (или даже лучше – `less +F`), `ln` и `ln -s` (узнайте разницу между символьными ссылками и жёсткими ссылками, и почему жёсткие ссылки лучше), `chown`, `chmod`, `du` (для быстрой сводки по использованию диска: `du -hk *`). Для менеджмента файловой системы, `df`, `mount`, `fdisk`, `mkfs`, `lsblk`.
- Обучитесь использованию системами управления пакетами `apt-get`, `yum`, `dnf` или `pacman` (в зависимости от дистрибутива). Знайте как искать и устанавливать пакеты и обязательно имейте установленым `pip` для установки командных утилит, написаных на Python (некоторые из тех, что вы найдёте ниже, легче всего установить через `pip`).
- Используйте **ctrl-w** в Баше для того, чтобы удалить последнее слово в команде; **ctrl-u** для того, чтобы удалить команду полностью. Используйте **alt-b** и **alt-f** для того, чтобы бегать между словами команды, **ctrl-k** для того, чтобы прыгнуть к концу строки, **ctrl-l** для того, чтобы очистить экран. Гляньте на `man readline` чтобы узнать о всех шорткатах Баша. Их много! Например, **alt-.** бежит по предыдущим аргументам команды, а **alt-*** расширяет глоб.??
- Для того, чтобы посмотреть историю, введите `history`. Также существует множество аббревиатур, например `!$` – последний аргумент, `!!` – последняя команда, хотя эти аббревиатуры часто заменяются шорткатами **ctrl-r** и **alt-.**.
- Если Вы написали команду наполовину и вдруг передумали, нажмите **alt-#** для того, чтобы добавить `#` к началу, и отправьте команду, как комментарий. Потом вы сможете вернуться к ней через историю.
- Не забывайте использовать `xargs` (или `parallel`). Это очень мощная штука. Обратите внимание, что Вы можете контролировать количество команд на каждую строку, а также параллельность. Если Вы не уверены, что делаете что-то правильно, начните с `xargs echo`. Еще `-I{}` – полезная штука. Примеры:
- Знайте разные сигналы, которые можно слать процессам. Например, чтобы приостановить процесс, используйте `kill -STOP [pid]`. Для полного списка посмотрите `man 7 signal`.
- В Баш скриптах используйте `set -x` для того, чтобы дебажить аутпут. Используйте строгие режимы везде, где возможно. Используйте `set -e` для того, чтобы прекращать выполнение при ошибках. Используйте `set -o pipefail` для того, чтобы строго относится к ошибкам (это немного глубокая тема). Для более сложных скриптов также используйте `trap`.
- В Баш-скриптах подоболочки (subshells) – удобный способ группировать команды. Один из самых распространенных примеров – временно передвинуться в другую рабочую директорию, вот так:
- В Баше много типов пространства переменных. Проверить, существует ли переменная – `${name:?error message}`. Например, если Баш-скрипту нужен всего один аргумент, просто напишите `input_file=${1:?usage: $0 input_file}`. Арифметическая область видимости: `i=$(( (i + 1) % 5 ))`. Последовательности: `{1..10}`. Обрезка строк: `${var%suffix}` и `${var#prefix}`. Например, если `var=foo.pdf` тогда `echo ${var%.pdf}.txt` выведет `foo.txt`.
- В Баше перенаправляйте стандартный вывод, а также стандартные ошибки, вот так: `some-command >logfile 2>&1`. Зачастую, для того, чтобы убедится, что команда не оставит открытым файл, привязав его к открытому терминалу, считается хорошей практикой добавлять `</dev/null`.
- Используйте `man ascii` для хорошей ASCII таблицы, с *hex-* и десятичными значениями. Для информации по основным кодировкам полезны: `man unicode`, `man utf-8` и `man latin1`.
- Используйте `screen` или [`tmux`](https://tmux.github.io/) для того, чтобы иметь несколько экранов в одном терминале. Это особенно полезно, когда вы работаете с удаленным сервером, тогда Вы можете подключаться/отключаться от сессий. Более минималистичный подход для этого – использование `dtach`.
- Еще может быть полезно оптимизировать вашу SSH конфигурацию, например этот файл `~/.ssh/config` содержит настройки, которые помогают избегать потерянных подключений в некоторых сетевых окружениях. Используйте сжатие (которое полезно с scp через медленные подключения) и увеличьте количество каналов к одному серверу через этот конфиг, вот так:
- Некоторые другие настройки SSH могут сильно повлиять на безопасность и должны меняться осторожно, например, для конкретной подсети или конкретной машины или в домашних сетях: `StrictHostKeyChecking=no`, `ForwardAgent=yes`
- Чтобы получить разрешения файла в восьмеричном виде, что полезно для конфигурации систем, но нельзя получить из `ls`, можно использовать что-то типа:
- Для интерактивного выделения результатов других команд используйте [`percol`](https://github.com/mooz/percol) или [`fzf`](https://github.com/junegunn/fzf).
`python -m SimpleHTTPServer 7777` (если у вас Python 2 и вы хотите открыть сервер на порту 7777) или `python -m http.server 7777` (для Python 3 и порта 7777).
- Чтобы выполнить определённую команду с привилегиями, используйте `sudo` (для рута) и `sudo -u` (для другого пользователя). Используйте `su` или `sudo bash`, чтобы запустить шелл от имени этого пользователя. Используйте `su -`, чтобы симулировать свежий логин от рута или другого пользователя.
- Для того, чтобы найти файл в текущей директории, сделайте `find . -iname '*something*'`. Для того, чтобы искать файл по всей системе, используйте `locate something` (но не забывайте, что `updatedb` мог еще не проиндексировать недавно созданные файлы).
- Для работы с Excel и CSV-файлами используйте [csvkit](https://github.com/onyxfish/csvkit) (программа предоставляет команды `in2csv`, `csvcut`, `csvjoin`, `csvgrep` и т.д.)
- Для работы с Amazon S3 удобно работать с [`s3cmd`](https://github.com/s3tools/s3cmd) и [`s4cmd`](https://github.com/bloomreach/s4cmd) (последний работает быстрее). Для остальных сервисов Амазона используйте стандартный [`aws`](https://github.com/aws/aws-cli).
- Не забывайте, что Ваша локаль влияет на многие команды, включая порядки сортировки, сравнение и производительность. Многие дистрибутивы Linux автоматически выставляют `LANG` или любую другую переменную в подходящую для Вашего региона. Из-за этого результаты функций сортировки могут работать непредсказуемо. Рутины `i18n` могут значительно снизить производительность сортировок. В некоторых случаях можно полностью этого избегать (за исключением редких случаев), сортируя традиционно побайтово, для этого `export LC_ALL=C`.
- Знайте основы `awk` и `sed` для простых манипуляций с данными. Например, чтобы получить сумму всех чисел, которые находятся в третьей колонке текстового файла, можно использовать `awk '{ x += $3 } END { print x }'`. Скорее всего, это получится раза в 3 быстрее и раза в 3 проще, чем делать это в Питоне.
Для того, чтобы переименовать сразу много файлов по шаблону, используйте `rename`. Для сложных переименований может помочь [`repren`](https://github.com/jlevy/repren):
- Знайте флаги `sort`а. Для чисел используйте `-n`, для работы с человекочитаемыми числами используйте `-h` (например `du -h`). Знайте как работают ключи (`-t` и `-k`). В частности, не забывайте, что вам нужно писать `-k1,1` для того, чтобы отсортировать только первое поле; `-k1` - это сортировка, учитывая всю строчку. Также стабильная сортировка может быть полезной (`sort -s`). Например для того, чтобы отсортировать самое важное по второму полю, а второстепенное по первому, можно использовать sort -k1,1 | sort -s -k2,2`.
- Если вам когда-нибудь придётся написать код символа табуляции в терминале, например, для сортировки по табуляциям с флагом -t, используйте сокращение **ctrl-v****[Tab]** или напишите `$'\t'`. Последнее лучше, потому что его можно скопировать.
- Стандартные инструменты для патчинга исходников это `diff` и `patch`. Также посмотрите на `diffstat` для просмотра статистики диффа. `diff -r` работает рекурсивно по всей директории. Используйте `diff -r tree1 tree2 | diffstat` для полной сводки изменений.
- Для конвертирования кодировок используйте `iconv`. Для более сложных задач – `uconv`, он поддерживает некоторые сложные фичи Юникода. Например, эта команда переводит строки из файла в нижний регистр и убирает ударения (кои бывают, например, в испанском языке)
- Дле веб-дебаггинга используйте `curl` и `curl -I`, или их альтернативу - `wget`. Также есть более современные альтернативы, например [`httpie`](https://github.com/jakubroztocil/httpie).
- Чтобы получить информацию о диске/CPU/сети используйте `iostat`, `netstat`, `top` (или лучшую альтернативу `htop`) и особенно `dstat`. Хороший старт для того, чтобы понимать, что происходит в системе.
- Для более детальной информации используйте [`glances`](https://github.com/nicolargo/glances). Эта программа показывает сразу несколько разных статистик в одном окне терминала. Полезно, когда следите за сразу несколькими системами.
- Для того, чтобы следить за памятью, научитесь понимать `free` и `vmstat`. В частности, не забывайте, что кешированые значения ("cached" value) – это память, которую держит ядро и эти значения являются частью `free`.
- Дебаггинг Java – совсем другая рыбка, но некоторые манипуляции над виртуальной машиной Оракла, или любой другой, позволят вам использовать делать `kill -3 <pid>` и трассировать сводки стека и хипа (включая детали работы сборщика мусора, которые бывают очень полезными), и их можно дампнуть в stderr или логи.
-`ab`, которая поставляется вместе с apache, полезна для быстрой и поверхностной проверки производительности веб-сервера. Для более серьезного лоад-тестинга используйте `siege`.
- Знайте про `strace` и `ltrace`. Эти команды могут быть полезны, если программа падает или висит, и вы не знаете почему Или если вы хотите протестировать производительность программы. Не забывайте про возможность дебаггинга (`-c`) и возможность прицепиться к процессу по pid (`-p`).
- Для анализа более сложных систем и производительности посмотрите на `stap` ([SystemTap](https://sourceware.org/systemtap/wiki)), [`perf`](http://en.wikipedia.org/wiki/Perf_(Linux)), и [`sysdig`](https://github.com/draios/sysdig).
- Узнайте, какая у вас операционка, через `uname` or `uname -a` (основная Unix-информация/информация о ядре) или `lsb_release -a` (информация о дистрибутиве).
- Это довольно круто, что можно найти множественные пересечения файлов, соединить отсортированные файлы и посмотреть разницу в нескольких файлов через `sort`/`uniq`. Это быстрый подход и работает на файлах любого размера (включая многогигабайтные файлы). (Сортировка не ограничена памятью, но возможно вам придется добавить `-T`, если `/tmp` находится на небольшом логическом диске). Еще посмотрите то, что было сказано выше о `LC_ALL`. Флаг сортировки `-u` не используется ниже, чтобы было понятнее:
- Используйте `grep . *` для того, чтобы посмотреть содержимое всех файлов в директории. Особенно полезно, когда у вас много конфигов типа `/sys`, `/proc`, `/etc`.
- Получить сумму всех чисел, которые находятся в третьей колонке текстового файла. (Скорее всего, это раза в 3 быстрее и раза в 3 проще, чем делать это в Питоне):
- Используйте `xargs` (или `parallel`). Это очень мощная штука. Обратите внимание, что Вы можете контролировать количество команд на каждую строку, а так же параллельность. Если Вы не уверены, что делаете что-то правильно, начните с `xargs echo`. Еще `-I{}` – полезная штука. Примеры:
- Давайте представим, что у нас есть какой-то текстовый файл, например лог какого-то сервера и на каких-то строках появляется значение, строки с которым нам интересны. Например, `acct_id`. Давайте подсчитаем, сколько таких запросов в нашем логе:
-`sponge`: прочитать весь инпут перед тем, как его записать. Полезно, когда читаешь из того же файла, куда записываешь. Например, вот так: `grep -v something some-file | sponge some-file`
- Системы управлением пакетами – `brew` (Homebrew) и `port` (MacPorts). Они могут быть использованы для того, чтобы установить большинство программ, упомянутых в этом документе.
- Не забывайте, что MacOS основан на BSD Uni и многие команды (например `ps`, `ls`, `tail`, `awk`, `sed`) имеют некоторые небольшие различия с линуксовыми. Это обусловлено влянием `UNIX System V` и `GNU Tools`. Разницу можно заметить, увидев заголовок "BSD General Commands Manual." в манах программ. В некоторых случаях, на Мак можно поставить GNU-версии программ, например `gawk` и `gsed`. Когда пишите кроссплатформенные Bash-скрипты, старайтесь избегать использовать команды, которые могут различаться (например, лучше используйте Python или `perl`), или тщательно все тестируйте.
Кому много дано, с того много и спрашивается. Тот факт, что что-то может быть написано на Баше, вовсе не означает, что оно должно быть на нём написано. ;)
Оригинальная работа и перевод на русский язык распространяется под лицензией [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/).