Learning Platform
Глоссарий Troubleshooting
Урок 04.02 · 18 мин
Начальный
BashZshFishShellScripting

Bash vs Zsh vs Fish: какой shell выбрать

В прошлом уроке мы установили, что shell — это программа-интерпретатор, и их несколько на выбор. Сегодня — детальное сравнение трёх главных вариантов на 2026 год: Bash 5.3, Zsh (с oh-my-zsh) и Fish 4. Цель — понять, какой выбрать для интерактивной работы, а на каком писать скрипты.

Спойлер: на чём писать скрипты — на Bash (везде работают). Что использовать interactive — выбор зависит от вкуса.


Bash 5.3 — стандарт де-факто

Bash (Bourne Again SHell) — это GNU-реализация Bourne Shell, написанная Brian Fox в 1989. С тех пор развивается командой GNU. Последний крупный релиз — bash 5.3 (июль 2025).

Bash: ключевые факты
POSIXBash совместим с POSIX-стандартом + добавляет много extensions. Скрипты, написанные на чистом POSIX, будут работать в любом POSIX-shell (dash, sh, ksh)
РаспространениеСтоит почти везде: Linux серверы, Docker базовые образы, macOS (но старый), WSL2. Если знаете bash — работаете на любой Unix-системе
Документацияman bash — 5000+ строк. Огромная экосистема Stack Overflow, книг, скриптов. Любая проблема имеет решение в Google
СкриптыВсе системные скрипты — bash. Большинство open-source проектов — bash. Если пишете cli-утилиту в bash — она запустится у каждого
Interactive UXИз коробки — простой prompt, базовая история, базовый Tab-complete. По умолчанию выглядит 'старым'. Можно прокачать конфигом
СкоростьНе самый быстрый shell, но достаточно. На больших loop'ах (10000+ итераций) заметно медленнее compiled-кода

Что нового в bash 5.3 (июль 2025):

  • Улучшенная производительность [[ ... ]] тестов;
  • Новая встроенная команда wait -n с улучшенной обработкой сигналов;
  • Поддержка BASH_REMATCH для multi-line regex;
  • Множество мелких bugfix-ов в read, printf, mapfile.

На большинстве Ubuntu 26.04 и Debian 13 у вас будет именно bash 5.3. На macOS системный bash — всё ещё 3.2 (2007 год!), нужно ставить через brew.

$ bash --version
GNU bash, version 5.3.0(1)-release (x86_64-pc-linux-gnu)

Zsh — bash на стероидах

Zsh (Z Shell) появился в 1990, активно развивается. Главная идея: совместимость с bash + улучшения. Большинство bash-скриптов работают в zsh без изменений. Но zsh даёт больше для интерактивной работы.

Чем zsh лучше bash для interactive
Tab-completionzsh имеет programmable completion 'из коробки' для тысяч команд (git, kubectl, docker, npm). bash требует установки bash-completion пакета, и работает хуже
Globbing**/foo — рекурсивный glob, foo(.) — только файлы, foo(*) — только исполняемые. bash для этого требует shopt -s globstar
HistoryИстория shared между сессиями, лучше дедупликация, fuzzy-search прямо в shell. bash требует настройки и плагинов
Themesoh-my-zsh + Powerlevel10k = красивый prompt с git-инфой, Python venv, kubectl context. Из коробки в zsh поддержка модульного prompt
Pluginsoh-my-zsh — фреймворк с сотнями плагинов: auto-suggestions, syntax highlighting, aliases для git/docker/kubectl. Огромная экосистема
Совместимость95% bash-скриптов работают в zsh без правок. Но есть подводные камни: word splitting, array indexing с 1 (а не 0)

Главный фреймворк для zsh — oh-my-zsh. Это open-source проект, который добавляет zsh:

  • 300+ плагинов (git, docker, kubectl, python venv, autosuggestions);
  • 100+ тем (от минималистичных до с цветами и иконками);
  • Удобная установка и обновление.
# Установка oh-my-zsh
$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

После установки настройка идёт через ~/.zshrc. Плагины — добавление имён в строку plugins=(git docker).

Лучшая тема для DE — Powerlevel10k. Показывает в prompt: ветку git, статус (clean/dirty), Python venv, k8s context, время выполнения предыдущей команды. Настраивается интерактивным wizard за 2 минуты.

TIP

Современная альтернатива oh-my-zsh — starship. Это prompt, написанный на Rust, кросс-shell (работает в bash, zsh, fish, nushell), супер-быстрый. Все DE-фичи (git, kube, venv) — из коробки. Один config (~/.config/starship.toml) переносится между машинами. Многие сейчас переходят на starship: oh-my-zsh для совместимости, prompt от starship.


Fish — friendly out of the box

Fish (Friendly Interactive SHell) — это третий путь. Главная философия: «должно работать из коробки, без часовой настройки». Никаких oh-my-fish (хотя есть), всё уже встроено.

Что fish даёт без настройки
AutosuggestionsПри наборе команды fish показывает серым предлагаемое продолжение из истории. Right-arrow принимает. Этого нет в bash/zsh из коробки
Syntax highlightingВ реальном времени: команда красная если не найдена, опции голубые, аргументы белые. В bash требует плагинов
Tab-completionИз коробки работает для тысяч команд, парсит man-страницы для опций. Реально лучше zsh
Веб-конфиг`fish_config` запускает локальный веб-сервер с UI для настройки темы, prompt, alias. Уникально для shell
НЕ POSIXГЛАВНЫЙ МИНУС: другой синтаксис. `for i in 1 2 3; do ... done` (bash) vs `for i in 1 2 3 ... end` (fish). Bash-скрипты НЕ работают
СообществоМеньше bash/zsh. Плагинов меньше. Stack Overflow ответов меньше. Иногда приходится самому разбираться

Пример различия синтаксиса:

# Fish: переменные присваиваются через `set`, не `=`
> set name "Alice"
> echo $name
Alice

# bash/zsh
$ name="Alice"
$ echo $name
Alice
# Fish: функции
function greet
    echo "Hello $argv[1]"
end
greet "Bob"

# bash/zsh
greet() {
    echo "Hello $1"
}
greet "Bob"

Если попробуете запустить bash-скрипт в fish — упадёт почти сразу:

> bash -c 'for i in 1 2 3; do echo $i; done'  # работает (это bash под капотом)
> for i in 1 2 3; do echo $i; done             # фатально, fish не понимает синтаксис
fish: Expected end of statement, but found ';'

Что выбрать для DE

Простое правило:

Решение для DE
СкриптыЛюбой production-скрипт пишите на bash. Он есть везде, переносится, документирован, понимается всеми коллегами
InteractiveДля повседневной работы — что нравится. Большинство DE: zsh + oh-my-zsh + starship. Минималисты — bash. Гедонисты — fish
На сервереВ SSH-сессии чаще всего default bash. Учите bash как основной — на сервере не сможете поставить себе zsh

Конкретные рекомендации:

  1. Скрипты — bash. Никогда не пишите production-скрипт на fish (никто кроме вас не запустит). Никогда не пишите на zsh-specific синтаксисе (массивы 1-indexed, word splitting) — на серверах может стоять только bash.
  2. Интерактив на ноуте — что нравится. Зейн-вариант: zsh + starship + autosuggestions + syntax-highlighting плагины. Минималистичный: bash + readline + кастомный PS1.
  3. На сервере в SSH — bash. Не ставьте zsh на каждый сервер, это лишний шум. Привыкайте работать в bash, чтобы на любом сервере чувствовать себя дома.
Git хуки и автоматизация — bash-скрипты в pre-commit

Shebang: какой shell запускает скрипт

Когда вы делаете ./script.sh, ядро не знает, что это shell-скрипт. Оно смотрит на первую строку файла — shebang.

#!/usr/bin/env bash
echo "Hello from bash"

#! (sh-bang) в начале файла говорит ядру: «запусти эту программу и передай ей файл как аргумент». Ядро запускает /usr/bin/env bash script.sh, и bash интерпретирует файл.

Разница между двумя вариантами:

Два варианта shebang — что выбрать
#!/bin/bashПрямой путь к bash. Сработает только если bash в /bin/. На большинстве Linux это так. На macOS — это старый bash 3.2!
#!/usr/bin/env bashЗапускает env, который ищет bash в PATH. Подхватит самую свежую версию (включая /usr/local/bin/bash). Стандарт переносимости

Рекомендация: всегда #!/usr/bin/env bash. Это переносимо. Особенно важно на macOS, где /bin/bash — это древний 3.2, а нормальный bash живёт в /opt/homebrew/bin/bash или /usr/local/bin/bash.

$ cat > /tmp/test.sh <<'EOF'
#!/usr/bin/env bash
echo "Bash version: $BASH_VERSION"
EOF
$ chmod +x /tmp/test.sh
$ /tmp/test.sh
Bash version: 5.3.0(1)-release

Подробнее про chmod и executable bit — в модуле 6.


Что точно НЕ работает между shell

Несколько распространённых граблей:

  1. Массивы. bash: arr=(a b c); echo "${arr[0]}" (0-indexed). zsh: тоже работает, но zsh array по умолчанию 1-indexed (echo $arr[1]). fish: совсем другой синтаксис set arr a b c; echo $arr[1] (1-indexed).

  2. Word splitting. bash: var="a b"; for x in $var — разобьёт на два слова. zsh без setopt SH_WORD_SPLIT — не разобьёт, оставит как одну строку. Это часто ломает скрипты при переносе из bash в zsh.

  3. $(< file). bash и zsh: читает файл целиком. fish: не работает, нужно cat file или read.

  4. local в функциях. bash/zsh: local var=foo. fish: нет concept of local, нужно set -l var foo.

Когда пишете production-скрипт, тестируйте на bash. Когда interactive — пишите что нравится, но осознавайте, что эти команды не перенесутся в shell-скрипт без переписывания.


Попробуй сам

Узнайте, какие shell установлены у вас и сравните:

$ cat /etc/shells
# Список разрешённых shell-ов на вашей системе
/bin/sh
/bin/bash
/usr/bin/bash
/bin/zsh
/usr/bin/zsh

# Какой у вас сейчас:
$ echo $0      # имя текущего shell
bash

# Переключиться в zsh (если установлен):
$ zsh
% echo $0
zsh

# Назад в bash:
% exit

Сравните, что отличается в подсветке и подсказках. На bash без oh-my-bash подсказок и подсветки не будет. На zsh с oh-my-zsh — будет.

Попробуйте установить starship (модерн prompt):

# Установка
$ curl -sS https://starship.rs/install.sh | sh

# Добавить в ~/.bashrc или ~/.zshrc:
$ echo 'eval "$(starship init bash)"' >> ~/.bashrc
$ source ~/.bashrc

Starship покажет в prompt: текущая директория, git-ветка, статус, активный Python venv, время выполнения.


Проверка знанийKnowledge check
Junior пишет deployment-скрипт у себя на маке в fish, тестирует — работает. Деплоит на production Linux-сервер — скрипт сразу падает с syntax error. Почему?
ОтветAnswer
Fish — это не-POSIX shell с своим синтаксисом, несовместимым с bash. Скрипт, написанный для fish, использует `set var foo` вместо `var=foo`, `function foo ... end` вместо `function foo() { ... }`, `if condition` вместо `if [ condition ]; then ... fi`. На production-сервере fish обычно не установлен (бывает только на dev-машинах разработчиков), и скрипт запускается через bash (или sh) — который не понимает fish-синтаксис. Правильный подход: production-скрипты всегда пишутся на bash (shebang `#!/usr/bin/env bash`). Fish можно использовать как интерактивный shell для удобства, но скрипты — обязательно bash. Это правило не только про fish: zsh-specific конструкции (массивы 1-indexed, нативный SH_WORD_SPLIT) тоже могут поломать перенос на bash. Pure bash — это контракт надёжности для скриптов.

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 5. На чём писать production-скрипты для DE?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 4