LINUX TOOLS THAT MAKE LIFE EASIER. ВТОРАЯ ЧАСТЬ

LINUX TOOLS THAT MAKE LIFE EASIER. ВТОРАЯ ЧАСТЬ

Расшифровка семинара Григория Серебрякова (Xperience AI), который состоялся в мае 2020 года. Видеоверсия доступна для просмотра на нашем youtube-канале. Первую часть можно прочитать здесь.

tmux

Давайте начнем с проблемы: допустим, вы зашли на удаленную машину или на сервер к товарищу и хотите запустить тренировку. Дальше что-то произошло – мы выдернули Ethernet провод, отправили ноутбук в спячку, просто нажали Ctrl+C и эта запущенная тренировка внезапно умерла. Особенно обидно, когда это случается за несколько секунд до того, как должен был сделаться очередной snapshot. Почему команда не может жить после того, как мы ее запустили, зачем ей нужно соединение с нашей машиной? Все дело в том, что когда мы запускаем интерактивный софт, он себе лоцирует псевдотерминал, который ему нужен для ввода-вывода. С точки зрения программы он выглядит как файл. Когда мы разрываем связь с удаленной машиной, этот файл пропадает. ОС видит, что у нее отвалилось устройство и посылает приложению, которое его использует, сигнал hangup. Если наша программа его не обрабатывает специальным образом, то это приводит к ее завершению.

Самый простой вариант, который обычно советуют для решения проблемы – это использовать команду nohup. Она перехватывает сигнал hangup и не пропускает его к той команде, которую вы запустили. Вы таким образом сможете что-то запустить, закрыть соединение и пойти по своим делам. Тем не менее, пользоваться этим не удобно, потому что тогда надо помнить про команду tale -f, с которой можно посмотреть, что там этот лог файл пишет. Плюс нужно помнить, что у вас там запущено. Неудобно.

Поэтому давным-давно были придуманы терминальные менеджеры окон, терминальные мультиплексоры. Достаточно долго это был screen, который позволял делать то, что сейчас вам позволяет делать практически любая программа, в которой вы открываете консоль: делать вкладки, что-то запускать в них и управляет сессией за вас. Когда вы отключаетесь от сессии и закрываете соединение с удаленной машиной, все, что было запущено внутри терминального мультиплексора, продолжает работать. Время шло, screen устаревал, потому что он был написан когда-то давно и не очень хорошо дружил с современными фичами. Терминалы становились умнее, там появлялось много цветов, Unicode. В какой-то момент кому-то пользоваться надоело screen, и люди разработали другой терминальный мультиплексор, tmux. Он позволяет многое: иметь несколько вкладок, иметь внутри одной вкладки несколько сплитов – вертикальных, горизонтальных, ровно как в вашем любимом текстовом редакторе; отключиться от удаленной сессии, запустить несколько сессий tmux, работающих на одной машине, внутри каждой из которой будет множество окон, каждая из которых разбита на сплиты. И одна из полезных особенностей – можно позвать товарища в свою запущенную сессию на удаленной машине и вместе с ним дебажить. Несколько человек могут видеть, как двигается курсор внутри одного окошечка, набирать команды, мешать или помогать друг другу.

Важно, что у tmux есть плагины и менеджер плагинов. Плагины, очевидно, может писать кто угодно, и вместе с tmux в его репозиторий поставляется некоторое количество годных. Например, мы взяли наш tmux, насоздавали в нем вкладок, распределили их по проектам. Вкладки можно называть именами, которые имеют для вас смысл. И после этого, например, вы перезагрузили компьютер. Стандартная история – вкладки, естественно, пропали, а хочется, чтобы было, как в браузере, когда вы его открыли и вкладки все опять восстановилось. Для этого есть плагин tmux-resurrect, который делает именно это. Он запоминает вашу конфигурацию вкладок и позволяет их восстановить при перезапуске компьютера или при перезапуске сессии tmux. Но это нужно делать руками. В какой-то момент людям стало лень, и появился плагин tmux-continuum, который просто работает в бэкграунде и время от времени автоматически сохраняет вашу конфигурацию. Потом вы восстанавливаетесь с самой последней версии. Кроме этого, есть всякие улучшения для того, чтобы было удобнее выделять текст, копировать его в системный буфер обмена, потому что работа со скроллом и буфером обмена в tmux несколько непривычна.

Как это все применяется. Вот мой tmux конфиг (изображение выше). Мы объявили, что у нас есть плагин менеджер, объявили плагины, которые будем использовать, чтобы он их сам стащил с GitHub. Дальше команда для resurrect сохранять bash history. Опция, с одной стороны, полезная, с другой – бесящая. Полезная, потому что сохраняется история шелла отдельно для каждой вкладки. Вы убили сессию, перезагрузили машину, восстановили сессию – и у вас история, как будто вы только что набирали эту команду. Это очень удобно. Но побочный эффект этого состоит в том, что шелл не дает возможности сохранить историю, не влезая в процесс взаимодействия с ним. В результате случается так, что вы набираете команду, в этот момент по таймеру срабатывает сохранение истории, ваша команда пропадает, вместо этого появляется сообщение о том, что resurrect сохранил вашу историю и вам приходится заново набирать команду, что не очень приятно.

ssh

Теперь давайте разбираться, как нам сходить на удаленную машину. Стандартный способ – это ssh, то есть secure shell. Это вещь, которая стала стандартом, поскольку большинство серверов сделаны на Unix: ssh там везде есть, все им пользуются. Это просочилось во всякие утилиты для разработчиков. Способ аутентификации через ssh-ключи можно встретить на GitHub, GitLab и везде, где есть git. PyPi умеет ходить по ssh за пакетами. В самом простом случае вам даже не нужен ssh-ключ, вам достаточно знать имя пользователя, пароль и имя хоста. Вы говорите ssh user @hostname, вводите пароль. Если это не запрещено настройками, вас пустят и у вас будет сессия. Но как всегда все самое интересное – под капотом.

Крайне полезной особенностью ssh являются всякие программы, которые написаны вокруг него. Есть, например, программа, которая называется sshfs. Это имплементация файловой системы в юзерспейсе. Это значит, что нам не нужны рутовые права для того, чтобы подмонтировать эту файловую систему. Обмен файлами идет через ssh. Вместе с ssh к вам прилетает полезная утилита под названием scp, которая позволяет через ssh копировать один файл. Если вам нужно скопировать много файлов, то это удобно сделать через RSYNC , который тоже умеет делать авторизацию через ssh. А один файл можно скопировать с помощью scp. Если нужно посмотреть все дерево файловой системы, как-то его открыть в файловом браузере, то sshfs отлично для этого подходит. Да, будет подтормаживать, зато удобно.

Следующее, чего нам хочется – это запустить какое-нибудь графическое приложение на удаленной машине и увидеть его окошечко локально, рядом с нами. Это все можно сделать при помощи того же ssh, у него для этого есть ключ -X. Вы сказали ssh -X на другую машину, запустили там какое-то приложение, оно у вас показалось. Иногда этого недостаточно. Что на самом деле происходит, когда вы делаете ssh -X: ssh вам выставляет переменное окружение DISPLAY, которое вам указывает на порт на локальной машине, который будет проброшен на порт на удаленной машине, а иксовые приложения на эту переменную DISPLAY ориентируются и знают, куда показывать. Таким образом, все будет показано с удаленной машины на вашу локальную. Проблема начинается, например, с tmux. У вас есть запущенная tmux сессия на удаленной машине. Тут вы решаете, что вы хотите там показать что-то графическое, говорите ssh -X на удаленную машину, прикрепляетесь к tmux сессии, запускаете и вам говорят, что переменная DISPLAY не выставлена или выставлена неправильно и с DISPLAY соединиться не удалось. Это происходит потому, что ssh выставил переменную DISPLAY, но он выставил ее в том шелле, в котором он стартовал. А внутри tmux шелл свой. Переменное окружение никуда не прокидывалось, вам нужно будет это сделать руками: пойти и посмотреть, как она выставилась – обычно это localhost:10.0. Если у вас  несколько shell -X, тогда может быть и 11, и 12. Берем ее, копируем, заходим в tmux, там говорим export, и у вас все работает.

Что еще может пойти не так. Может быть такое, что в вашем конфиге для ssh daemon почему-то запрещена пересылка иксов. Это строчка #X11Forwarding yes, она по умолчанию yes. Вот можно увидеть, откуда берется 10 – #X11DisplayOffset 10. Отсюда у нас будет первый порт 10, следующий 11 и так далее. Если вам вдруг какой-то злодей написал #X11Forwarding no, то ничего работать не будет. В мажорных дистрибутивах Linux обычно все нормально в этом смысле и все разрешено. Но если вдруг не работает, можно пойти посмотреть.

В какой-то момент вам надоест писать -X руками и думать о том, написали вы ее вообще или нет. Вам захочется это дело упростить – для этого есть такая штука, как конфиг ssh. В него можно внести всяческую полезную информацию о том, как же соединяться с выбранным хостом. А именно – можно завести имя для хоста. Например: у меня есть Host work-desktop, моя машина. Я работаю с ноутбука, машина стоит где-то. Я не хочу думать о том, какой у нее ip адрес, не хочу помнить – хочу к ней обращаться по имени work-desktop. Заводим Host work-desktop, говорим, что у него HostName – это наш ip. Если у вас работает DNS и вы в нем уверены, можно написать DNS имя. Обозначаем пользователя, который будет ходить на эту машину – и вот я здесь сразу сказал себе ForwardX11 yes, чтобы у меня ключ -X автоматически выставлялся. Теперь для ssh, sshfs, rsync, vscode и прочих друзей, которые умеют авторизовываться через ssh, мне больше не нужно параметры вводить руками. Я им говорю, что нужно ходить на машину work-desktop, и они все остальное прочитают из конфига.

Следующая типичная ситуация, которая возникает с ssh – это проблема с сетью. Для того, чтобы у вас нормально работала интерактивность в терминале, чтобы вы могли там курсором шевелить, ходить по словам и хотя бы нормально печатать, нужна какая-то минимальная отзывчивость сети, короткие пинги. Если ваша сеть плохая, то вы будете наблюдать лаги. Если у вас сеть периодически отваливается, ssh может подвиснуть. Самый простой пример – у вас есть ноутбук, вы отправили его в спячку с открытой ssh сессией, открыли, а она у вас зависла. ssh можно научить бороться с зависшими сессиями, чтобы вам не приходилось закрывать их руками, закрывать вкладки в терминале и так далее. Можно в конфиге сказать, чтобы ssh периодически посылал пакеты, проверял, живо соединение или нет, и если оно не живо, то обрывал сессию. Можно сказать, что это для специфического хоста, а можно для всех хостов подряд, как в данном случае. Хост любой, проверяем раз в 300 секунд, что он жив. Если два раза недоступен, то рвем сессию.

Это неплохо, но все равно неудобно. Если сессия порвалась, ее все равно надо переустанавливать – не круто. Ребята из MIT тоже посчитали, что это не круто, и написали MOSH. Расшифровывается как mobile shell. Это замена ssh для плохих ситуаций. Что делает эта штука. Она сначала пользуется ssh для того, чтобы авторизоваться на удаленной машине. Далее она стартует daemon и забывает про ssh. У нее есть клиент, у нее есть сервер, они на вашем ноутбуке и удаленной машине обмениваются данными по UDP. Это приводит к тому, что вы можете спокойно переключаться между разными видами связи – Wi-Fi, Ethernet, телефон, модем. Ваша сессия будет жить. Вы можете отправить ноутбук в спячку, открыть его и продолжить работать – сессия будет жить. Мне эта штука очень нравится, клиенты есть под различные ОС и даже под телефоны. И она просто работает. Очень удобно.

NGROK

Как вместе дебажить, если вы сидите дома и у вас нет публичного ip-адреса? Куда будет подключаться товарищ с ssh? Для этого есть штука под названием NGROK. Она позволяет делать туннели – разные между разными вещами. Она в принципе платная, но можно сделать ограниченное количество туннелей бесплатно. Чтоб позвать товарища, нам нужен всего один. Как это работает: у вас есть локальный компьютер, где-то есть сервер ngrok. ngrok устанавливает соединение между вашим локальным компьютером и своим сервером и просто передает пакеты на порт, который вы ему скажете. Запускаем, ngrok tcp --region=eu 22, регион Европа, чтобы пинги поменьше были, и нужен 22 локальный порт, который по умолчанию ожидает ssh. Он вам говорит forwarding и дает адрес. Вы даете его товарищу, товарищ подсоединяется на указанный адрес на указанный порт, попадает на вашу машину. Денег никому платить не надо, но и супер секретные данные таким образом тоже передавать не надо, потому что они проходят через недоверенный сервер. Скорее всего, никто ничего не сворует, но разумную паранойю никто не отменял.

То же самое можно сделать средствами самого ssh, называется ssh reverse proxy. Вы устанавливаете соединение с удаленным хостом и по сути оно нужно только для того, чтобы сделать такой туннель, по которому будут передаваться данные. Проблема в том, что вам в этой схеме с ssh нужна третья машина. Это немножко усложняет вопрос.

Ключи ssh

Давайте разбираться, как делать аутентификацию средствами ssh. Замечательно, если мы знаем имя пользователя и пароль. Не очень удобно каждый раз вводить пароль – имя пользователя можно написать в конфиг. Иногда доступ с паролем запрещен. В этом случае и вообще хорошим решением является использование ssh ключей. Стандартная криптографическая схема работает с двумя ключами – приватным и публичным. Вы подписываете сообщение приватным ключом. При помощи публичного ключа можно проверить, что сообщение действительно подписано вами. Вы распространяете свой публичный ключ во все места, где нужно проверять, что это действительно вы пришли. Ровно та же схема с ssh ключами работает для подписывания коммитов в Git, для доступа к GitLab и так далее. Первое, что нам нужно сделать для этого – это сгенерировать пару из публичного и приватного ключа. Я думаю, что все эту процедуру проходили, потому что все регистрировались в GitHub, GitLab и работали с Git.

Бывают разные алгоритмы шифрования, бывает разная длина ключа. Одной из популярных рекомендаций является rsa с длиной 4096 бит, потому что 2048 уже взламывается. Можно иметь много пар ssh ключей, различать их по именам: для этого у ssh key gen  есть ключ -f, который говорит, куда же его записать. Если вы ничего не скажете, он спросит, переписать ли вам дефолтный ключ. Но можно в интерактивной сессии выбрать, куда записать, а можно сказать через -f. Приватный ключ должен быть только у вас на машине, потому что каждый, у кого есть ваш приватный ключ, если вы его не зашифровали паролем (можно пароль ввести для ключа) сможет им воспользоваться и выдать себя за вас. Далее вам нужно каким-то образом передать свой публичный ключ на ту машину, где вы планируете авторизовываться. В случае, если это GitLab или GitHub, вы его в интерфейсе просто копируете, но представим, что нужно сходить на сервер. Есть замечательная команда ssh-copy-id, которой мы даем свой публичный ключ при помощи ключа -i и этот ключ использует ssh когда ему нужно выбрать между несколькими ключами. Представляем, что мы знаем имя пользователя и пароль на какой-то удаленной машине. Мы говорим ssh-copy-id <identity_file> <user>@<hostname> и после этого мы можем забыть про пароль и ходить туда по identity файлу.

ssh agent

У нас теперь есть identity файл - наш файл с ключом. Теперь не нужно каждый раз набирать пароль. Мы немножко запараноили и защитили наш ключ паролем. И теперь нам нужно вводить проходить защиту от ключа. Ничего, казалось бы, не поменялось. Вместе с ssh идет замечательная программа ssh-agent, которая решает за вас эту ситуацию. Ssh-agent позволяет импортировать в себя ключ на время, пока он работает. Вы вводите секретный код один раз, а дальше agent выступает авторизационным агентом для ssh.

Есть у вас Ubunta, – предположим, что большинство присутствующих с ней работает, – у вас скорее всего ssh-agent стартовал вместе с текущей графической сессией. Можно пойти посмотреть на список процессов, с помощью grep найти его по слову ssh-agent, у вас что-нибудь будет запущено. Я его не сам стартовал, у меня его Xfce стартанул. Если так случилось, что у вас нет запущенного агента, можно посмотреть, как его запускать, вот ниже пример для баша. Нужно сказать eval «$(ssh-agent –s)». $ и () нам говорят, что нужно при помощи баша выполнить какую-то команду. Команда выполняется, результат ее вставляется внутрь кавычек и eval говорит, что нужно содержимое строчки выполнить, как будто это код. Ssh-agent –s запускает агента и пишет две строчки: export SSH_AGENT_PID и export SSH_AUTH_SOCK. Первое – это id процесса ssh-agent, он вам нужен для мониторинга. А вот второе – это сокет, через который идет обмен данными для авторизации. Вы можете eval не писать, можете просто запустить ssh-agent –s и выполнить вот эти две команды с экспортом. После того, как у вас есть запущенный ssh-agent, вы говорите ssh-add <private_key>, вводите один раз пароль и до тех пор, пока эта сессия ssh-agent не умрет, у вас все будет работать. Зачем я рассказывал про сокеты, eval и так далее. Представим, что у вас есть несколько шеллов, несколько терминалов. Неважно, вы вкладками в терминале пользуетесь, вы tmux пользуетесь. Так получилось, что у вас не стартовал ваш агент вместе с вашей иксовой сессией. Вы его стартовали в какой-то из вкладок вручную и как мы уже обсуждали, эти переменные окружения, которые были экспортированы, не распространились в остальные вкладки. Нужно их передать. Но как я уже сказал, можно без eval просто запустить ssh-agent, посмотреть на эти переменные, скопировать эти две строчки, ну или только вторую, и повставлять их во всех терминалах, которые у вас запущены. После этого у вас все должно заработать. Частный случай этой ситуации – когда у вас по каким-то причинам не выставился вот этот SSH_AUTH_SOCK, но при этом агент уже запущен, например, вы его запустили с eval и забыли. Забыли посмотреть назначение. Можно заметить, что сокет, на самом деле, создается в папочке tnp и имя у него будет ssh что-нибудь, там лежит файлик. Можно просто найти его руками. У него в конце /agent.четырецифры. Цифры близки к id этого процесса. Если у вас несколько файлов, то можно найти того, который относится к живому агенту и просто пробросить, экспортировать переменное окружение. При помощи lsof можно посмотреть, кому он принадлежит, чтобы не заниматься сравнением циферок. Чем еще хорош агент, так это тем, что если вы его аккуратно настроите, можно переслать ключи на удаленную машину. Представьте цепочку – у вас есть одна машина, на которую вы можете ходить, в дата-центре. И с нее вы можете ходить на какие-то другие машины в дата-центре. Вам для авторизации нужен ssh ключ, который у вас лежит на локальном ноутбуке. Вы можете настроить в вашем конфиге параметр ForwardAgent yes и после этого магическим образом ключи, которые у вас же импортированы в агент, будут доступны вам в удаленной сессии. Также есть ссылка на GitHub, если что-то пошло не так. Самый распространенный случай – вам нужно склонировать Git репозиторий на удаленной машине. Вот тут он вам и пригодится.

Можно использовать разные ключи для разных машин. Для этого нужно явно в конфиге указать, какой ключ от какого хоста. После этого ssh будет самостоятельно разбираться, чем же пользоваться. Более того, можно на один и тот же хост завести разные alias и в зависимости от alias будет использоваться разный ssh ключ. Иногда это полезно. Например, я хочу разделять личный и рабочий аккаунты на GitLab. Я их разделяю ключами и могу, заходя на рабочий или личный GitLab, разделять, с какими id я буду коммитить код.

Пароли, пароли, пароли

Итак, мы разобрались, как авторизоваться при помощи ssh ключей везде, где только можно. Штука вроде полезная, но встречаются ситуации, когда никаких ключей нам никто не даст и нас просят ввести пароль. Как нас учит современная история, иметь один пароль везде – это плохо. Рано или поздно он утечет, все ваши доступы будут уязвимы, и вас неминуемо взломают. Поэтому хочется иметь разные варианты. Но их тяжело помнить, особенно если они хорошие, длинные, надежные. Как выглядит типичный сложный пароль: он состоит из комбинации прописных и строчных букв, циферок, спецсимволов ну и можно воспользоваться какой-то мнемоникой для его запоминания. Дальше идет подсчет, сколько здесь бит энтропии, сколько нам нужно времени для того, чтобы подобрать такой пароль, пользуясь современными вычислительными мощностями. Кажущийся нам сложным пароль подбирается за три дня. В то же время есть подход, который говорит о том, что мы можем составить пароль из нескольких просто английских слов без всяких спецсимволов. Нужно сделать эти слова с одной стороны случайными, но с другой стороны дающими в сумме достаточно длинную фразу. В-третьих, если фраза будет достаточно абсурдной, мы ее достаточно легко запомним. У нас теперь пароль длиннее, а с точки зрения энтропии нет никакой разницы между цифрами и буквами. 44 бита энтропии – на расшифровку понадобится 550 лет с такой же скоростью перебора. Мы хотим пользоваться этим подходом, но хотим его немного автоматизировать, потому что если мы будем придумывать случайные слова, то они будут уже не очень случайными.

Есть утилита, которую я по этому поводу очень люблю, называется xkcdpass. Она имплементирует подход, описанный в комиксе, и пользуется тем, что у нас в Linux есть словари английского языка. Она берет четыре слова или сколько вы ей скажете при помощи ключа -n слов, хоть 10; при помощи ключа -d можно сказать, какой разделитель использовать. У меня -. И при помощи команды tr я привожу весь аутпут к нижнему регистру. Все, вы получили команду, которая нам позволяет генерировать четырехсловные пароли в произвольных количествах. Есть одна проблема. Как обычно, вот это все длинное нужно каждый раз писать руками. Мы ленивые программисты, поэтому давайте сделаем bash alias для этого.

Я вам привожу выдержку из своего файла bash alias, куда нам предлагают складывать все такие команды. Называется он generate_password. Рядышком команда, как его записать туда. После того, как я сделал новый шелл или подгрузил содержимое bashrc в текущий, я пишу команду generate_password, у меня пароль генерируется. Это хорошо, это замечательно, но я все еще не хочу их запоминать. Потому что они длинные и их много. Человечество по этому поводу придумало менеджеры паролей. Из хороших обычно советуют 1password, который стоит денег. Проблема с ним в том, что на Linux им пользоваться неудобно, потому что у него нет десктопной версии под Linux. В очередной раз пришел на помощь open source. Есть стандартный менеджер паролей на Linux под названием pass. Ссылочку на сайт привожу и на гайд, как его установить. Что он делает. Помнит за вас все пароли, держит их в виде Git репозитория. У вас есть возможность синхронизироваться между разными машинами при помощи клонирования этого репозитория, можно что-то из истории доставать, автоматически делается коммит на каждый новый добавленный пароль. Есть интеграция с разным софтом, есть клиенты под Android, Windows.

В качестве примера полезной интеграции давайте вспомним про docker и авторизацию, которую нужно сделать, чтобы засунуть какой-нибудь docker image в GitLab registry. Хочется иметь какую-то такую же штуку, как ssh-agent, который бы нам помогал не вводить пароль каждый раз. В случае с GitLab это крайне важно, потому что GitLab в свое registry вас не пускает просто с пользовательским паролем. Он заставляет вас генерировать токен для доступа к API и ходить при помощи него. Этот токен нужно где-то хранить. У docker есть официальная имплементация, которая интегрируется с pass и делает его менеджером паролей для docker. pass начинает работать так же, как ssh-agent. Вы вводите один раз мастер-пароль для менеджера паролей, он открывает доступ к хранилищу и после этого у вас случается авторизация для docker. Очень удобно, пользуюсь постоянно.

Бонусные тулы

Подходим к концу. Можно посмотреть справку про очень многие команды при помощи команды man. Про нее многие знают, но кто не знает, в общем, man от слова manual. Она очень подробная и там можно закопаться. Люди, которые не любят закапываться, сделали пакет под названием tldr. Вот на примере команды rsync можно посмотреть, что в man про rsync больше двух тысяч строк, а в tldr укладывается в 39. Там, конечно, очень коротко, но основные сценарии использования покрыты.

Про powerline. Это такая штука, которая позволяет сделать функциональную строку приглашения. Он интегрируется с вашим консольным текстовым редактором, он интегрируется с вашим терминалом, он интегрируется с вашим tmux. Вот для примера у меня здесь что показывается. Показывается код возврата последней команды – это 127. Показывается, в каком каталоге я сейчас нахожусь. Показывается ветка Git, которая сейчас активна. Все эти вещи можно сделать со стандартным приглашением командной строки, но нужно будет посидеть какое-то время. Про history. Из полезного – по history можно искать при помощи стандартного сочетания клавиш Ctrl+R, можно набирать команды и вы их найдете в истории. Можно сделать так, чтобы ваша текущая команда в консоли в историю не попала – если команда начинается с пробела, то в историю она не попадает. Ну и когда речь заходит про шэллы, обычно в современных условиях рекомендуют посмотреть на zsh, стандартный шэлл для OSX. Много всяких современных полезных плюшек. Есть очень большой коммьюнити проект по притаскиванию всяких плюшек в zsh, называется ohmyz.sh. Он действительно интересный и люди стараются всячески упростить жизнь, перемещение по каталогам, отображение и так далее.

Скажу всего два слова про текстовые редакторы. Изучите какой-нибудь консольный редактор. Это правда вам пригодится. Вы сможете редактировать конфиги из консоли, редактировать что-то на удаленных серверах. nano умеет на самом деле сильно больше, чем показывает по умолчанию. Там есть и подсветка синтаксиса, и номера строчек, и всякое разное. Оно просто в конфиге выключено по умолчанию. Но я вам порекомендую потратить время на vim или emacs. Здесь есть ссылочки полезные про то и другое. Изучите хотя бы базовые вещи – оно окупается.