.bashrc и история команд
Каждый раз когда вы открываете терминал, bash читает файл конфигурации и подгружает оттуда настройки: aliases, переменные окружения, функции, history-настройки. Это важный механизм, потому что без понимания вы получите проблемы вида «alias работает в одном терминале, а в другом — нет», «PATH прописал, но не работает», «история теряется между сессиями».
В этом уроке разберём, какие файлы читает bash, чем .bashrc отличается от .bash_profile, как настроить историю, и какие есть хитрые shortcut-ы для работы с историей (Ctrl-R, !!, !$, и так далее).
Login shell vs Interactive shell
Bash может запускаться в разных режимах, и это влияет на то, какие конфиги он читает. Два главных разделения:
Получается четыре комбинации:
- Login + Interactive — вы зашли по SSH или в console. Это первый bash, в нём интерактивно вводите команды.
- Non-login + Interactive — открыли новый таб в iTerm2 на macOS. macOS по умолчанию запускает login shell в каждом табе (исторически), на Linux — non-login.
- Login + Non-interactive — редко, обычно при ssh с
-Tили скрипт черезbash --login. - Non-login + Non-interactive — скрипт
./script.sh. Самый частый non-interactive случай.
Bash для каждого режима читает свой набор файлов.
Какие файлы читает bash
Это важный момент. Когда вы пишете bash-скрипт ./deploy.sh, он НЕ читает .bashrc и НЕ знает ваши aliases. Поэтому если в скрипте вы хотите ll — у вас ничего не получится, нужно писать ls -la явно.
Главный конфиг для interactive работы — ~/.bashrc. Туда кладут:
- aliases (
alias ll='ls -la') - переменные окружения (
export PATH=...) - prompt customization (
PS1=...) - history settings
- автодополнение
- инициализацию starship/p10k
Файл ~/.bash_profile обычно делает одну вещь — подгружает ~/.bashrc:
# ~/.bash_profile
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
Это нужно, потому что на login-shell .bashrc не подгружается автоматически. На macOS каждый новый таб iTerm2 — это login shell, и без этого хака .bashrc не работал бы.
~/.profile — universal POSIX
~/.profile — это POSIX-стандартный файл. Его читает не только bash, но и dash, sh, ksh. Туда обычно кладут только переменные окружения, в POSIX-синтаксисе (без bash-extensions).
Логика такая: ~/.profile — переменные для ВСЕЙ системы, ~/.bashrc — настройки только bash. Если вы используете zsh, у zsh свой аналог ~/.zshrc.
На Ubuntu обычно цепочка такая:
~/.bash_profile # если есть, перебивает остальные
-> ~/.bashrc
-> ~/.profile # только если bash_profile нет
На macOS:
~/.bash_profile -> ~/.bashrc (в каждом login-shell)
Чтобы не путаться, простое правило: всё кладите в ~/.bashrc. Если работаете в zsh — в ~/.zshrc. А .bash_profile пусть делает только source:
# ~/.bash_profile (универсальная заготовка)
[[ -f ~/.bashrc ]] && source ~/.bashrc
Aliases — короткие имена для команд
Alias — это бирка для команды. Когда shell видит alias в начале строки, заменяет его на полную команду.
$ alias ll='ls -la'
$ ll
total 24
drwxr-xr-x ...
$ alias # показать все
alias ll='ls -la'
alias la='ls -A'
alias l='ls -CF'
$ unalias ll # удалить
Стандартный набор полезных aliases:
# В ~/.bashrc:
alias ll='ls -la --color=auto'
alias la='ls -A --color=auto'
alias l='ls -CF --color=auto'
alias ..='cd ..'
alias ...='cd ../..'
alias gs='git status'
alias gd='git diff'
alias gco='git checkout'
alias gp='git pull'
alias k='kubectl'
alias d='docker'
alias dc='docker compose'
# Безопасность: интерактивный режим для опасных команд
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
git config aliases — Git-side настройка сокращений
Aliases работают только в interactive shell. В скриптах они НЕ работают (если не включить shopt -s expand_aliases). Поэтому в скриптах всегда пишите полную команду, а не alias. Когда копируете чужой скрипт и удивляетесь «откуда там ll?» — скорее всего, это функция, не alias.
Aliases для интерактива — отлично. Для скриптов — пишите функции:
# В ~/.bashrc или в скрипте:
mkcd() {
mkdir -p "$1" && cd "$1"
}
$ mkcd ~/new-project
$ pwd
/home/user/new-project
Подробнее про функции в модуле 17.
Exports — переменные окружения
Переменные в bash бывают двух типов:
- Локальные — видны только в текущем shell.
- Экспортированные (env) — видны и дочерним процессам.
$ name="Alice" # локальная
$ bash -c 'echo "$name"' # дочерний bash не видит
# (пустая строка)
$ export name="Alice" # экспортирована
$ bash -c 'echo "$name"' # видит
Alice
В ~/.bashrc обычно используют export для переменных, которые должны быть видны всем программам:
# Добавить в PATH
export PATH="$HOME/.local/bin:$PATH"
export PATH="$HOME/bin:$PATH"
# Установить редактор по умолчанию
export EDITOR=vim
export VISUAL=vim
# Цвета для less, man
export LESS='-R' # raw output (для цветов)
export LESSHISTFILE=- # не записывать историю less
# Локаль
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
PATH — самая важная переменная. Она содержит список папок, в которых shell ищет команды. Когда вы пишете ls, shell перебирает все папки из PATH (например, /usr/local/bin, /usr/bin, /bin) и ищет файл ls в одной из них.
$ echo $PATH
/home/user/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Где именно ls?
$ which ls
/usr/bin/ls
$ type ls
ls is aliased to `ls --color=auto' # потому что alias
type показывает, что именно найдено: alias, function, builtin (встроенная в bash) или внешний файл.
Bash history: основные настройки
Bash сохраняет вашу историю команд в файл (обычно ~/.bash_history). Это файл, который пополняется при каждом завершении сессии (или при history -a).
Настройка через переменные окружения:
# В ~/.bashrc:
# Размер истории: 10000 команд в памяти, 50000 в файле
export HISTSIZE=10000
export HISTFILESIZE=50000
# Не сохранять дубликаты подряд и команды, начинающиеся с пробела
export HISTCONTROL=ignoredups:ignorespace
# Добавлять timestamp к каждой команде
export HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S "
# Добавлять к файлу истории, а не перезаписывать (если несколько терминалов)
shopt -s histappend
# После каждой команды — записывать в файл (не ждать до выхода)
PROMPT_COMMAND="history -a; ${PROMPT_COMMAND}"
Что значит каждый параметр:
После применения HISTTIMEFORMAT команды в history показывают время:
$ history | tail -5
996 2026-05-13 14:32:01 cd ~/projects
997 2026-05-13 14:32:05 git status
998 2026-05-13 14:32:10 git diff
999 2026-05-13 14:32:30 git commit -m 'fix'
1000 2026-05-13 14:33:00 git push
Поиск в истории: Ctrl-R
Самый полезный shortcut в bash — Ctrl-R (reverse incremental search). Нажимаете Ctrl-R, начинаете печатать — bash ищет в истории команду, содержащую это слово.
$ <Ctrl-R>
(reverse-i-search)`':
# Начинаете печатать "git push"
(reverse-i-search)`git pu': git push origin main
# Enter — выполнить
# Esc — оставить в строке без выполнения
# Ctrl-R ещё раз — следующее совпадение в истории
Это экономит часы. Без Ctrl-R вы стрелкой вверх 50 раз пролистываете историю — с Ctrl-R находите за 3 символа.
История shortcut: !!, !$, !^
Bash имеет «event designators» — короткие способы ссылаться на команды из истории:
Примеры использования:
$ apt update
E: Could not open lock file /var/lib/apt/lists/lock - permission denied (13)
$ sudo !!
sudo apt update
[sudo] password for user:
...
$ vim /etc/ssh/sshd_config
$ ls -la !$
ls -la /etc/ssh/sshd_config
-rw-r--r-- 1 root root 3253 May 13 14:00 /etc/ssh/sshd_config
# С опечаткой:
$ cd /et/passwd
bash: cd: /et/passwd: No such file or directory
$ ^et^etc
cd /etc/passwd
bash: cd: /etc/passwd: Not a directory # ну, тоже ошибка, но понятная
Это всё readline-фичи, работают в bash и zsh. В fish — свой синтаксис.
fzf: интерактивный fuzzy-search для истории
Альтернатива Ctrl-R — fzf (fuzzy finder). После установки:
$ sudo apt install -y fzf
# В ~/.bashrc:
$ echo 'source /usr/share/doc/fzf/examples/key-bindings.bash' >> ~/.bashrc
$ source ~/.bashrc
Теперь Ctrl-R открывает интерактивный fuzzy search:
$ <Ctrl-R>
> git pu_ ← печатаете
> git push origin main
git push --tags
git pull origin main
git pull --rebase origin main
Стрелочками выбираете, Enter — запускаете. Гораздо удобнее обычного Ctrl-R, особенно когда история большая (10000+ команд).
fzf — это супер-инструмент для DE, мы подробнее разберём его в модуле 19.
Попробуй сам
Откройте свой ~/.bashrc и посмотрите, что там:
$ cat ~/.bashrc
# Длинный файл с настройками. Найдите HISTSIZE, HISTCONTROL и aliases
Добавьте полезные настройки:
# В конец ~/.bashrc:
# Расширенная история
export HISTSIZE=10000
export HISTFILESIZE=50000
export HISTCONTROL=ignoredups:ignorespace
export HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S "
shopt -s histappend
# Полезные aliases
alias ll='ls -la --color=auto'
alias ..='cd ..'
alias ...='cd ../..'
alias gs='git status'
# PATH для локальных скриптов
export PATH="$HOME/.local/bin:$PATH"
Перезагрузите конфиг:
$ source ~/.bashrc
# или короче:
$ . ~/.bashrc
# Проверьте, что заработало:
$ alias
$ echo $HISTSIZE
10000
Попробуйте history shortcuts:
$ pwd
/home/user
$ echo "!$"
echo "/home/user"
/home/user
$ ls
$ sudo !!
sudo ls
...
$ <Ctrl-R>git<Enter>
# найдёт последнюю git-команду