Pull to refresh

Comments 118

Перешел на zsh по одной причине: bash постоянно теряет историю. Вроде бы эта проблема давно уже «исправлена», но нет, все равно в какой-то момент история полностью сбрасывается. Почти никакими плюшками zsh не пользуюсь, ценю только за то, что помнит историю годами. Активный пользователь Meta-R. :)

А как там обстоит дело с историей из нескольких ssh терминальных сессий? В баше сохраняется только из одной, если верно помню.
shopt -s histappend
PROMPT_COMMAND='history -a'
В ~/.bashrc говорят, что вы помните неправильно.
В комментариях к каждой статья про zsh повторяется чушь про башхистори, типа вашей.
Там у каждого терминала есть так сказать свой буфер который флашится на диск или при закрытии терминала и при выполнении соттв. команды.
прям вообще не сбрасывается?
Давно перешёл на zsh, но использую всё так же, как раньше bash. Т.е. никакими фирменными фичами так и не пользуюсь. Установил только Oh My Zsh и выбрал шаблон по вкусу :)
Ещё заметил, что bash всегда стартует почти мгновенно, а zsh с небольшой задержкой.
Думаю это десятки плагинов Oh My Zsh у вас стартуют

Заметил, что задержка появилась после того, как поставил NVM. До этого сессия стартовала мгновенно.

У меня NVM тоже стоит, но заметил задержку ещё до установки NVM.
При всем уважении к разработчикам, я отношусь к zsh как к куче батареек для bash, которыми до конца никто пользоваться не умеет. Батарейки известно к чему ведут — лишние тормоза, баги с совместимостью, неполноценная документация и, как следствие, отсутствие понимания происходящего. Кстати, я что-то не встречал ни одного системного администратора, использующего zsh вместо bash на постоянной основе в своей работе, а эти ребята хорошо разбираются в применении консольных инструментов и конкретно интерпретаторов именно по назначению.

Ну и как водится, что только не придумают, чтобы bash/sh не изучать.

P.S. в опрос неплохо бы добавить, использовал zsh, но перешел обратно на другой интерпретатор
P.S. в опрос неплохо бы добавить, использовал zsh, но перешел обратно на другой интерпретатор

Да, мне тоже эта мысль недавно пришла в голову. Добавил.

UFO just landed and posted this here
Сколько промышленных серверов и какого типа (vm, dedicated, embedded) было у этих администраторов в эксплуатации?
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
Вот и я говорю, что такого нет. Под пром серверами имею в виду production
Собственно в вашем вопросе — половина ответа. Zsh хорош, когда вы можете подстроить его под себя, а когда от половины до трех четвертей времени ты проводишь на серверах, где zsh просто нет и/или подстроить его под себя нельзя (например там один пользователь, из-под-которого работают 10 человек), то тебе приходится держать в голове и помнить — где у тебя что.

Оказывается, что жить всегда без удобств zsh проще, чем вот так — нараскоряку…

Не понятно что имеется ввиду под применял? На боевых серверах? Врятли, хотя я такое видел на инфраструктуре одного крупного клиента. Там было машин 500. Админ редко один, поэтому нужно находить компромис с коллегами. А компромис этот либо bash, либо ksh (если надо держать совместимость со старым Unix, типа Чпукса)


А вот локально каждый развелкается как умеет. У меня это адовая смесь из bash и скриптов на perl, а у одного бывшего коллеги как раз zsh на все случаи жизни. И некоторые патерны из zsh мне нравятся. На столько нравятся, что я думаю все таки попробую в ближайшее время.


Например меня интересует подгрузка кода по контексту: в баш приходится либо вилосепедить, либо применять что-то на подобии https://github.com/cxreg/smartcd.git Также интересно выглядит отложенная подгрузка кода. Не уверен, что это даст большой буст, но на взгляд source ~/.bashrc_my у меня уже давно подтормаживает при том, что по большей части этот код имеет узкую специализацию и нужен редко или в определенном котексте (smartcd, кстати сильно спасает).

Админ редко один, поэтому нужно находить компромис с коллегами.

Просто не надо использовать общие аккаунты и sudo -i. Если каждый админ использует личный аккаунт и sudo для индивидуальных команд — ему ничего не мешает иметь личный ~/.zshrc. Помимо прочего это намного более здраво в плане безопасности, аудита и контроля доступа отдельных сотрудников.

sudo -s может потребовать внимания с точки зрения правильного выставления ENV. Т.е. здесь вопрос сответствия затрат на унифицирование разнобразных .profile. Не все отделы на это пойдут.


Плюс, есть один, очень важный момент в работе больших админских отделов. Так называемые "notes". Суть состоит в том, что админ дублирует команды в некоторый текстовый (или md), общедоступный файл, разумеется с пояснениями и комментариями. Файл этот каким-либо образом привязан к тикет системе. В следущий раз, если возникает необходимость сделать то же самое, его колега уже будет не в полной темноте. А в третий раз, уже начнется оптимизация: участки будут переписаны как скрипты для bash/zsh/ansible и т.п. В таком виде один шел на всех очень важен. Это средство обмена опытом, нахождение общих патернов и т.д.


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

Особый общий ENV большинству команд не требуется, но в любом случае это не проблема — если он "общий", то какая разница, поддерживать его в /root/.bashrc или в /etc/profile.d/?
Notes в виде файла на конкретном сервере? Вы так шутите? Ну или это было очень-очень много лет назад. Сейчас для этой цели есть wiki.
Скрипты для bash/zsh/ansible — на то и скрипты, чтобы их можно было запускать всем, вне зависимости от того, какой у кого $SHELL.


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

Во-во. Типичные условия развития махрового консерватизма, когда всё делается по принципу "так было всегда" и "ничего не менять пока мы из-за этого не теряем деньги". К здравому смыслу и эффективной работе всё это отношения не имеет.

Сейчас для этой цели есть wiki.

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


К здравому смыслу и эффективной работе всё это отношения не имеет.

Категоричность обычно не является профессионализмом. Прочитайте ещё раз свой и мой текст, и поймете, что в общем-то наша позиция не отличается.

Категоричность обычно не является профессионализмом.

Звучит немного категорично, нет? :)


На самом деле категоричность с профессионализмом не связана вообще никак (не обязательно верить мне на слово, можете посмотреть определение терминов в словаре, например). Если ты очень хорошо владеешь каким-то инструментом или имеешь много опыта в какой-то области, то вполне можно позволить себе категоричные высказывания на этот счёт — почему нет, если ты действительно знаешь, о чём говоришь? Просто категоричные высказывания часто позволяют себе фанбои, которые недавно открыли для себя что-то классное, при этом толком не разбираются в том, о чём говорят, либо не учитывают, что ситуации бывают разные — отсюда и представление, что категоричность симптом непрофессионализма.


А если заведется любитель fish или ipython или tcsh? :)

Переменные окружения заданные в формате posix sh подчитать смогут все, так или иначе. Суть ведь не в том, чтобы сделать удобно всем сразу, а в том, чтобы дать возможность желающим сделать себе удобно самостоятельно.

Звучит немного категорично, нет? :)

Рекурсия, но и клин-клином.


Переменные окружения заданные в формате posix sh подчитать смогут все

csh точно нет — это антогонисты. Остальными не пользовался.


Суть ведь не в том, чтобы сделать удобно всем сразу, а в том, чтобы дать возможность желающим сделать себе удобно самостоятельно.

Ну допустим. Есть практический опыт? Мне это кажется утопичным.

csh точно нет — это антогонисты. Остальными не пользовался.

У fish тоже свой синтаксис с set. Только setenv не обязателен хотя и есть зачем‐то, можно использовать set -x.

Поэтому я и написал "… подчитать смогут все, так или иначе". Можно оставить основным шеллом bash или даже sh, просто написать в ~/.bashrc exec fish/tcsh, чтобы они запустились уже с этими переменными, можно загрузить в них эти переменные кучей других способов. Об этом не должна болеть голова при основном администрировании сервера, это вполне может быть личной проблемой тех, кому нужен fish/tcsh — главное, чтобы для них эта проблема была решаемой в принципе.

Мой практический опыт сводится к тому, чтобы во-первых избегать использования общих админских аккаунтов, и во-вторых стараться на сервера вообще ручками ходить по-реже и делать там по-меньше, а не к тому, чтобы на любом из 1000 серверов было удобно работать в zsh через sudo (в этом плане, кстати, когда на серверах работать неудобно — это скорее плюс, лишний мотив этого избегать в принципе). Удобно работать должно быть на рабочей станции и на 2-3 уникальных серверах, которые админятся по-старинке ручками, а не через ансибл.


Но мы вроде не мой личный практический опыт обсуждали, а принципиальную возможность и смысл установки zsh на сервера, причём по умолчанию, из коробки. На мой взгляд ничего утопичного в том, чтобы не использовать общий аккаунт для администрирования и в том, чтобы поставить везде пакет zsh — нет. Насколько это нужно реальным юзерам — посмотрите на результаты голосования, даже учитывая что статья про zsh они довольно показательны.

Общим аккаунтом в любом случае остается тот под которым запущено приложение. Этого не избежать. И переключаться под него через sudo приходится.


и во-вторых стараться на сервера вообще ручками ходить по-реже и делать там по-меньше

Ну в такой крутой инфраструктуре весь это вопрос не имет никакого значения.

Всё верно. :(


Теоретически, можно дать доступ ко всем нужным файлам приложения через права группы и setgid-каталоги, поставить всем umask 0002, тогда через sudo под аккаунтом самого приложения надо будет исключительно его запускать/перезапускать, а работать можно под личным аккаунтом.


Но при попытке применять этот подход на практике постоянно вылезали какие-то шероховатости. Нередко попадаются не очень качественно написанные приложения и скрипты, которые нечаянно удаляют setgid-бит каталогам когда пытаются изменить их права. Или, зачем-то, игнорируют umask и форсируют "безопасные" права. Плюс, имея полный доступ к файлам приложения его возможно запустить под личным аккаунтом, и очень часто по ошибке это и делали. А потом другой юзер не мог прибить процесс чтобы его перезапустить. Последнее, вероятно, проблема решаемая — можно в стартовом скрипте приложения проверять $UID, например, но количество излишних сложностей и потенциальных проблем начинает превышать комфортный уровень, в результате чего все на это забивают и продолжают пользоваться общим аккаунтом.

set[ug]id очень неприятная идея. Не зря в современных дистрибах уже почти не осталось подобных мест.

Для выполнимых файлов — безусловно. Но на каталоге setgid чем плох?

Сложно сказать. Вроде все довольно прозрачно, но как-то я не видел чтоб это широко использовалось.

его в /root/.bashrc или в /etc/profile.d/

А если заведется любитель fish или ipython или tcsh? :)

Меня как сидящего все еще на bash интересует,
для начала две базовые вещи:


  1. как сделать "бесконечную" историю? На bash я использую такой код:
    export HISTCONTROL=ignoredups
    export HISTFILESIZE=-1
    export HISTSIZE=-1
  2. Как поставить такой же "prompt" как у bash?
    case ${TERM} in
        [aEkx]term*|rxvt*|gnome*|konsole*|interix)
                PS1='\[\033]0;\u@\h:\w\007\]'
                ;;
        screen*)
                PS1='\[\033k\u@\h:\w\033\\\]'
                ;;
        *)
                unset PS1
                ;;
    esac

Я сходу не вижу в доке возможности указать -1 для HISTSIZE, но… а Вам реально важно, чтобы она была именно бесконечная? Учитывая что история считывается в память, что занимает время и место, значение HISTSIZE более 1 миллиона вряд ли имеет смысл (это даёт размер файла с историей порядка 50MB, и будет хранить историю примерно за 1 год).


Что касается PS1 — можно точно так же и поставить, разве что escape-последовательности будут другие. Но обычно в zsh для обновления заголовка терминала используют другой подход: существуют функции-хуки precmd и preexec, автоматически вызываемые перед выводом приглашения и перед запуском команды, и обновление заголовка терминала прописывают обычно в них (в частности, это даёт возможность записать в заголовок имя запущенной команды пока она выполняется, а не только текущий каталог). В oh-my-zsh это работает из коробки, в prezto не проверял, но скорее всего тоже.

а Вам реально важно, чтобы она была именно бесконечная?

Да, да и еще раз да. Нафига мне задумываться о том сколько строчек оставить,
а если для меня будет важна именно 1_000_000 + 1?


Иногда очень нужно посмотреть: "а какой хитрой командой
я делал вещь X пять лет назад?" Можно конечно сохранять хитрые команды в файлы,
или иметь файл snipets, но смысл если bash умеет все это сам сохранять.


Учитывая что история считывается в память, что занимает время и место, значение HISTSIZE более 1 миллиона вряд ли имеет смысл (это даёт размер файла с историей порядка 50MB, и будет хранить историю примерно за 1 год).

bash не считывает всю историю в память, а только несколько последних X строк (проверенно экспериментально),
плюс более ignore dups делает свое дело:


$ ls -lh .bash_history 
-rw------- 1 evgeniy evgeniy 3,4M апр 15 22:19 .bash_history
$ wc -l .bash_history
117402 .bash_history

Этому ноутбуку года 4.


Что касается PS1 — можно точно так же и поставить, разве что escape-последовательности будут другие

Т.е. тоже нельзя? Или есть автоматический перекодировщик escape-последовательностей?


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

Если у Вас за 4 года накопилось 117402 команды, то миллиона хватит лет на 40. Можно, конечно, всё-равно продолжать беспокоиться что миллиона может не хватить, но это уже проблема психологическая, а не техническая.


Автоматический перекодировщик чего конкретно? У Вас там ровно три значения: \u — юзер, \h — хост, \w — текущий каталог. Аналогичные три значения можно найти в доке zsh быстрее, чем мы это обсудим в комментах.

Если у Вас за 4 года накопилось 117402 команды, то миллиона хватит лет на 40. Можно, конечно, всё-равно >продолжать беспокоиться что миллиона может не хватить, но это уже проблема психологическая, а не >техническая.

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


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


Автоматический перекодировщик чего конкретно?

у меня там еще и цвета, которые закодированы escape последовательностями,
и по вашим словам:


разве что escape-последовательности будут другие

из них я сделал вывод, что и для цветов в prompt zsh требует какие-то свои escape последовательности.

из них я сделал вывод, что и для цветов в prompt zsh требует какие-то свои escape последовательности.

Вообще‐то нет, escape‐последовательности можно передавать терминалу как есть, как и в bash, только вместо \[ и \] будут %{ и %}. Но я бы не рекомендовал: оно либо не читаемое, либо вам придётся заводить переменные вроде BLUE_COLOR=$'\e[34m', тогда как zsh предоставляет вещи вроде %F{blue} для раскрашивания.

Для подсветки разными цветами последовательности действительно отличаются, но: во-первых указанные Вами отвечают не за цвета, а за указание терминалу/screen изменить заголовок окна, а они от шелла не зависят и везде будут одинаковые, а во-вторых в bash даже для смены цвета обычно задаются стандартные последовательности, которые не так удобно читать как "%B%F{red}жирный красный%f%b" в синтаксисе zsh, но зато, опять же, они должны работать одинаково в любом шелле, так что если нет желания переписывать их в синтаксисе zsh — их можно просто скопировать как есть.

UFO just landed and posted this here
Никогда не задавался такой идеей, хранить историю беконечно). А вообще — man bash

Вы комментарий на который отвечаете читаете? Для bash у меня все настроено, и даже настройки
приведены в теле комментария.

Да, узнал об этом шелле в этой статье https://habrahabr.ru/post/323496/
Первое впечатление было: «Вау! Крутая штука!»
Но в итоге поигрался пару часиков и вернулся на bash — на моем ноуте zsh тормозит конкретно.

Зато теперь знаю, что крутой промпт в скринкастах на маках — это zsh, а не фича макоси! )
Взял на заметку — придет время обновлять систему (на следующий Ubuntu LTS) попытаю еще раз счастья.
на моем ноуте zsh тормозит конкретно.

Это не zsh. В самом zsh тормозить нечему. Это тормозила чужая навороченная конфигурация с кучей включённых по умолчанию плюшек (вроде oh-my-zsh), которую Вы, вероятно, поставили, чтобы получить "вау-эффект" с первой минуты.

Нет, ту конфигурацию я не ставил, установил просто zsh из реп.
Конфиг почти пустой был — вот сейчас проверил (в системе zsh остался, я его не удалял), удалил совсем конфиг и запустил с нуля — тормозит.

А можно чуть конкретнее? Что именно тормозит и как Вы это определяете?

Набираю команду — после нескольких введенных символов курсор «спотыкается» — фризится, дальше сразу несколько следующих символов появляются и так повторяется в зависимости от длины команды.
Я печатаю вслепую, смотрю постоянно на монитор и такой дерганное отображение раздражает
(в bash'е, естественно, такого нет).

А при запуске zsh -f этот эффект тоже наблюдается?
Если нет — проблема в Ваших конфигах zsh, или в ~/ или в /etc/.
Если да — возможно проблема в каких-то общесистемных вещах, но для начала стоит попробовать обновить zsh на 5.2 или более новую версию.

Как-то я пересел на зишелл, навключал всяких вау плюшек. Было круто, но вся эта конфа тормозила на макбуке. В итоге соскочил назад на баш, покурил ман и стековерфлоу, реализовал почти все фишки на обычном баше в одном конфиге. Летает мухой.
Если у вас 1000 серверов и везде стоит обычный bash, то какой смысл ставить себе zsh локально? Я не перехожу на zsh в том числе и по этой причине.

1000 серверов управляется ведь не ручками, а через ansible/chef/etc. Так что раскатать на них zsh с вашими конфигами не должно быть проблемой, было бы желание.

1000 серверов управляется ведь не ручками, а через ansible/chef/etc.

Не всегда это так. На Хабре очень привыкли к ситуации когда 1000 серверов это: 500 app, 200 nginx, 100 mongo, ну и инфраструктура на сдачу.


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

Общие паттерны здесь не при чём. Хотя они всё-равно всегда есть, просто относятся к инфраструктуре, а не основной задаче сервера: логи, бэкапы, обновления, добавление аккаунтов для новых сотрудников, etc. И если сервер умер или его надо обновить/переустановить — Вы предпочтёте разыскивать уволившегося два года назад сотрудника, который знал что/как/почему надо настраивать на этом сервере, или всё-таки запустить плейбук ансибла который тупо раскатает на новый сервер всё, что необходимо — пусть даже этот плейбук нужно было когда-то написать конкретно для этого сервера?

Да чтож такое, почему на Хабре принято читать только свои комменты :(


Раскатка нового сервера это первое что автоматизируется. В интерент проектах это важный кусок работы (поскольку раскатка идет часто, сервера однотипные). Но в ентерпрайзе это мизер. Он автоматизирован, поскольку его легко автоматизировать, но это дай бог 2-3 процента работы. Аналогично заведение нового пользователя. Вы сейчас гововорите о мелочах, которые автоматизированы буквально у всех.


А вот например, клонирование крупного софта (OEBS или SAP), проведние каких-то особых операций с этим софтом автоматизируется со скрипом: редкие операции над большим количеством компонент, высокая вариативность настроек от сервера к серверу. На нахождение именно этих патернов уходят долгие годы. Потом они закрепляются в том же ansible или даже в продуктах Oracle (Rapid Clone хороший пример этой истории).


Т.е. сумируя: если на старте вы точно знаете что делать и видите все точки ветвления в операции — то сразу пишите ansible скрипт, если вам сказали иди туда не знаю куда, возьми индускую документацию и сделай, то сначала вы сделаете, а потому уже будете автоматизировать, поскольку вам снача нужно набить експу и понять как это работает.

Угу. Только свои комменты. Именно. У нас здесь вообще-то есть определённый контекст, и обсуждаем мы не SAP. Какое отношение описанное Вами имеет к сложности/неприемлемости установки zsh на 1000 разношёрстных серверов в энтерпрайзе?

Ну да, пожалуй флейм, согласен.

Лучше на дефолте, но зато везде одинаково, чем тут zsh, а везде bash и ругайся потом, что чего-то работает не так, как ты привык. Пожалуй это главный аргумент в пользу оставить всё как было.
Да не дает особо крутых каких-то нехватающих уберфич этот zsh.
Подсветка синтаксиса настраивается и так, полно скриптов в bashrc.
Редактирование команд и интеграция с редактором — продвинутые парни используют vim/emacs mode для bash
Автодополнение — так по неизвестным командам все равно открываешь man, часто используемые команды заносятся в алиасы, а для совсем экзотических случаев есть bash-completion.
Хитрое скриптование — так это вообще не задача шелла, нафига его использовать не по назначению, если есть профессиональные инструменты perl/python.
продвинутые парни используют vim/emacs mode для bash

emacs mode это дефолт так то. Можно включить vim mode, но даже мне, любителю vim, этот режим неудобен.
для совсем экзотических случаев есть bash-completion.

скорее наоборот, для экзотики man, а обычно всё автодополняет именно bash_completion.
Хитрое скриптование — так это вообще не задача шелла

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

Какая ещё подсветка синтаксиса в bash? Никогда не видел таких скриптов.


Про «интеграцию с редактором» в zsh тоже. Вот для приложений на основе readline кто‐то создал библиотеку, которая позволяет использовать Vim (реальный Vim, а не неполноценную эмуляцию в виде vim mode) для редактирования. ZLE — это собственная альтернатива readline от авторов zsh, а не какой‐то редактор: в виде отдельной библиотеки ZLE не существует.
А Vim/emacs mode с ZLE не сравняться: попытайтесь, к примеру, создать сочетание клавиш для вставки из буфера обмена в уже экранированном виде. Или ещё интересный запрос: хочется написать zmw *.c *.c.bak и переименовать все файлы *.c в *.c.bak. Нет, с экранированием и специальным¹ скриптом/приложением такое можно сделать. Я спрашиваю, как это сделать без того, чтобы я использовал экранирование.


Ваша претензия к автодополнению тут не в тему, совершенно. В zsh это гораздо шире: его можно использовать для поиска файлов (к примеру, /u/b/z<Tab> можно дополнить до /usr/bin/z и дальше он будет предлагать варианты на z), оно работает внутри различных синтаксических конструкций ($V<Tab>, $(e<Tab>), $(e<Tab> (я не зря указал оба варианта, проверьте их оба в bash как следует)), оно умеет убирать (или не убирать, если вам не нравится) ненужные косые черты при автодополнении каталогов (я имею ввиду, вы написали cmd<Space>dir<Tab><Space>foo и получили cmd directory foo, а не cmd directory/ foo). Именно man мне автодополнение почти никогда не заменяет, но на bash я его не променяю.


Хитрое скриптование — оно у zsh вообще‐то больше заточено под write-only однострочники и это как раз задача shell. Скрипты с некоторыми возможностями zsh получатся не слишком читаемыми и их лучше писать больше похожими на bash‐скрипты.


¹ zmv — это функция zsh, zmw — это моё что‐то вроде alias’а noglob zmv -W, только noglob меня чем‐то не устроил…; впрочем чем меня не устроил noglob — не важно, да я и не помню — в bash такого временного модификатора всё равно нет.

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

Какая ещё подсветка синтаксиса в bash? Никогда не видел таких скриптов

Догадываетесь почему? Потому что это нафиг никому не надо — смотреть в непонятный пестрый экран. Там, где это действительно надо (редакторы), это делается другими инструкментами. А вот если вы погугите немного в этом направлении, найдете очень много хитрых решений в bashrc для этого функционала. Вчера только свежий дебиан 8.4 ставил на одну из ВМ, там в консоли уже по умолчанию все цветное (если xterm-256color).

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

А зачем? Люди используют удаленные сессии, как там вообще может удаленный zsh перехватывать буфер обмена? Если вы пользуетесь действительно таким функционалом, вам гораздо быстрее написать скрипт экранирования и сделать в консоли что-то вида echo <Shift-Ins> | escape

хочется написать zmw *.c *.c.bak и переименовать все файлы *.c в *.c.bak.

Не хочется. Для этого я запущу find или xargs, а в самом сложном варианте сделаю через однострочних в цикле for.

его можно использовать для поиска файлов

вот попробуйте испоьзовать этот прием на рабочем сервере с миллионом (или сколько там ограничение у разных fs) файлов. Вы в таких случаях отучитесь вообще пробовать у шелла автодополнение. Попробовать такое на embedded дистрибутивах также вам доставит удовольствие.

оно работает внутри различных синтаксических конструкций

А зачем? В однострочниках переменные называются интуитивным образом, их не надо дополнять. В многострочниках это задача редактора.

Хитрое скриптование — оно у zsh вообще‐то больше заточено под write-only однострочники

Так я это и не отрицаю. Просто каждому хотелось бы, чтобы write-only рецепт сработал как на нагруженном сервере, так и на очередной поделке с dd-wrt, так и на локальной машине. А учить для одного сервера zsh, для того, чтобы на сотне других пользоваться bash, как-то уже совсем не то.

Наверно, zsh хорошо подходит, если много работаешь именно на локальной машине. Но перекрыть его возможности обычным башем также с легкостью можно.

Ну и в догонку — согласно вики zsh был запущен в лохматом 1990, я с ним плотно игрался в 2008-2009 (припоминаю, там еще были косяки по unicode). За все это время с развитием технологий виртуализации, автоматической настройки серверов, я не встречал ни одной крупной организации, где бы в init скриптах на создание очередного сервера стояла автоматическая установка zsh. Я полагаю, это не просто так.

Shell должен работать быстро везде (за исключением машин в Австралии или подключенных через спутниковый канал=), если появляется лишняя непредсказуемая задержка — она уже сама наводит панику, что какую-то команду я ввел зря.
Я не пытался сделать какие-то претензии к zsh, я просто хочу показать, что его функционал излишен для выполнения работ на удаленных машинах в целях системного администрирования.

Хм. А почему Вы для таких работ используете bash, ведь есть же sh? Разве функционал bash не излишен примерно в той же степени, что и zsh?


Догадываетесь почему? Потому что это нафиг никому не надо — смотреть в непонятный пестрый экран.

Звучит как "виноград кислый", если честно. Я, лично для себя, пока ещё не определился, нравится мне подсветка синтаксиса или нет (но скорее всего надо просто немного поднастроить цвета, может отключить подсветку отдельных элементов). Но я не вижу абсолютно никакой проблемы в том, что при наборе на удалённом сервере я сразу вижу есть ли опечатка в имени команды или не закрытые кавычки, ещё в процессе набора, до запуска команды. Если оно из коробки "пёстрое" — ну так подправьте цвета под свой вкус, отключите подсветку лишних элементов, но в самой идее подсветки синтаксиса абсолютно ничего плохого нет, и продуктивность это обычно повышает.


Люди используют удаленные сессии, как там вообще может удаленный zsh перехватывать буфер обмена?

Хрен его знает. :) Но я только что проверил — через ssh работает, а в screen (даже локальном) — нет.


Не хочется. Для этого я запущу find или xargs, а в самом сложном варианте сделаю через однострочних в цикле for.

А мне вот хочется. Вероятно, это дело вкуса. Я линух админю уже 23 года, но параметры find для меня так и не стали интуитивно понятными, что-то чуть нетривиальное — приходится сначала лезть в man, а потом ещё и экспериментировать немного, чтобы убедиться что команда возвращает нужные файлы. Так что возможность использовать find значительно реже — для меня выглядит довольно привлекательно.


вот попробуйте испоьзовать этот прием на рабочем сервере с миллионом (или сколько там ограничение у разных fs) файлов. Вы в таких случаях отучитесь вообще пробовать у шелла автодополнение. Попробовать такое на embedded дистрибутивах также вам доставит удовольствие.

Практически всё, что даёт удобный интерфейс и облегчает жизнь пользователя — делает это за счёт большего количества вычислений, т.е. потерь производительности. Обычно это не заметно, потому что время реакции человека меньше этих задержек. Но, да, бывают крайние случаи когда это заметно. И если Вы 90% своего времени выполняете команды в каталоге с миллионом файлов или на невероятно медленном устройстве — zsh тут действительно будет неуместна. Но, как правило, 90% своего времени проводится вовсе не в таких условиях, и проще быть осторожнее в набираемых командах когда изредка оказываешься в таких условиях, чем лишать себя удобств во всё остальное время.


А зачем? В однострочниках переменные называются интуитивным образом, их не надо дополнять.

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


Просто каждому хотелось бы, чтобы write-only рецепт сработал как на нагруженном сервере, так и на очередной поделке с dd-wrt, так и на локальной машине.

Да. К сожалению, мир устроен иначе. Я вот изредка попадаю на сервера где нет bash. И половина набираемых мной команд, внезапно, перестаёт работать как ожидалось. Знаете, что я в этот момент делаю? Устанавливаю, с матами, bash. А ещё bash бывает разных версий, так что часть привычных конструкций изредка на древних серверах выдаёт не то, что ожидается (такое бывает не часто, да, но всё-равно). Так что Ваша мечта всегда будет только мечтой, к сожалению.


А учить для одного сервера zsh, для того, чтобы на сотне других пользоваться bash, как-то уже совсем не то.

Вот! Именно это и удерживало меня от изучения zsh долгие годы. И именно про это написана статья — чтобы показать, что отличий между bash и zsh не так много, что "учить zsh" это не так масштабно и сложно как кажется на первый взгляд, что практически все команды которые работают в bash будут ровно так же работать в zsh (а если включить SH_WORD_SPLIT — тогда, думаю, вообще все в которых не встречается $BASH…).


Запомнить что в bash нельзя пользоваться флагами/квалификаторами/модификаторами несложно, и даже если что-то такое набрать по привычке случайно в bash — будет не трагедия, а синтаксическая ошибка (как и для сокращённых вариантов if|while|for). Автодополнение в bash будет работать хуже, но это тоже не помешает набирать корректные команды. По большому счёту, основное что может создать проблему помимо SH_WORD_SPLIT — это шаблоны с <число1-число2>, которые bash скорее всего поймёт как перенаправление stdin/stdout.


Если нужно много работать с bash, то Вам никто не мешает включить SH_WORD_SPLIT и забыть про возможность использовать <число1-число2> в шаблонах. Тогда шанс, что привычная по zsh команда некорректно заработает в bash, будет пренебрежимо мал. В общем-то, именно для таких ситуаций в zsh и существуют эти 177 опций, кардинально влияющие на поведение и поддерживаемый синтаксис — чтобы каждый мог работать в такой zsh, которая подходит лично ему, а не в такой же zsh, как у всех.


Наверно, zsh хорошо подходит, если много работаешь именно на локальной машине.

Да. Но, в идеале, на серверах вообще нежелательно ручками работать, для этого есть ansible/chef/etc. Идеал не всегда достижим, конечно, но общая тенденция идёт в этом направлении. Приложения расползаются по docker-контейнерам, в которых вообще не то, что bash, но даже и sh может не быть (хотя бы из соображений безопасности).


Но перекрыть его возможности обычным башем также с легкостью можно.

Это прямая ложь, нехорошо, однако.


я с ним плотно игрался в 2008-2009 (припоминаю, там еще были косяки по unicode)

Да, судя по changelog — было такое. Но сейчас вроде всё ок, так почему наличие багов 8 лет назад является проблемой сейчас?


За все это время с развитием технологий виртуализации, автоматической настройки серверов, я не встречал ни одной крупной организации, где бы в init скриптах на создание очередного сервера стояла автоматическая установка zsh. Я полагаю, это не просто так.

Как я уже выше упоминал, чем дальше мы идём по тропинке виртуализации, увеличения количества серверов и сужения выполняемых ими задач — тем меньше смысла выполнять на этих серверах команды вручную по ssh, они должны управляться через ansible etc. Поэтому там и bash нередко избыточен, не говоря уже про zsh. Так что да, это не просто так.


Shell должен работать быстро везде (за исключением машин в Австралии или подключенных через спутниковый канал=), если появляется лишняя непредсказуемая задержка — она уже сама наводит панику, что какую-то команду я ввел зря.

Угу. Но я пока от zsh задержек не наблюдал. Допускаю, что они бывают, вот эта настройка в oh-my-zsh наводит на такую мысль (но здесь подразумевается индикация причины задержки, так что всё вроде ок):


# Uncomment the following line to display red dots whilst waiting for completion.
COMPLETION_WAITING_DOTS="true"

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


Например, что вставка из clipboard нескольких строк теперь не начинает молча выполняться, а просто показывает вставленный текст и ждёт подтверждения Enter-ом для его запуска; очень быстрая навигация по каталогам — у меня по Ctrl-Shift-Left|Right перебираются последние каталоги (причём не затирая текущую частично набранную команду — изменяется только имя каталога в приглашении перед командой), по Alt-q можно "отложить" текущую набранную команду, выполнить вместо неё другую и тут же автоматически продолжить редактировать отложенную команду с курсором в том же месте, в bash после прерывания по Ctrl-C некоторых команд состояние терминала портилось и нужно было вслепую запускать reset — а в zsh этого не просходит… и там много ещё такого всякого. Давеча у меня rm * внезапно спросил подтверждения… оказывается, есть и такая фича, специально для ситуации когда rm получает одним из аргументов *. В общем, приложение изначально заточенное сделать тебе "удобно" в интерфейсе, и не заточенное — это две большие разницы, и чувствуется это в куче разных мелочей.


Я не хотел всё это перечислять в статье, потому что то, что одному удобно — другого только раздражает, но суть в том, что в zsh слишком много всего и каждый может сделать намного удобнее лично для себя. А к заметно более удобному привыкаешь моментально… так что выкатывание zsh со своими конфигами на сервера становится вопросом времени. :)

Это скорее относится к скриптам. Скрипты я на zsh писать тоже не планирую,

Но ведь есть одно строчные скрипты, типа


for i in *.jpg; do convert -resize 200x200 $i /tmp/res/`basename $i`.png; done

т.е. какое-то знание о while/for/if/ нужно, иначе как скажем применить несколько команд к определенным (не всем) файлам в директории.

И что? Такой bash/sh синтаксис zsh понимает и так, у него очень сильная совместимость с другими шеллами. А вот если вы привыкнете в zsh писать в сокращённой форме:


for i in *.jpg; convert -resize 200x200 $i /tmp/res/`basename $i`.png
# или даже
for i in *.jpg; convert -resize 200x200 $i /tmp/res/${i:t}.png

то всё, что вам грозит при попытке запустить это в bash:


-bash: syntax error near unexpected token `convert'

В общем, если честно, я не вижу трагедии. Ладно шелл, но вот пользоваться на других машинах редактором-убожеством вроде mcedit, nano или не настроенного vim — я "пас" в любом случае. А раз всё-равно приходится везде носить свои настройки для vim, то добавить к ним ещё и настройки для zsh — не сложно.

вставка из clipboard нескольких строк теперь не начинает молча выполняться, а просто показывает вставленный текст и ждёт подтверждения Enter-ом для его запуска;

давно я не копировал в терминал что-то, чтобы выполнить. А на боевом сервере я бы не рискнул такое делать даже зная, что zsh не выполнит вставленное.
очень быстрая навигация по каталогам — у меня по Ctrl-Shift-Left|Right перебираются последние каталоги (причём не затирая текущую частично набранную команду — изменяется только имя каталога в приглашении перед командой)

в inputrc (где удобно, глобальный или нет) вписываем следующее:
"\e[A": history-search-backward
"\e[B": history-search-forward
"\eOA": history-search-backward
"\eOB": history-search-forward

теперь начинаем вводить команду и жмём стрелочку вверх — введённый текст не затирается, в истории ищутся последовательно все команды, которые начинались так же. Так же знаю ещё одну фичу zsh — он ходит по каталогам не взирая на case символов, для этого в баш есть такое:
set completion-ignore-case On

теперь cd movies или Movies — не важно, если совпадение по буквам единственное — bash его заполнит.
по Alt-q можно «отложить» текущую набранную команду, выполнить вместо неё другую и тут же автоматически продолжить редактировать отложенную команду с курсором в том же месте

sudo apt insta^U
вводим новую команду
^Y
готово.
в bash после прерывания по Ctrl-C некоторых команд состояние терминала портилось и нужно было вслепую запускать reset

достаточно редкое явление, чаще всего ^L помогает.

Вот и в bash я уже привык ко всему и не вижу смысла везде тащить zsh, тем более, что киллер-фич не особо густо, на самом деле.

Удобство создаётся не какой-то киллер-фичей, а множеством разных мелочей.


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

Я про это отписался выше: настройте zsh опциями так, чтобы максимально эмулировать поведение bash, забудьте про одну-две фичи zsh которые могут создать проблемы в bash — и вы получите большую часть доступных удобств zsh без создания себе проблем при наборе привычных по zsh команд в bash.

очень быстрая навигация по каталогам — у меня по Ctrl-Shift-Left

Как это включить?

Подключить плагин dircycle из oh-my-zsh.

Вся эта история вокруг bash/zsh напоминает обсуждения какие обои и какие виджеты должны быть на рабочем столе. Начисто игнорируя то, что реальная работа происходит не на рабочем столе и не в bash/zsh.

Есть люди, которые в терминале проводят очень много времени, и от удобства терминала зависит их продуктивность. Некоторые люди предпочитают копировать файл из директории A в директорию B с помощью mc и тратят на эту операцию иногда по несколько минут. Даже зная, что с помощью bash это сделать можно за несколько секунд, все равно предпочитают mc, потому что он дает им лучшее понимание контекста. Мне нравится zsh ровно тем, что повышает продуктивность (выполняю больше действий в единицу времени), дает лучшее понимание контекста (где нахожусь, какой бранч в git'е, есть ли изменения), экономит время (не надо запускать time, если кто-то работал медленно) и еще много приятных плюшек.
В правильной статье про zsh должны быть скриншоты/гифки с демонстрацией того, как это работает.

В посте тема дополнения особо не затрагивалась, но я бы добавил, что есть такой виджет дополнения как _complete_help, который покажет нынешний контекст, а с NUMERIC ещё и используемые стили.


Вместо ручного ввода escape-последовательностей в zkbd можно их получить модулем terminfo (http://zshwiki.org/home/zle/bindkeys#reading_terminfo).

С вариантом на terminfo есть свои проблемы (конкретно в моём случае).
Во-первых, я начитался про то, как у людей подтормаживает zsh при запуске из-за большого количества подключённых модулей/плагинов, поэтому стараюсь изначально не подгружать то, без чего можно обойтись.
Во-вторых, в $terminfo есть далеко не все кнопки, например как через него получить код для Ctrl-PageUp?
В-третьих, у меня в ~/.Xresources есть немаленький блок строчек URxvt.keysym.* задающий конкретные escape-последовательности конкретным кнопкам (без этого часть комбинаций не работает в Vim)… и что-то я сомневаюсь, что $terminfo будет возвращать именно эти комбинации, это было-бы как-то уж слишком волшебно.
Ну и в последних — у меня не так много разнотипных серверов, везде примерно одно и то же, так что файл с результатом zkbd попадёт на сервера вместе с остальными конфигами zsh и будет, я полагаю, вполне корректно работать везде, без необходимости вызывать zkbd на каждом сервере отдельно.

Во-вторых, в $terminfo есть далеко не все кнопки, например как через него получить код для Ctrl-PageUp?

Но кнопки без модификаторов присутствуют. Присутствуют даже некоторые с модификаторами (Ctrl-Left, Ctrl-Right, Shift-Tab). zkbd не спрашивает Shift-Tab.


В-третьих, у меня в ~/.Xresources есть немаленький блок строчек URxvt.keysym.* задающий конкретные escape-последовательности конкретным кнопкам (без этого часть комбинаций не работает в Vim)… и что-то я сомневаюсь, что $terminfo будет возвращать именно эти комбинации, это было-бы как-то уж слишком волшебно.

Не будет, пока вы не измените соответствующий capability и не перекомпилируете утилитой tic. Зато эти изменения станут видны другим программам, полагающимися на terminfo.

UFO just landed and posted this here
UFO just landed and posted this here
Похоже правильное место для моего вопроса. Как выставить приоритет в автодополнении zsh, чтобы каталоги подставлялись до команд? Иногда хочется перейти в каталог, но есть куча команд с похожим названием и это мешает.
Пример
image

Попробуйте это (возможно стоит указать только local-directories, а остальное выкинуть):


zstyle ':completion:*:*:-command-:*:*' group-order \
    local-directories directory-stack named-directories directories

А по мне — так только в линуксе я перестал каждый раз полдня настраивать прочее окружение. 15 галочек там, 25 здесь, поставить то, это…
Независимо от консоли линукса, в которой я нахожусь, я все могу делать сразу. И во многом это заслуга именно bash. На любом сервере я могу сразу работать, не испытывая неудобства по поводу, например, того самого чудесного автодополнения или ещё какой чудо-фичи, настроенной под меня за полдня подготовки рабочего места к собственно работе...

Почему бы вам не попробовать сохранять ваши dotfiles где-нибудь на github?
Две-три команды и у вас ваше окружение на любом компьютере.

Проблема в том, что сервера не принадлежат единственному и неповторимому админу (мне), туда ходят минимум 5 коллег со своими представлениями об удобстве.
bash в этом случае — достаточно приличный компромисс, после установки bash-completion, который достаточен для выполнения админских задач.

На локалхосте или сервере, где ты _единственный_, кто туда ходит — без проблем, хоть sh, хоть tcsh, хоть zsh. В случае сервера, куда рутом ходят только в случае проблем, zsh с чужими настройками — помеха, а не помощь.
Соглашусь с предыдущим оратором. У меня есть домашняя рабочая станция, есть рабочая. А есть несколько десятков серверов, куда я никакие dotfiles тащить не буду ни в коем случае.
Посыл был именно в том, что мне не надо привыкать ни к чему — везде одна среда.
и да, dotfiles и прочие плюшки home-каталога у меня ездят между рабочими станциями. Потому что это моё, и если что-то пойдёт не так, то это мои личные проблемы, а не проблемы моего работодателя.
UFO just landed and posted this here
UFO just landed and posted this here

Реальной необходимости нет в абсолютном большинстве нововведений. Любая ОС 15-ти летней давности содержит всё реально необходимое для работы. Даже в хабре нет реальной необходимости для работы "большинства матёрых линуксоидов"… но, тем не менее, Вы зачем-то тут читаете статьи и даже комментируете (а была ли реальная необходимость в Вашем комментарии?). Что касается "красивостей" — то же можно сказать и про абсолютное большинство книг/фильмов/картин/музыки — реальной необходимости в них нет. (Кстати говоря, если говорить абсолютно честно и искренне, не принимая во внимание желание оправдать получаемую зарплату — а есть ли реальная необходимость в большей части Вашей работы? Вы действительно каждый день делаете то, без чего нельзя обойтись, ваши проекты и сервера действительно реально необходимы человечеству?)


Суть в том, что нет реальной необходимости ограничивать себя реально необходимым минимумом, если можно сделать красивее, удобнее, интереснее… Иногда это вредит продуктивности, иногда помогает, но продуктивность — в любом случае не самое главное в жизни.


P.S. Что касается "я матёрый линуксоид, знаю все нужные флаги" — когда на глаза регулярно попадается список флагов при автодополнении, то даже матёрому линуксоиду это позволяет регулярно открывать для себя новые флаги и возможности, без которых можно было бы обойтись, конечно, но которые могут быть полезны/удобны. Я вот полностью список флагов ls и многих других базовых команд первый и последний раз читал примерно в 1994, когда осваивал линух. После этого у меня всегда было чем заняться и без перечитывания этих man-ов в поисках "а нет ли там чего полезного, чего не было в 1994 либо что я в 1994 не оценил/не запомнил".

UFO just landed and posted this here
… в реальном использовании bash … не настолько менее продуктивен, чтобы ради этого переходить …

С этим я соглашусь. Но это не значит, что переходить нет смысла. Переход на zsh — вопрос не продуктивности, а удобства. И даже если через год вернуться на bash, то оно всё-равно того стоит, потому что вернётесь Вы уже с пониманием, что и как можно сделать удобнее лично для Вас, и часть этого действительно получится реализовать в bash — так что время потраченное на изучение и использование zsh не пройдёт даром (потому что в результате Вам станет удобнее работать в bash).


Вообще, bash штука странная. Умение писать на нём скрипты — является скорее минусом, потому что как только эти скрипты выходят за пределы лично ваших компов, то вас (почти) сразу начинают тыкать носом в "башизмы" в этих скриптах и просить переписать их так, чтобы они работали на любом sh (мне пришлось даже тулзу checkbashisms поставить для упрощения этого процесса). То, что bash "везде установлен" — вообще-то не является правдой, в BSD его обычно из коробки нет, в некоторых линухах вроде OpenWRT тоже нет, etc. А то, что его обычно первым делом устанавливают — ну так ровно с тем же успехом можно было и zsh поставить. Но даже если bash из коробки есть, то вот пакет bash-completion уж точно из коробки отсутствует — а Вы вроде не отрицаете реальную необходимость автодополнения для bash. И снова, в чём принципиальная разница между необходимостью на каждой системе первым делом ставить пакет bash-completion или пакет zsh? То, что "bash везде одинаковый" — тоже не правда, потому что тогда Вам нужно перестать использовать все alias-ы и дополнительные keybinding-и в inputrc. "Голый" bash, без алиасов в .bashrc, без автодополнений и keybinding-ов, который есть почти но всё-равно не везде — это действительно то, чем Вы бы хотели ежедневно пользоваться? И чего ради, чтобы не устанавливать ни одного лишнего пакета, который не нужен для выполнения основных функций сервера?


На мой взгляд в отношении bash/zsh основная проблема скорее в инерции мышления и консерватизме, нежели в реальных причинах предпочитать bash. Примерно так, как было когда-то, когда сайты дизайнили "под IE" а не по стандартам, потому что "IE есть у всех". Там ситуацию, хоть и с громадным трудом, переломили — потому что были заинтересованные в этом крупные игроки. А в отношении bash/zsh таких нет, если мы хотим чтобы нам же было удобнее, то менять ситуацию (читай — ставить везде zsh по умолчанию, просто из вежливости к коллегам) надо нам самим.

UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
А почему никто не сказал про безопасность?
Когда в zsh копируешь строку с переносами, то оно не выполняется по ходу вставки, в отличии от bash, а тихо ожидает дальнейших действий.

Я смотрю тут одни матерые сисадмины с 100+ чужих серверов собрались. У меня другой сценарий: 6 машин, включая локальную, везде через ansible накатывается плюс-минус один конфиг zsh с плагинами (есть небольшие различия из-за того, что оси разные, все различия также лежать в плейбуках).


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


На чужих серверах мне редко приходится бывать, да, там не хватает zsh дополнений и прочего, но 99% времени я провожу в настроенных мной терминалах.


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


Не исключаю, что все, что нужно можно написать в одном конфиге на bash, но зачем, если можно пользоваться готовым?

с парой секунд ожидания на старте мы готовы мириться.

Если Вы про время старта zsh, то это, вообще-то, проблема решаемая. Я лично не люблю автоматическое обновление плагинов, ни для vim, ни тем более для шелла (помимо прочего, это ещё и немаленькая дыра в безопасности) — я лучше буду делать плагинам git pull когда мне это нужно, ещё и посмотрев при этом git diff. А вот скорость работы я люблю, включая скорость запуска (у меня постоянно запущено под 20 терминалов, и все они автоматом запускаются при загрузке компа).


Если выкинуть сложную и медленную логику обновления разных типов плагинов, то всё остальное можно заоптимизировать при желании на пару порядков относительно "самого быстрого фреймворка":


% time zsh -i -c 'echo ok'
ok

0.037 real  0.025 user  0.009 sys  8MB RAM

Это скорость запуска весьма навороченного конфига (там только моего кода около 1000 строк, плюс кучка плагинов — zsh-completions, syntax highlighting, частично грузится oh-my-zsh, ну и разная мелочь в количествах).

Спасибо, подебажил свой конфиг (core i5, hdd, ubuntu 16.04, zsh 5.1.1):
100 мс — пустой .zshrc
350 мс — + пустой antigen && antigen apply
450 мс — + тема (powerlevel9k)


Дальше была какая-то магия: после комментирования-раскомментирования разных плагинов в итоге получилось так, что вышеописанный конфиг стал грузиться 250 мс.


Через какое-то время понял, что включение-отключение тяжелого плагина иногда (не всегда!) оставляет его в кеше, поэтому вашу команду дополнил:


rm ~/.*.zwc; time zsh -i -c 'echo ok'

Если включить один из плагинов: docker, pip, python, vagrant, хоть один, хоть все сразу — время увеличивалось на 250 мс. Явно что-то там где-то общее подгружается, хотя я заглянул в них (кроме огромного docker) и ничего такого общего не увидел. Почему так может быть?


В одном из своих плагинов нашел ошибку, которую я буквально вчера посчитал хорошей идеей: вместо копипаста списка команд своего скрипта я вызывал args="$(myscript help)" и сохранял его в массив, это стоило мне +250 мс.


Еще нашел virtualenvwrapper, +250 мс


В итоге, удалил свой кривой плагин, удалил pyvirtualenv, получил 320-330 мс стабильных, если включить 4 странных плагина (docker, pip, python, vagrant), то 630-680 мс. В начале было около 1 секунды.


Можно ваш конфиг попробовать? Мне кажется, что дело не только в конфиге, что-то у меня еще не в порядке.

zwc удалять не надо, их надо создавать (хотя может и не для всего — для совсем мелких файлов у меня есть подозрение, что zwc только тормозов добавляют).


Конфиг мой можно будет увидеть чуть позже, когда я закончу его допиливать и выложу на гитхаб как dotfiles.


Для скорости выполнения .zshrc я использую следующие подходы:


  • не загружать ненужные плагины (банально, да)
  • стараться запускать как можно меньше внешних команд $(cmd args …) или хотя бы отложить их запуск до момента, когда они реально понадобятся при запуске какой-то команды ручками
  • если какая-то функция/плагин при загрузке делает сложные расчёты/заполнение больших массовов/хешей (напр. коды для 256 цветов) — скидываю уже заполненный массив/хеш в кеш-файл и при следующей загрузке этой функции/плагина читаю из кеша (при условии, что файл кеша новее файла самой функции/плагина)
  • подгружаю плагины через свою функцию zsource
  • вызываю свою функцию zzcompile для:
    • файла с кешем completions (.zcompdump) — кеш это хорошо, а хорошо откомпилированный кеш это ещё лучше :)
    • самого .zshrc — он у меня пока довольно большой т.к. по сути заменяет фреймворк
    • дополнительных файлов крупных плагинов (вроде fast-syntax-highlighting/fast-highlight) которым фреймворк автоматически не делает zcompile

zsource:


# Ensure sourced file will be loaded faster… at least next time.
source $1
zzcompile $1

zzcompile:


# (Re-)Compile source files in background, if needed.
[[ $1.zwc -nt $1 ]] || {
    sleep 1         # looks like mtime difference must be > 1 sec, or .zwc will be ignored
    zcompile -U $1
} &!

пример использования:


autoload -Uz compinit
compinit -d $ZSH_CACHE_DIR/zcompdump
zzcompile $ZSH_CACHE_DIR/zcompdump
...
zsource $BUNDLE/dircycle/*.plugin.zsh
zsource $BUNDLE/fast-syntax-highlighting/*.plugin.zsh
...
zzcompile $ZDOTDIR/.zshrc
zzcompile $BUNDLE/fast-syntax-highlighting/fast-highlight
100 мс — пустой .zshrc

Так не должно быть. Пустой это вот так:


% time zsh -f -i -c 'echo ok'                                                                  
ok

0.002 real  0.001 user  0.000 sys  8MB RAM

Система у меня чуть по-быстрее Вашей (i7 @ 4.5GHz, hdd, zsh-5.2, gentoo), но не настолько же.

Нет, это не пустой. Без -f zsh загружает (пробует загрузить) минимум четыре файла: системный zshenv, пользовательский zshenv, системный zshrc, пользовательский zshrc. Ещё четыре, если zsh — login shell. Плюс всё нужно удвоить — есть ещё zwc файлы и zsh обязательно сделает для них stat. 100 мс здесь легко может съесть сильно загруженная (IO) система, с вытесненными из кэша файлами настроек zsh. Хотя у меня с пустым zshrc и echo 1 > /proc/sys/vm/drop_caches по‐прежнему почти ноль:


% time zsh -i -c 'true'
zsh -i -c 'true'  0,00s user 0,00s system 0% cpu 0,011 total

Полагаю, моя система должна быть сильно загруженной для 100 мс. Или есть ещё какие кэши. Или, скорее, в дистрибутиве popstas напихали фигни в /etc/zshrc, а, может, у него просто очень длинная история: моя


% time ( cat ~/.zsh-history/hist | wc -l )
66692
( cat ~/.zsh-history/hist | wc -l; )  0,00s user 0,02s system 31% cpu 0,063 total

 — это 63 мс просто на подсчёт числа строк (15 мс с кэшем) (не хочу проверять в zsh: если ошибусь, её попортит).

Система совсем не загружена:


$ free -m                                                                                                                                            
              total        used        free      shared  buff/cache   available
Mem:          24028       14752         217         147        9058        8673
Swap:          4767        3976         791

$ uptime                                                                                                  
 23:04:17 up 17 days,  1:02,  5 users,  load average: 0.07, 0.11, 0.21

Сейчас перепроверил, 0.06 примерно выдает, видимо вчера какие-то zwc тяжелые оставались, все равно в 6 раз больше, чем у вас. Странно…
А с -f тоже по нулям.

Нашел, 60 мс добавляет compinit в /etc/zsh/zshrc в Ubuntu 16.04, оно завернуто в условие на переменную skip_global_compinit, я добавил в /etc/zsh/zshenv строчку:


skip_global_compinit=1

После этого конфиг стал грузиться 300 мс вместо 600!
Я почти уверен, что при этом что-то сломалось, но на первый взгляд все дополнения работают, может подскажете, что дает compinit и где искать потерянный функционал?

Что даёт compinit написано в man zshcompsys. Если всё работает — вероятно ваш фреймворк тоже вызывает compinit (они все это делают, что характерно) и ничего не потеряно.

compinit нужен для работы умного автодополнения. У меня в zshrc он вызывается с ключём -C.


Без кэша compinit должен обойти все места, где есть файлы с описанием автодополнений к разным командам, прочитать (нужна минимум первая строчка) эти файлы и сохранить результат куда‐то внутрь процесса, а так же в файл с кэшем (~/.zcompdump, у меня он 46K). Вот как у меня влияет compinit:


# echo 1 > /proc/sys/vm/drop_caches
% time zsh -f -i -c 'autoload -Uz compinit ; compinit -D'
zsh -f -i -c 'autoload -Uz compinit ; compinit -D'  0,21s user 0,07s system 62% cpu 0,447 total
% time zsh -f -i -c 'autoload -Uz compinit ; compinit -D'
zsh -f -i -c 'autoload -Uz compinit ; compinit -D'  0,15s user 0,03s system 90% cpu 0,199 total
# echo 1 > /proc/sys/vm/drop_caches
% time zsh -f -i -c 'autoload -Uz compinit ; compinit'
zsh -f -i -c 'autoload -Uz compinit ; compinit'  0,04s user 0,01s system 76% cpu 0,065 total
% time zsh -f -i -c 'autoload -Uz compinit ; compinit'
zsh -f -i -c 'autoload -Uz compinit ; compinit'  0,05s user 0,00s system 88% cpu 0,057 total
# echo 1 > /proc/sys/vm/drop_caches
% time zsh -f -i -c 'autoload -Uz compinit ; compinit -C'
zsh -f -i -c 'autoload -Uz compinit ; compinit -C'  0,03s user 0,01s system 70% cpu 0,057 total
% time zsh -f -i -c 'autoload -Uz compinit ; compinit -C'
zsh -f -i -c 'autoload -Uz compinit ; compinit -C'  0,03s user 0,01s system 84% cpu 0,047 total

: 447 мс вообще без кэша zsh и ФС, 65 мс если нужно только проверить, нет ли новых автодополнений и 57 мс, если ничего проверять не нужно. Во всех случаях меньше, если есть системные кэши ФС. Замечу, что корень у меня в RAID1 с ssd и hdd, так что лежащие там файлы (а файлы автодополнения в основном в /usr/share, что в той же ФС) добываются довольно быстро.

У меня SSD нет, так что дисковый кеш я оставлю в покое. С ним:


% time zsh -f -i -c 'autoload -Uz compinit ; compinit -D'
0.113 real  0.086 user  0.024 sys  6MB RAM

% rm -f ~/.zcompdump*
% time zsh -f -i -c 'autoload -Uz compinit ; compinit'
0.167 real  0.132 user  0.029 sys  6MB RAM
% time zsh -f -i -c 'autoload -Uz compinit ; compinit'
0.026 real  0.018 user  0.007 sys  6MB RAM

% time zsh -f -i -c 'autoload -Uz compinit ; compinit -C'
0.021 real  0.020 user  0.000 sys  6MB RAM

Но ведь кеш compinit можно ещё и откомпилировать, как я упоминал выше!


% zcompile ~/.zcompdump
% time zsh -f -i -c 'autoload -Uz compinit ; compinit'
0.011 real  0.005 user  0.006 sys  6MB RAM
% time zsh -f -i -c 'autoload -Uz compinit ; compinit -C'
0.004 real  0.004 user  0.000 sys  6MB RAM

Вооот! Такие цифры мне нравятся намного больше. Хотя -C в реальной жизни использовать вряд ли получится, вручную за актуальностью следить как-то не хочется.


Update: Размеры:


-rw-r--r-- 1 powerman powerman 40264 апр 25 22:41 .zcompdump
-r--r--r-- 1 powerman powerman 88728 апр 25 22:43 .zcompdump.zwc

Оказалось, вышел antigen 2.0, теперь тот же самый конфиг отрабатывает за 180 мс, в начале было около 1000 мс, такая скорость меня полностью устраивает, всем спасибо!

вот чудеса — на двух маках стоит zsh и mc, как файл менеджер.
на одном mc запускается правильно, на втором запускает внутри себя bash
конфиги zsh и mc между компами синхронятся.
не могу понять, куда копать.

Подозреваю, что конфиги zsh и mc тут ни при чём, просто у одного пользователя в passwd оболочка zsh, а у другого — bash. Если это так (т.е. если mc берёт оболочку именно оттуда), то вам нужно использовать chsh. Ещё посмотрите, что находится в $SHELL в обоих случаях.

хм, chsh — полностью решило проблему. спасибо!
Sign up to leave a comment.

Articles