Тема "Windows vs Linux" является частой причиной холиваров. Спорить бессмысленно, так как для каждой задачи требуется свой инструмент. Позвольте заинтересовать вас чудесным миром Linux и теми бонусами, которые вы можете получить от использования терминала в повседневной деятельности. Всё разберём на примерах реального использования.
Легко поставить софт
При получении в мессенджере оригиналов фотографий из iPhone мы получаем непонятный .HEIC-файл, а хочется привычных JPG/PNG. Для Linux с помощью менеджера пакетов можно поставить программу-конвертер и применить её
sudo apt update && sudo apt install libheif-examples
heif-convert 1.HEIC 1.jpg
Причём в терминале можно активно пользоваться кнопкой tab, чтобы не набирать команду целиком. Это выглядит примерно так: пишем "heif-c", нажимаем tab и получаем полную команду. Работает с командами, именами файлов и даже с настроенными подкомандами: sudo apt i<tab> дополнят команду до install.
Легко автоматизировать процессы
Мы справились с одной фотографией. А как поступить с десятком фотографий? Как быть, когда фотографий сотни? Когда у вас готово решение для конкретного случая, то в терминале его легко можно автоматизировать. Сила автоматизации в том, что можно легко масштабировать решение, например, для всех файлов с заданным расширением
for file in *.HEIC; do heif-convert "$file" "${file%.*}.jpg"; done
Да, тут немало нюансов. Ладно, синтаксис do-done и нюансы расстановки точек с запятой можно принять как данность. Применение перебора по маске уже достаточно непростая тема. Обязательные двойные кавычки вокруг переменных вызывают вопросы. Самое неприятное, что всё будет работать и без кавычек, если в названиях нет пробелов. А с пробелами нужны кавычки, но в примере из интернета об этом не скажут. Нюансы удаления расширения у файлов с использованием %.* вообще могут свести с ума, документация на этот счёт огромная и довольно сложная.
Прелесть этого подхода в том, что вам не нужен отдельный софт или отдельная кнопка для запуска на большом наборе входных данных. У вас есть программа для изменения формата, размера или чего угодно? Вы сможете применить эту программу для всех нужных файлов в терминале. Масштабирование от одного файла до сотни происходит абсолютно одинаково для любой программы.
Неудобством является высокий порог входа относительно программы с кнопкой "сделать хорошо", но и подход оказывается более универсальным – изученный однажды способ автоматизации навсегда остаётся с вами.
Легко вспомнить
Нужное решение можно не только нагуглить, но и найти в ранее выполненных командах, если вы такую задачу уже решали. В терминале доступны стрелочки вверх и вниз, позволяющие выполнить предыдущие команды. Это существенно ускоряет работу в терминале, позволяя переиспользовать команды. Актуальность этого увеличивается с ростом длины команды.
И совсем крутой является возможность искать по истории команд. Нажатием сочетания ctrl+R мы переводим терминал в режим обратного поиска по заданной подстроке. Я ввожу ctrl-R, набираю HEIC и получаю нужную команду из истории.
(reverse-i-search)`HEIC':
for file in *.HEIC; do heif-convert "$file" "${file%.*}.jpg"; done
Если нужной команды нет, я могу дописать подстроку или нажать ctrl+R повторно для демонстрации предыдущего подходящего значения.
Легко настроить под себя
По умолчанию сохраняется только тысяча последних команд, и эта тысяча достаточно быстро заканчивается. Посмотрел у себя – дефолтную тысячу команд я использовал за 3 недели. Чтобы сделать историю команд почти бесконечной, надо залезть в конфиг. В файле ~/.bashrc для переменных HISTSIZE и HISTFILESIZE поставьте значение в миллион или вроде того.
# в вашем ~/.bashrc
HISTSIZE=1000000
HISTFILESIZE=1000000
Почти у каждой программы есть текстовый конфигурационный файл, с помощью которого можно поменять её поведение. И у текстовой конфигурации много плюсов – её можно посмотреть глазами, её можно сохранить в git и отслеживать изменения, её можно легко нагуглить в интернете. Графический интерфейс программы может меняться, объяснения "нажми сюда, потом туда" неудобны и быстро устаревают.
При этом можно пойти дальше, добавив алиасы для ещё большей скорости работы в терминале. В дополнение к стрелочкам, ctrl+R и tab у нас есть автозамены, они же alias. Писать git status слишком долго, проще написать gs. Вот фрагмент моих алиасов для работы с git
alias gs='git status'
alias gd='git diff'
alias gitc='git commit -m'
alias gl="git log --graph --pretty=format:'%C(yellow)%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --date=short "
У git log флаги обеспечивают такое визуальное представление:
![Пример вывода настроенного git log git log example](https://habrastorage.org/getpro/habr/upload_files/bff/756/9d4/bff7569d4d95bf41c28af2206c9ea41c.png)
Из секции "прочее" я использую такие интересности
alias ll='ls -alF'
alias la='ls -A'
alias ..="cd .."
alias ...="cd ../.."
alias ....="cd ../../.."
alias h="history | tail -30"
# хрен запомнишь
alias TAR='tar -zcvf' # dest source
alias UNTAR='tar -zxvf' # source
С одной стороны, такая индивидуальная настройка сильно привязывает вас к рабочему месту, за ноутом коллеги вы начинаете сильно спотыкаться. С другой стороны конфиг с alias можно хранить всегда под рукой на гитлабе. А какие alias любите вы?
Статистика среди разработчиков
Посмотрим, что происходит в индустрии. Stackoverflow проводит ежегодные опросы разработчиков для отслеживания текущих трендов в программировании. В 2022 году в опросе участвовало 70 тысяч разработчиков. Посмотрим отдельные вопросы и ответы на них.
В какой операционной системе вы в основном работаете? (What is the primary operating system in which you work?)
![Основная ОС разработчика по опросу Stackoverflow developer survey Основная ОС](https://habrastorage.org/getpro/habr/upload_files/8a3/913/de0/8a3913de0e5888619af6944942a8cf4c.png)
Как видно из результатов, Linux среди разработчиков занимает очень весомые позиции.
Как вы пользуетесь Git? В вопросе системы контроля версий в общем виде, но 97% используют git. (How do you interact with your version control system? Select all that apply.)
![Как разработчики используют git VCS by type](https://habrastorage.org/getpro/habr/upload_files/66d/590/10e/66d59010ef4ce2f6c304ee7c7dbd7202.png)
Интересно, что 84% разработчиков используют интерфейс командной строки. Не удивительно, так как при поиске ответа на сложный вопрос вы попадёте на Stackoverflow, где вам предложат именно консольную команду. Консоль является универсальным языком взаимодействия разработчиков.
Терминал важен для разработчиков
Попробуем запустить веб-сервер на питоне. Штатный результат выглядит так:
python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
Однако вы можете получить вот такой неприятный вывод
python3 -m http.server
Traceback (most recent call last)
...
OSError: [Errno 98] Address already in use
Эта ошибка означает, что порт по умолчанию 8000 занят другим приложением. Для починки ситуации можно найти и завершить процесс, который занимает этот порт. Но что это за приложение и где его найти?
В терминале с помощью netstat выведем процессы и занимаемые ими порты, а в выводе с помощью grep найдём строку 8000, отвечающую за нужным нам порт
sudo netstat -nltp | grep 8000
tcp 0 0 0.0.0.0:8000 0.0.0.0:* LISTEN 16240/python3.10
Вертикальная черта обозначает конвейер, связывающий вывод левой команды с вводом правой. Теперь можно завершить процесс с идентификатором 16240 с помощью kill
kill 16240
В примере выше, кстати, очень хорошо видна философия Unix – программа должна делать что-то одно, и делать это хорошо. Задача операционной системы – предоставить гибкий клей для объединения различных программ. Мощь кроется в интеграции между программами и умении декомпозировать задачу на кусочки. Сложная задача рассматривается как комплекс более простых, а терминал становится единым языком общения для разработчиков.
Причём можно докрутить конвейер до получения результата в одну строку. Выведем все процессы, найдём порт 8000, выделим 7 столбец, где указан номер процесса, и в нём возьмём первую часть от слеша. Результат подадим в kill в виде аргумента, для этого воспользуемся xargs
netstat -nltp | grep 8000 | awk '{print $7}' | awk -F/ '{print $1}' | xargs kill
Такие однострочники неустойчивы к ошибкам в процессе, если требуется надёжное решение – надо аккуратно писать скрипт. Записал на этот счёт 20-минутное видео Идеальный скрипт на bash, где последовательно показываю процесс создания красивого скрипта с документацией и учётом bash-идиом. В процессе показываю консольный git и интересные фишки терминала. Когда вы овладеете CLI, терминал станет для вас удобной и привычной средой обитания. Для возникшей задачи ваши пальчики сами будут выдавать однострочник, решающий проблему. И выходить из терминала вам больше не захочется.
Вместо netstat можно использовать ss, lsof или fuser, путей решения проблемы всегда более одного. С опытом пополняется пул известных разработчику команд, что позволяет сразу решать проблему или быстро воспринимать нагугленное решение.
Изучается один раз
Из предыдущего пункта вытекает следующий. Графический интерфейс (GUI) учится под каждую программу. Интерфейс командной строки (CLI) учится один раз, дальше только необходимо пополнять пул известных команд за счёт поиска. Причём отдельный инструмент может внести огромный вклад – например, понимание регулярных выражений сразу делает доступным sed, awk и другие инструменты, которые завязаны на регулярках.
Docker для DevOps
Уже достаточно давно технология контейнерной виртуализации Docker стала популярным способом деплоя приложений, который применяется разработчиками. Даже небольшое современное приложение требует фронтенд, бекенд, базу данных, nginx для балансировки и другой магии, автообновление сертификатов. Это 3+ сервиса, объединённые в одно целое с помощью docker compose. GUI для docker существует, но большая часть гайдов и примеров приводятся для терминала. Чем эффективнее вы умеете работать в терминале, тем эффективнее вы сможете работать с докером – решать возникающие проблемы, модифицировать готовое решение под ваши реалии и так далее.
Можно для команды на сервере поднять кучу инструментов – gitlab для разработки, mattermost для коммуникации, систему мониторинга, локальное хранилище и прочее. Для DevOps всё ещё сильнее завязано на bash. CI/CD-пайплайны, "инфраструктура как код" и прочее требуют Linux вообще и bash в частности.
Терминал часто нужен для настройки серверов и развёртывания инфраструктуры в облаке. И тут SSH вообще вне конкуренции для удалённого управления серверами. С помощью SSH вы можете работать с удалённым сервером так же, как с локальным, писать скрипты для автоматизации и многое другое.
Ускоряем работу на примере
Завершить хотелось бы решением прикладной задачу: попробуем найти уникальные строки в большом файле. Начинающие разработчики для решения подобной задачи склонны либо садиться писать небольшую программу, либо искать готовую программу на просторах интернета. Но в Linux всё уже под рукой, надо найти и настроить под свой случай.
В качестве поля для экспериментов возьмём утечку rockyou, в которой 139 мегабайт (14 млн) утекших в 2009 году паролей. Замерять время будем с помощью time, смотрим на время real. Решение в лоб состоит в сортировке с флагом --unique или -u и последующем подсчёте строк с помощью команды wc
time cat rockyou.txt | sort --unique | wc -l # 47s у меня
Решение уже есть, но с ростом размера файла неприятно растёт и время обработки. Если мы хотим разобрать больше строк, либо если внутренний критик хочет посмотреть на потенциал ускорения при решении такой задачи, то приглашаем вас в пучины технологической магии по его ускорению.
Неожиданно, но замена одной команды sort -u на две отдельные команды sort и uniq даёт выигрыш в скорости. Подозреваю, что дело в возможности распараллелить их работу.
time cat rockyou.txt | sort | uniq | wc -l # 43s
Дальше умудрённый опытом пользователь терминала обратит внимание, что команда cat в начале не нужна. Команда sort сама умеет работать с файлом. Убираем лишний cat и получаем ещё бонус в скорости.
time sort rockyou.txt | uniq | wc -l # 33s
А следующее изменение максимально нетрививальное. Команда sort сортирует в текущей кодировке пользователя, сейчас обычно это utf-8. А можно заставить sort работать в однобайтовой кодировке, что может сэкономить время, и, как выясняется, очень существенное.
time LC_ALL=C sort rockyou.txt | uniq | wc -l # 5s
В результате наших действий мы в десять раз сократили время получения уникальных строк в файле. Напоминает про часто поднимаемую тему 10x-разработчиков про десятикратную разницу между крутыми и посредственными разработчиками.
Заключение
На разных примерах мы продемонстрировали, как быстро решать самые разнообразные задачи, имея в своем арсенале навык работы с командной строкой. Некоторые заголовки и тезисы провокационны и с ними можно поспорить. Но можем сказать абсолютно точно – освоенный навык работы с терминалом становится базовым инструментом для решения многих повседневных задач. Терминал позволит материализовать ваши мысли: открыл терминал, похимичил и задача решена.
В канале DevFM мы делимся опытом разработки на python, проектирования систем, работой с базами данных и полезными тулзами. Присоединяйтесь!