Чтобы перейти с bash на zsh необходимо знать базовые отличия между ними — без этого будет сложно провести первоначальную настройку zsh в ~/.zshrc.


Я не нашёл краткого описания этих отличий когда переходил сам, и мне пришлось потратить немало времени на вычитывание документации zsh. Надеюсь, эта статья упростит вам переход на zsh.


Зачем переходить


Для начала — а стоит ли вообще тратить своё время и внимание на переход? Учить ещё один диалект sh, менее распространённый чем POSIX sh или bash, заново заниматься настройкой рабочего окружения…


На мой взгляд, если вы проводите много времени в консоли, вам нравятся Vim или Emacs и вы уже потратили немало времени на их настройку "под себя" — однозначно стоит! Zsh по духу очень на них похожа: это очень сложная и гибкая программа, чьи возможности полностью мало кто знает, но потратив некоторое время на настройку можно получить очень удобную лично вам рабочую среду.


Что касается изучения нового диалекта sh… пользы от этого, скорее всего, действительно мало, но описанного в этой статье минимума должно быть достаточно чтобы настраивать zsh, а писать новые скрипты на диалекте zsh вам никто и не предлагает. В общем и целом это ничем не отличается от необходимости минимально знать VimL или Emacs Lisp исключительно для настройки Vim/Emacs.


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


  • Zsh не использует readline для ввода команд пользователем. Вместо этого используется собственный редактор ZLE (Zsh Line Editor). Это позволило реализовать множество фич: удобное редактирование многострочных команд, подсветку синтаксиса прямо в процессе ввода команды, особую обработку "paste" из clipboard чтобы не выполнить случайно вставленный текст, гибкое управление горячими клавишами, undo (в т.ч. отменяющее результат автодополнения и разворачивания glob-ов)… плюс интегрировать функционал редактора с zsh, что позволяет управлять его поведением через обычные функции zsh (например, подсветка синтаксиса так и реализована).
  • Невероятно сложный и гибкий механизм автодополнения команд. Он сильно зависит от контекста, поэтому при нажатии <Tab> в разных местах командной строки будут дополняться разные вещи: имена команд, их параметры, файлы, имена пользователей и серверов, номера процессов, названия переменных, индексы массивов и ключи хешей, элементы синтаксиса zsh, названия цветов и шрифтов, сетевых интерфейсов, системных пакетов… короче, вообще всего что можно автодополнять. И его можно детально контролировать, вплоть до изменения логики автодополнения для конкретного контекста у конкретной команды.
  • Громадное количество (177 в zsh-5.2) опций, изменяющих поведение zsh. С их помощью можно, например, изменять поддерживаемый синтаксис и включать (в т.ч. частично) режимы совместимости с sh/bash/ksh/csh. Они позволяют настолько значительно влиять на работу, что в zsh пришлось сделать отдельный "режим совместимости с zsh", который многие функции обычно включают первой командой, потому что только это даёт им гарантию, что код этой функции будет понят zsh именно так, как ожидал его автор.
  • Предпочтение максимально сжатого, краткого синтаксиса — чтобы вам нужно было набирать как можно меньше текста для выполнения типичных, пусть даже довольно сложных, задач. В коде, где важна читабельность через месяц — это однозначно минус. Но в командной строке — однозначно плюс.
  • Модульная организация настроек через фреймворки (вроде oh-my-zsh и prezto), плагины, темы, etc. На самом деле здесь нет ничего специфичного для zsh, ровно то же самое можно сделать и для bash, но… почему-то для zsh всё это уже есть, а для bash — нет (а если и есть, то про это мало кто знает). А это даёт возможность относительно быстро собрать свой вариант настроек zsh из готовых "кубиков" (как пример, посмотрите видео менеджера плагинов zsh Аntigen), точно так же, как обвешивается плагинами Vim.

Отличия и совместимость


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


Термины


  • Параметр: обычная переменная — скаляр (строка, целое, дробное), массив, ассоциативный массив (хеш). А переменными называют в основном переменные окружения, т.е. экспортированные скалярные параметры.
  • Аргумент: параметр (в традиционном смысле) вызываемой команды или функции (аргументы функции доступны через параметры $@, $1, …).
  • Шаблон: глоб. Как правило шаблоны подразумевают совпадение с реально существующими файлами, но в некоторых случаях они применяются к строке или значению параметра. Поддержка полноценных регулярок тоже есть, но в основном везде в качестве шаблонов для совпадения или поиска/замены используются глобы.
  • Флаги: задаются в круглых скобках перед тем, на что они должны влиять. Для параметров задаются между открывающей фигурной скобкой и именем параметра: ${(kv@)some_hash}. Для шаблонов могут быть в начале или середине: *CaseImportant(#i)CaseIgnored*.txt.
  • Квалификаторы: задаются в круглых скобках после шаблона, уточняя его свойствами не связанными с именем файла: *(/^F).
  • Модификаторы: задаются каждый после двоеточия, применяются по очереди изменяя текущее значение. Для параметров задаются после имени параметра: $PWD:h:t, ${some_param:h:t}. Для шаблонов задаются перед закрывающей круглой скобкой квалификаторов: *(:e).

Текущие настройки


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


# текущие опции
setopt
# полный список всех опций
setopt KSH_OPTION_PRINT; setopt

# список обрабатываемых кнопок в текущем режиме
bindkey
# список обрабатываемых кнопок во всех режимах, в формате команд zsh
for m in $(bindkey -l); bindkey -M $m -L

# текущие стили (контекстно-зависимые настройки)
zstyle
zstyle -L

# текущие алиасы (обычные плюс глобальные), в формате команд zsh
alias -L
# текущие алиасы для суффиксов, в формате команд zsh
alias -s -L

# текущие параметры (переменные)
typeset
# текущие параметры (переменные), в формате команд zsh
typeset -p

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


Ещё может быть полезным запуск zsh -f — это запускает zsh в состоянии по умолчанию (без выполнения любых стартовых скриптов кроме /etc/zshenv, которого в большинстве систем и так нет).


setopt и emulate


  • В именах опций регистр и подчёркивания значения не имеют, плюс перед любой опцией можно добавить префикс "no".
  • Вызов для одной и той же опции setopt с префиксом "no" и unsetopt без "no" (равно как и наоборот!) делают одно и то же.
  • В выводе setopt используются маленькие буквы без подчёркиваний, в документации используются большие буквы с подчёркиваниями. Это создаёт некоторое неудобство — при поиске в документации нужно догадаться, где вставлять подчёркивания чтобы найти нужную опцию.
  • Команда emulate позволяет массово установить группу опций в состояние совместимости с sh, ksh, csh или в состояние по умолчанию для zsh. Многие функции в zsh начинаются командой emulate -L zsh, что позволяет на время выполнения функции привести ключевые опции в состояние по умолчанию для zsh — без этого большинство нетривиальных функций может ломаться из-за выставленных пользователем опций (например, есть опция которая управляет тем, как индексируются массивы — от 1 или от 0).

# все эти команды делают одно и то же
setopt nonumericglobsort
setopt NO_numericglobsort
setopt NO_NUMERIC_GLOB_SORT
setopt _N_O_numERICglob_SORT_
unsetopt NUMERIC_GLOB_SORT
unsetopt numericglobsort

В начале использования zsh, для более привычной работы после bash, я бы рекомендовал следующие опции:


# традиционный стиль перенаправлений fd
unsetopt MULTIOS
# поддержка ~… и file completion после = в аргументах
setopt MAGIC_EQUAL_SUBST
# не обрабатывать escape sequence в echo без -e
setopt BSD_ECHO
# поддержка комментариев в командной строке
setopt INTERACTIVE_COMMENTS
# поддержка $(cmd) в $PS1 etc.
setopt PROMPT_SUBST

Ещё есть опция SH_WORD_SPLIT, и формально для привычной работы после bash её тоже надо включить, но я бы этого не рекомендовал: поведение zsh без этой опции более удобное и логичное, лучше сразу к нему привыкать. Она отвечает за то, как сработает cmd $PARAM если значение $PARAM это строка содержащая пробелы: в bash cmd получит несколько аргументов, а в zsh — один (как если бы вызвали cmd "$PARAM"). А если $PARAM это массив, то zsh передаст cmd по одному аргументу на каждый не пустой элемент массива (даже если эти элементы содержат пробелы).


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


Параметры


  • Соглашение: для имён скалярных параметров (строки, целые и дробные числа) обычно используют $БОЛЬШИЕ буквы, а для массивов (обычных и ассоциативных) — $маленькие.
  • Через typeset -U можно объявить массив с уникальными элементами (попытки добавления уже существующих элементов будут игнорироваться).
  • Через typeset -T можно связать массив со скаляром в формате $PATH. Несколько таких связанных параметров уже созданы: $PATH и $path, $FPATH и $fpath, $MANPATH и $manpath, $CDPATH и $cdpath. Для связанных параметров не имеет значения какой из них мы изменяем — изменяются сразу оба. Поэтому в zsh с такими параметрами практически всегда работают через массивы ($path, $fpath, …) — это значительно удобнее.
  • Некоторые скалярные параметры так же связаны между собой, например $PS1, $PROMPT и $prompt (хотя, это скорее просто синонимы для одного параметра).

Массивы


  • Индексируются с 1.
  • Можно использовать отрицательные индексы (от конца массива).
  • Можно использовать срезы.
  • При использовании как скаляра — объединяют элементы через пробел.
  • Индексирование скаляра возвращает символы строки.
  • Глоб возвращает массив, так что индекс можно использовать как квалификатор глоба: *([2,-2]).

Шаблоны


  • **/ — совпадает с подкаталогом любого уровня вложенности, включая отсутствие подкаталога
  • <число1-число2> — совпадает с числом в заданном диапазоне в имени файла, и начало и конец диапазона можно не указывать
  • (шаблон1|шаблон2) — альтернатива (так же — группирующие скобки при использовании опции EXTENDED_GLOB)
  • если включить опцию EXTENDED_GLOB, то в шаблонах можно будет дополнительно использовать # (повтор предыдущего элемента), ~ и ^ (исключение из совпадения)

# показать файлы в текущем каталоге или его подкаталогах,
# которые содержат в имени число большее или равное 5 либо строку example,
# и у которых расширение .txt
ls -l **/*(<5->|example)*.txt

Флаги/Квалификаторы/Модификаторы


Квалификаторы есть только у шаблонов, они позволяют задать дополнительные условия отбора файла: по типу (файл/каталог/симлинк/etc.), правам, времени (изменения/etc.), размеру… Можно сортировать и индексировать отобранные файлы. Можно включить для конкретно этого шаблона совпадение начальной * с именами начинающимися на точку. Можно включить удаление этого шаблона из аргументов командной строки если он не совпал ни с одним файлом.


# до 5-ти подкаталогов текущего каталога,
# имена которых могут начинаться на точку и содержат "a",
# которые изменялись последними
ls -ld *a*(D/om[1,5])

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


# эти команды идентичны
ls -ld .[cC][oO][nN][fF][iI][gG]*
setopt extendedglob; ls -ld .(#i)Config*

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


# вывод ключей ассоциативного массива вместо значений
echo ${(k)some_hash}
# преобразовать $PATH в массив разделив на элементы по ":",
# после чего корректно взять каждый элемент в одинарные кавычки
echo ${(s<:>qq)PATH}

И для шаблонов и для параметров можно использовать модификаторы: удаление последнего элемента пути, удаление всех элементов пути кроме последнего, удалить/оставить расширение, экранирование и обратная операция, поиск и замена подстроки, etc.


# вывод имени родительского каталога (сначала отбрасываем последний
# элемент пути, потом отбрасываем все элементы пути кроме последнего)
echo $PWD:h:t
# вывести имена (без каталога) всех симлинков в любом подкаталоге,
# заменив в них подстроку "fil" на "FIL" (если такая подстрока есть)
echo **/*(@:t:s/fil/FIL/)

autoload -Uz


Помимо традиционного способа подгружать код через source /path/to/file.sh или . /path/to/file.sh в zsh активно используется автозагрузка кода в момент первого вызова функции.


Для поиска файла с нужной функцией используется $FPATH — переменная аналогичная по формату $PATH, содержащая список каталогов в которых выполняется поиск файла с именем, идентичным имени загружаемой функции.


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


fpath=(~/my-zsh-functions $fpath)
autoload -Uz fn
fn

При этом содержимое файла ~/my-zsh-functions/fn может быть в одном из этих трёх форматов:


# Просто набор команд, без каких-либо функций:
echo "Я функция fn"

# Одна функция с именем совпадающим с именем файла:
fn() {
    echo "Я функция fn"
}

# Набор из любых команд и функций, включая fn:
fn() {
    fn2
}
fn2() {
    echo "Я хелпер функции fn"
}
echo "Выполнится перед первым запуском fn"
# Но файл должен содержать явный вызов fn:
fn "$@"
echo "Выполнится после первого запуска fn"

zkbd


При первом запуске zsh нередко оказывается, что часть кнопок вроде F1/Backspace/Delete/курсора работает некорректно. Это связано с тем, что абсолютное большинство консольных приложений использует readline и корректная настройка этих кнопок считывается из /etc/inputrc и ~/.inputrc, а zsh этого не делает.


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


bindkey '^[[A' up-line-or-history       # Up
bindkey '^[[B' down-line-or-history     # Down
# и т.д.

Смотреть выдаваемые кнопками последовательности можно запустив cat >/dev/null и нажимая Ctrl-V перед нужной кнопкой. (И таки да, занимаясь этим в 2017 я чувствовал себя немного странно…) Но в комплекте с zsh идёт вспомогательная утилита zkbd, которая автоматизирует этот процесс. Для этого необходимо подключить её в ~/.zshrc, после чего у вас появится ассоциативный массив $key содержащий нужные escape-последовательности:


autoload -Uz zkbd
[[ ! -f ~/.zkbd/$TERM-${${DISPLAY:t}:-$VENDOR-$OSTYPE} ]] && zkbd
source  ~/.zkbd/$TERM-${${DISPLAY:t}:-$VENDOR-$OSTYPE}

[[ -n $key[Up]   ]] && bindkey -- $key[Up]   up-line-or-history
[[ -n $key[Down] ]] && bindkey -- $key[Down] down-line-or-history
# и т.д.

Я не уточняю детально какие команды (вроде up-line-or-history) на какие кнопки назначать потому, что во-первых назначать надо не все подряд, а только те, которые у вас из коробки не заработают, и во-вторых если мнения насчёт того, что должны делать Home или Backspace у всех сходятся, то вот поиск в истории по Up и Down может выполняться довольно разными способами, и функции в этих случаях на эти кнопки надо назначать тоже разные.


(Кстати, задавать символ Escape (^[) в параметре bindkey можно и настоящим символом, вводя его через Ctrl-V, и двумя обычными символами ^[, и двумя символами \e.)


zstyle


Это встроенный способ использовать контекстно-зависимые настройки. Он во многом похож на обычные параметры, только помимо имени и значения параметра zstyle позволяет задать шаблон "контекста". А потом получать значения относящиеся к текущему контексту. Этот подход активно используется для настройки работы автодополнений, но им можно пользоваться и для своих скриптов.


# установим значение my-param=default для 3-х уровневого контекста,
# где на первом уровне идентификатор нашего приложения (у всех
# приложений общая база zstyle, так что свои настройки надо изолировать)
# а на следующих двух уровнях любые значения
% zstyle ':my-app:*:*' my-param default
# установим значение my-param=val-one для контекста, у которого на
# втором (более приоритетном) уровне будет значение "one"
% zstyle ':my-app:one:*' my-param val-one
# установим значение my-param=val-two для контекста, у которого на
# третьем (менее приоритетном) уровне будет значение "two"
% zstyle ':my-app:*:two' my-param val-two

# получаем значение my-param в переменную result для заданного контекста
% zstyle -s ':my-app:a:b' my-param result
% echo $result
default
% zstyle -s ':my-app:one:b' my-param result
% echo $result
val-one
% zstyle -s ':my-app:a:two' my-param result
% echo $result
val-two
% zstyle -s ':my-app:one:two' my-param result
% echo $result
val-one

zmodload


Часть дополнительного функционала zsh реализована не в обычных скриптах подгружаемых через autoload -Uz, а как системные библиотеки *.so. Они используются, например, для предоставления доступа к регулярным выражениям PCRE, математическим функциям, сокетам, etc. Такие библиотеки подгружаются через zmodload.


Разное


Для перехвата сигналов помимо стандартного trap '…;code;…' INT можно использовать функции с особыми именами: TRAPINT() { …;code;… }.


У многих конструкций вроде if, while, etc. есть сокращённая форма (пример есть выше, где выводилось значение всех режимов bindkey).


Внезапно, zsh-специфичный аналог echo — команда print — оказалась весьма удобной при изучении zsh. Она много чего умеет, но из самого полезного:


# вывод по одному аргументу на строку, удобно для массивов
print -l $path
# вывод по два аргумента на строку в столбцах,
# удобно для ключей и значений ассоциативных массивов
print -a -C 2 "${(kv@)ZSH_HIGHLIGHT_STYLES}" | sort
# вывод используя %-последовательности используемые в $PS1
print -P '%Bbold%b %F{red}current%f dir is: %~'

Если Когда решитесь переходить на zsh, то для принятия конкретных решений про фреймворки/модули/темы вам пригодится Awesome-коллекция всего для zsh.

Использование zsh

Проголосовало 433 человека. Воздержалось 86 человек.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Поделиться с друзьями
-->

Комментарии (109)


  1. immaculate
    15.04.2017 19:26
    +1

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


    1. n-name
      15.04.2017 22:20

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


      1. Erelecano
        15.04.2017 22:27
        +5

        shopt -s histappend
        PROMPT_COMMAND='history -a'
        В ~/.bashrc говорят, что вы помните неправильно.
        В комментариях к каждой статья про zsh повторяется чушь про башхистори, типа вашей.


      1. zim32
        15.04.2017 23:26
        -1

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


    1. karl
      18.04.2017 13:00

      прям вообще не сбрасывается?


  1. ZoomLS
    15.04.2017 21:31
    +2

    Давно перешёл на zsh, но использую всё так же, как раньше bash. Т.е. никакими фирменными фичами так и не пользуюсь. Установил только Oh My Zsh и выбрал шаблон по вкусу :)
    Ещё заметил, что bash всегда стартует почти мгновенно, а zsh с небольшой задержкой.


    1. anton44eg
      15.04.2017 22:31
      +4

      Думаю это десятки плагинов Oh My Zsh у вас стартуют


      1. ZoomLS
        16.04.2017 01:44

        Скорее всего.


    1. twentyfivesymbolsusername
      16.04.2017 00:18

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


      1. ZoomLS
        16.04.2017 01:18

        У меня NVM тоже стоит, но заметил задержку ещё до установки NVM.


  1. vvpoloskin
    15.04.2017 22:12
    +4

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

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

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


    1. powerman
      15.04.2017 22:36

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

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


    1. raacer
      16.04.2017 01:19

      > Кстати, я что-то не встречал ни одного системного администратора, использующего zsh вместо bash на постоянной основе в своей работе

      А я встречал, почему-то


      1. vvpoloskin
        16.04.2017 01:25
        -1

        Сколько промышленных серверов и какого типа (vm, dedicated, embedded) было у этих администраторов в эксплуатации?


        1. raacer
          16.04.2017 01:37
          +1

          Я могу узнать, если Вам интересно. А что значит «промышленных»?


        1. raacer
          16.04.2017 01:43

          И ещё: Вас интересует одномоментная эксплуатация, или за всю историю?


        1. raacer
          16.04.2017 02:04

          Прошу прощения, я напутал. Был уверен, что zsh, а оказалось — какой-то форк ksh, да ещё и далеко не на всех серверах. Жаль, что нельзя теперь удалить своё сообщение. :(


          1. vvpoloskin
            16.04.2017 02:27
            +1

            Вот и я говорю, что такого нет. Под пром серверами имею в виду production


            1. khim
              16.04.2017 13:44

              Собственно в вашем вопросе — половина ответа. Zsh хорош, когда вы можете подстроить его под себя, а когда от половины до трех четвертей времени ты проводишь на серверах, где zsh просто нет и/или подстроить его под себя нельзя (например там один пользователь, из-под-которого работают 10 человек), то тебе приходится держать в голове и помнить — где у тебя что.

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


            1. acmnu
              17.04.2017 11:57
              +1

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


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


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


              1. powerman
                17.04.2017 12:13

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

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


                1. acmnu
                  17.04.2017 12:26

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


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


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


                  1. powerman
                    17.04.2017 12:48
                    -1

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


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

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


                    1. acmnu
                      17.04.2017 12:54

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

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


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

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


                      1. powerman
                        17.04.2017 13:20

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

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


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


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

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


                        1. acmnu
                          17.04.2017 13:28

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

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


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

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


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

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


                          1. ZyXI
                            17.04.2017 13:41

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

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


                            1. powerman
                              17.04.2017 14:00

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


                          1. powerman
                            17.04.2017 13:53
                            +1

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


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


                            1. acmnu
                              17.04.2017 14:19

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


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

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


                              1. powerman
                                17.04.2017 15:06

                                Всё верно. :(


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


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


                                1. acmnu
                                  17.04.2017 16:35

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


                                  1. powerman
                                    17.04.2017 17:02

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


                                    1. acmnu
                                      17.04.2017 17:10

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


                    1. acmnu
                      17.04.2017 12:57
                      +2

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

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


  1. apro
    15.04.2017 22:19
    +1

    Меня как сидящего все еще на 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. powerman
      15.04.2017 22:56

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


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


      1. apro
        15.04.2017 23:25
        +1

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

        Да, да и еще раз да. Нафига мне задумываться о том сколько строчек оставить,
        а если для меня будет важна именно 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-последовательностей?


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


        1. powerman
          15.04.2017 23:36
          +3

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


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


          1. apro
            15.04.2017 23:45

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

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


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


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

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


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

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


            1. ZyXI
              15.04.2017 23:50

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

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


            1. powerman
              15.04.2017 23:55
              +2

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


    1. Hissing_Bridge
      17.04.2017 12:09

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


      export HISTSIZE=
      export HISTFILESIZE=

      Тогда не забудьте настроить HISTTIMEFORMAT


      Или настройте logrotate, пусть раз в пол года делает архивы, если вам так нужно. В случае поиска воспользуетесь zgrep, zcat


      1. apro
        17.04.2017 13:30

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

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


  1. maolo
    15.04.2017 22:33

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

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


    1. powerman
      16.04.2017 10:59
      +1

      на моем ноуте zsh тормозит конкретно.

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


      1. maolo
        16.04.2017 14:55

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


        1. powerman
          16.04.2017 15:04

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


          1. maolo
            16.04.2017 15:12

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


            1. powerman
              16.04.2017 16:26

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


      1. olegkrasnov
        16.04.2017 21:00

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


  1. vaniaPooh
    15.04.2017 22:37
    +1

    Если у вас 1000 серверов и везде стоит обычный bash, то какой смысл ставить себе zsh локально? Я не перехожу на zsh в том числе и по этой причине.


    1. powerman
      15.04.2017 22:59
      +1

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


      1. acmnu
        17.04.2017 12:40

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

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


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


        1. powerman
          17.04.2017 12:57

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


          1. acmnu
            17.04.2017 13:08

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


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


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


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


            1. powerman
              17.04.2017 13:25

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


              1. acmnu
                17.04.2017 13:30

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


  1. conformist
    15.04.2017 22:43
    +4

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


    1. vvpoloskin
      15.04.2017 23:00
      +2

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


      1. conformist
        15.04.2017 23:20

        продвинутые парни используют vim/emacs mode для bash

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

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

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


        1. vvpoloskin
          16.04.2017 00:35
          +1

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


      1. ZyXI
        15.04.2017 23:42

        Какая ещё подсветка синтаксиса в 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 такого временного модификатора всё равно нет.


        1. vvpoloskin
          16.04.2017 01:21
          -1

          Я не пытался сделать какие-то претензии к 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 должен работать быстро везде (за исключением машин в Австралии или подключенных через спутниковый канал=), если появляется лишняя непредсказуемая задержка — она уже сама наводит панику, что какую-то команду я ввел зря.


          1. powerman
            16.04.2017 10:17

            Я не пытался сделать какие-то претензии к 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"


    1. powerman
      15.04.2017 23:24
      +1

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


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


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


      1. apro
        15.04.2017 23:34

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

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


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

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


        1. powerman
          15.04.2017 23:45

          И что? Такой 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 — не сложно.


      1. conformist
        15.04.2017 23:38
        +1

        вставка из 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, тем более, что киллер-фич не особо густо, на самом деле.


        1. powerman
          16.04.2017 10:33

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


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

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


      1. Ghedeon
        16.04.2017 18:25

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

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


        1. powerman
          16.04.2017 19:14

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


  1. Pilat
    16.04.2017 04:46

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


    1. SibProgrammer
      16.04.2017 07:06

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


  1. SibProgrammer
    16.04.2017 06:46

    В правильной статье про zsh должны быть скриншоты/гифки с демонстрацией того, как это работает.


  1. tilyupo
    16.04.2017 08:40

    Спасибо за статью!


  1. Kesha3
    16.04.2017 08:40

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


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


    1. powerman
      16.04.2017 10:51

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


      1. Kesha3
        16.04.2017 13:17

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

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


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

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


  1. Kesha3
    16.04.2017 13:15

    del


  1. Crandel
    16.04.2017 13:24
    +1

    Спасибо за интересную статью и очень интересные комментарии к ней.
    Более 2 лет пользуюсь fish shell дома и на рабочем ноуте, ну а баш на удаленных серверах.
    К фишу привык, его почти не нужно настраивать, но так как он почти совсем не совместим с баш/сш то посматриваю в сторону zsh.
    Если вдруг кому интересны мои настройки, то они располагаются на github
    Ну а вот как выглядит конечный результат(fish — зеленые часы и стрелочка, bash — голубые, zsh — желтые)
    image


    1. Crandel
      16.04.2017 13:30

      Блин забыл картинку под спойлер засунуть, простите


  1. Ghedeon
    16.04.2017 18:33

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

    Пример
    image


    1. powerman
      16.04.2017 19:12

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


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


  1. kolu4iy
    16.04.2017 21:50

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


    1. kvaps
      17.04.2017 02:10
      +2

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


      1. Stanislavvv
        17.04.2017 09:33
        +1

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

        На локалхосте или сервере, где ты _единственный_, кто туда ходит — без проблем, хоть sh, хоть tcsh, хоть zsh. В случае сервера, куда рутом ходят только в случае проблем, zsh с чужими настройками — помеха, а не помощь.


      1. kolu4iy
        17.04.2017 11:23

        Соглашусь с предыдущим оратором. У меня есть домашняя рабочая станция, есть рабочая. А есть несколько десятков серверов, куда я никакие dotfiles тащить не буду ни в коем случае.
        Посыл был именно в том, что мне не надо привыкать ни к чему — везде одна среда.


        1. kolu4iy
          17.04.2017 11:28

          и да, dotfiles и прочие плюшки home-каталога у меня ездят между рабочими станциями. Потому что это моё, и если что-то пойдёт не так, то это мои личные проблемы, а не проблемы моего работодателя.


  1. Hissing_Bridge
    17.04.2017 09:34

    Имхо, не могу представить реальную необходимость в переходе на zsh.
    Ну да, есть прикольные фишки, интерактивные подсветки, расширенные автодополнения по аргументам комманд и прочее. Но есть ли в этом реальная необходимость? Я думаю — нет.
    Вот один из аргументов почему:
    По долгу работы, да и вне ее, провожу большую часть времени в консоле. Многие недооценивают возможности bash, как мне кажется, по навигации, дополнению, истории и пр.
    Не было у меня еще в реальной жизни задачи, с которой бы не справился bash или bash был бы не удобен. А человеки ставят zsh только потому, что это больше по-гиковски, нежели из-за реальной необходимости, имхо. Во всяком случаи вот такие статьи и аналогичные на хабре, только лишний раз это подтверждают. Ну не нужны все эти красивости в реальной работе, не нужны).
    Все аргументы команд, которые более-менее часто используется, наберется около двух сотен. Все их аргументы, лично я, знаю. Даже не так, знаю, конечно, наизусть далеко не все, но подавляющее большинство, которые мне реально необходимы в работе, знаю.
    Ведь реальная работа в консоле, сводится к чаще всего однообразным действиям, с одинаковыми ключами, типа ps aux или du -h --max-depth=1 | sort -rh
    утрированно, но все же. Большинство из висят на альясы или написаны нужные мне функции.
    И все эти красивости, в виде подсказки в виде 38 различных флагов ls или весь список параметров netstat, ну реально, это так действительно необходимо?
    Ну надо что-то мне вспомнить: ctrl+| (открывает сплит в терминале справа), man netstat, /search_string, q, ctrl-d.
    Отрывать руки от клавиатуры на мышку? Да нет, конечно. Даже по навигации в текущей строке — никаких стрелочек, как и для истории. Надо написать длинную команду — Ctrl-x Ctrl-e и я в родном vim. Все это функционал bash.
    Это лишь частный пример, по многим другим пунктам аргументы будут аналогичные.
    Я пользовался zsh около года, печеритал толстенную доку по нему, перечитал большинство статей на хабре, но так и не понял, зачем он мне вместо баша. Безусловно, zsh функционален, красив и вообще как-то по-гиковски. Но нужен ли он в реальном использовании? Мое мнение, что для большинства даже матерых линуксоидов — нет. При должном освоение даже функционала bash-а за глаза.


    1. Hissing_Bridge
      17.04.2017 09:48

      Плюшки по сохранению вводимой команды, чтобы не потерять ее в bash — Esc+#, да не буду я тут всего перечислять, просто комментарии читаю, вижу что просто не достаточно народ возможности bash знает.
      Синтаксический сахар zsh — ну прикольно, реально необходимо — совершенно нет.
      Прыжки по истории каталогов — pushd, popd, dirs, пусть это не настолько удобно как стрелочками листать каталоги, но и не нужно это).
      Скрипты на zsh в практическом применении не переносимы, из-за отсутствия по-умолчанию в большинстве дистрибутивов этого шела.
      В общем это развлекуха, а большинство красивостей и удобств есть в bash, быстрей переход по каталогам, insensitive-case, небольшие опечатки — все это можно включить.
      Зато это единое окружение, которое присутствует везде. И вы не останетесь без своих няшек, когда зайдете на удаленный сервер, где по миллионам причин нет необходимости/разрешения устанавливать дополнительные шелы чтобы вам было удобнее.


    1. powerman
      17.04.2017 10:10
      +1

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


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


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


      1. Hissing_Bridge
        17.04.2017 10:22

        Ну не правы вы. Упускаете своло реальной необходимости. Что такое реальная необходимость: есть инструмент и он не справляется со своими задачами. Вы считаете что я в своем настроенном шеле менее продуктивен чем вы? А что вы под продуктивностью понимате? Быстрее сделать то, что смогу сделать я? Напечатать укороченную конструкцию или написать конвеер с командами и их аргументами? Ну тут я бы с вами поспорил. А может вы набираете со скоростью в трое ниже чем я. Тогда кто будет продуктивней? А руку в сторону стрелочек снимаете при навигации? Тоже время тратите. Это все очень субъективно. Я лишь высказал свое мнение, на основе достаточно длительного опыта, что в реальном использовании bash не менее продуктивен, точнее так: не настолько менее продуктивен, чтобы ради этого переходить на не дефолтный шел, изучать новый диалект и просто тонну документации по функционалу zsh и еще столько же по кучи плагинов.


        1. powerman
          17.04.2017 11:26
          +2

          … в реальном использовании 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 по умолчанию, просто из вежливости к коллегам) надо нам самим.


          1. Hissing_Bridge
            17.04.2017 11:48

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


      1. Hissing_Bridge
        17.04.2017 10:46

        Почти всегда мне не нужно видеть все флаги. Нужно только в случае, когда я что-то ищу, не знаю или забыл.
        Я сидел на zsh, в чем то вы правы по поводу "находишь что-то новое". Но я нахожу что-то новое, когда целенаправленно читаю man, --help или apropos, что делаю достаточно часто. А когда я начинал осваивать linux, то после какого-то времени, когда уже более-менее ориентировался в консоле, просто дополнял все команды на буквы алфавита, типа a[tab][tab] и по порядку узнавал что есть что. Со временем пробелы заполнялись. Я не могу сказать, что я знаю все команды, да и вряд ли это необходимо. Но не аргумент совсем, что видеть список всех флагов, позволяет открывать для себя что-то новое. Это все зависит от заинтересованности человека. Если человеку это не нужно, он и смотреть этого не будет.
        Да и может вы давно автокомплит bash не видели?
        http://i.imgur.com/P15CrxU.png


        1. Crandel
          17.04.2017 11:00

          И что этот автокомплит показывает? Что то я не вижу флагов, вот для сравнения zsh


          Заголовок спойлера

          image


          1. Hissing_Bridge
            17.04.2017 11:14
            -1

            Да видел все это я). И зачем мне это каждый раз видеть вообще? Серьезно. Если для конкретной ситуации мне нужно применить какую-то опцию, да я сделаю --help. Это случается крайне редко. Большинство параметров к регулярно используемым утилитам я знаю и смогу набрать, даже в отсутствии автокомплита.
            Я не пытаюсь вас переубедить, лишь высказал свои мысли по этому поводу. Проработав год в zsh, я пришел к выводу, что его функционал более чем избыточен для меня, хотя консоль — мой родной уголок, в котором провожу много времени.
            Возможно, если кто-то объективно посмотрит на тот функционал, которым реально пользуется и много ли профита с него — придет к таким же выводам.


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


            1. Crandel
              17.04.2017 11:23

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


              1. Hissing_Bridge
                17.04.2017 11:31

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


                Вот вам не нужен zsh, так зачем комментировать и читать статьи про него?

                Тут вообще-то пытаются народ убедить, что стоит переходить на zsh, я высказал свою точку зрения. Может быть кто-нибудь прочтет, да задумается, нужно вообще это ему или нет.


                И не говорите мне, что вы никогда не ошибаетесь, идеальных людей не существует

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


                1. Crandel
                  17.04.2017 12:29

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


  1. Galangetan
    20.04.2017 16:08

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


    1. powerman
      20.04.2017 16:12

      Об этом упомянуто и в статье и в комментах, но при желании это делается и для bash (точнее, для urxvt — плагин confirm-paste плюс http://lists.schmorp.de/pipermail/rxvt-unicode/2017q1/002360.html).


  1. popstas
    24.04.2017 00:14
    +1

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


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


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


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


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


    1. powerman
      24.04.2017 03:01
      +1

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

      Если Вы про время старта 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, ну и разная мелочь в количествах).


      1. popstas
        24.04.2017 21:48

        Спасибо, подебажил свой конфиг (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 секунды.


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


        1. powerman
          24.04.2017 22:50

          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


        1. powerman
          24.04.2017 23:02

          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), но не настолько же.


          1. ZyXI
            24.04.2017 23:55

            Нет, это не пустой. Без -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: если ошибусь, её попортит).