Linux терминал с отворени файлове .bashrc, .fedya_aliases и .fedya_functions

Подреден .bashrc: как разделих Bash функциите и alias командите

С времето всеки, който работи редовно с Linux, започва да натрупва собствени команди, съкратени имена, малки скриптове и помощни функции. Първоначално всичко изглежда удобно – добавяш няколко реда в .bashrc, отваряш нов терминал и започваш да ги използваш.

Проблемът идва по-късно.

Файлът постепенно се разраства. В него се смесват настройки на терминала, променливи на средата, пътища, SSH инструменти, alias команди и Bash функции. Когато трябва да намериш нещо или да промениш определена настройка, започваш да търсиш сред десетки, а понякога и стотици редове.

При мен решението беше сравнително просто: оставих в .bashrc основните настройки на Bash, а личните команди и функции изнесох в два отделни файла:

  • ~/.fedya_aliases – за всички мои alias команди.
  • ~/.fedya_functions – за Bash функциите, които изпълняват по-сложни операции.

Така запазих удобството на персонализираната командна среда, но разделих конфигурацията според предназначението ѝ.

В тази статия ще покажа как е организирана системата ми, защо избрах точно това разделение и как можеш да приложиш същия подход в собствената си Linux или WSL 2 среда.

1. Каква е ролята на .bashrc?

Файлът .bashrc се намира в домашната директория на потребителя и съдържа настройки, които Bash изпълнява при стартиране на интерактивна shell сесия.

Обикновено в него се намират:

  • настройки на командната история;
  • конфигурация на терминалния prompt;
  • цветове за файловете и командите;
  • променливи на средата;
  • допълнителни директории в PATH;
  • настройки за инструменти като NVM;
  • автоматично зареждане на Bash completion;
  • лични alias команди и функции.

Това не е универсален стартов файл за всички видове shell процеси. Той е предназначен основно за интерактивен Bash. Затова още в началото на моя .bashrc има проверка:

case $- in
    *i*) ;;
      *) return;;
esac

Тя проверява дали текущата Bash сесия е интерактивна. Ако не е, изпълнението на файла се прекратява.

Това е важно, защото не искам интерактивни настройки, зареждане на инструменти и помощни команди да се изпълняват без необходимост при автоматизирани процеси и неинтерактивни shell сесии.

2. Какво оставих в основния .bashrc?

Идеята ми не беше да разделя всеки ред в отделен файл. Напротив – .bashrc трябва да остане мястото за основните настройки на Bash.

В моята конфигурация там са запазени няколко основни групи.

История на командите

HISTCONTROL=ignoreboth
HISTFILESIZE=1000000
HISTSIZE=1000000

export HISTTIMEFORMAT="%d-%m-%Y %T "

shopt -s histappend
export PROMPT_COMMAND='history -a'

Тези настройки правят работата с историята значително по-удобна.

  • HISTCONTROL=ignoreboth пропуска команди, започващи с интервал, както и последователни дублиращи се команди.
  • HISTFILESIZE определя максималния брой записи във файла с историята.
  • HISTSIZE определя колко команди се пазят в паметта на текущата Bash сесия.
  • HISTTIMEFORMAT добавя дата и час при преглед на историята.
  • histappend позволява новите записи да се добавят към съществуващия файл, вместо той да бъде презаписван при приключване на сесията.
  • history -a записва новите команди във файла с историята след изпълнението им.

Последната настройка е особено полезна, когато работя с повече от един терминален прозорец.

Терминал и prompt

В .bashrc оставих и настройките за изгледа на терминала:

shopt -s checkwinsize

[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"

checkwinsize позволява на Bash да актуализира размерите на терминала след промяна на прозореца.

lesspipe добавя допълнителна обработка при преглед на определени файлове с less.

Оставих и собствената си конфигурация на PS1 – цветния prompt, който показва потребителя, името на машината и текущата директория.

Това е една от настройките, които предпочитам да останат в основния файл, защото пряко определят поведението и външния вид на shell сесията.

Външни инструменти

В основния файл продължават да се зареждат и инструментите, които използвам редовно:

  • Keychain за работа със SSH ключове;
  • NVM за управление на версиите на Node.js;
  • Bash completion за автоматично допълване на команди.

Например зареждането на NVM изглежда така:

export NVM_DIR="$HOME/.nvm"

[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

[ -s "$NVM_DIR/bash_completion" ] && \
    \. "$NVM_DIR/bash_completion"

Тези настройки не са лични команди, а част от средата, в която работя. Затова им е мястото в основната конфигурация.

3. Двата отделни файла

След като основните настройки останаха в .bashrc, дойде ред на личните команди.

Създадох два файла в домашната директория:

~/.bashrc
~/.fedya_aliases
~/.fedya_functions

Използвах скритите имена с начална точка, за да следват обичайния модел за конфигурационни файлове в Linux.

Разделението е логично:

Alias е кратко име за команда или комбинация от команди.

Bash function е малка програмна логика, която може да приема аргументи, да използва променливи, проверки, цикли и условни конструкции.

Това разграничение е важно. Не всяка команда трябва да бъде функция, както и не всяка операция е подходяща за alias.

4. Как зареждам двата файла?

В края на .bashrc добавих следния блок:

# ==========================================
# ЗАРЕЖДАНЕ НА ЛИЧНИ ФАЙЛОВЕ
# ==========================================

# Функции
if [ -f ~/.fedya_functions ]; then
    . ~/.fedya_functions
fi

# Алиаси
if [ -f ~/.fedya_aliases ]; then
    . ~/.fedya_aliases
fi

Това е съществената част от цялата организация.

Командата . зарежда и изпълнява съдържанието на посочения файл в текущата Bash среда. Тя е еквивалентна на source в Bash.

Проверката:

if [ -f ~/.fedya_functions ]; then

гарантира, че файлът съществува, преди да бъде зареден.

Така, ако някой от двата файла липсва, Bash няма да прекрати зареждането заради грешка от source.

Избрах първо да се зареждат функциите, а след тях alias командите. Това не е задължително правило за всяка конфигурация, но е разумна последователност, когато някои alias команди използват вече дефинирани функции.

След тази промяна не се налага да зареждам двата файла ръчно. При всяка нова интерактивна Bash сесия те се включват автоматично.

5. Как организирах .fedya_aliases?

Моят файл .fedya_aliases съдържа 69 alias команди, разделени в 12 тематични групи.

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

ГрупаПредназначение
System / NavigationОсновни системни команди и навигация
Files / SearchРабота с файлове, търсене и преглед
NetworkМрежови проверки
DockerУправление на контейнери и образи
Proxmox / Ansible / BackupsВиртуализация, автоматизация и архивиране
Git / DevelopmentКоманди за разработка
Node / NPM / AstroРабота с Node.js и Astro
Terminal / BashПомощни команди за терминала
Directories / ProjectsБърз достъп до работни директории
SSH / SecuritySSH връзки и настройки
NotificationsИзвестия след изпълнение на команди
Work helpersПомощни команди за ежедневната работа

Всяка група има отделно заглавие и кратки коментари.

Това прави файла лесен за преглед и поддръжка. Ако трябва да добавя нова Docker команда, знам точно къде да я поставя.

Няколко примера от моя файл

За навигация използвам:

alias ..='cd ..'
alias ...='cd ../..'
alias c='clear'

Това са малки съкращения, които спестяват писане на често използвани команди.

За преглед на файлове:

alias ll='ls -alF'
alias la='ls -A'
alias grep='grep --color=auto'

За Docker:

alias d='docker'
alias dcu='docker compose up -d'
alias dcd='docker compose down'
alias dps='docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Image}}\t{{.Ports}}"'

Последният пример е по-показателен. Вместо стандартния изход на docker ps използвам собствен формат, който показва само информацията, която искам да виждам при бърза проверка на контейнерите.

За Astro проектите имам съкратени команди:

alias dev='npm run dev'
alias build='npm run build'

alias np-tb='newpost print trainbrakes'
alias np-ld='newpost print linuxdevops'
alias np-zm='newpost print zdravemag'

Така мога да стартирам development server, да изпълня build или да извикам помощния си инструмент за нова статия, без всеки път да изписвам пълната команда.

Кога alias не е подходящ?

Alias командите са удобни, но имат ограничения.

Те представляват текстово заместване, а не пълноценни функции. Не са подходящи, когато трябва да обработват аргументи по контролиран начин или да изпълняват по-сложна логика.

Например:

alias ll='ls -alF'

е добър alias.

Но ако искам команда, която приема идентификатор на LXC контейнер, проверява дали има архив и го копира от отдалечен сървър, alias вече не е най-подходящото решение.

За подобни задачи използвам Bash функции.

6. Какво има в .fedya_functions?

Файлът .fedya_functions съдържа 15 функции.

Те не са просто съкратени команди. Всяка изпълнява конкретна задача и може да включва проверки, обработка на аргументи, работа с файлове или извикване на други инструменти.

Ето няколко примера от реалната ми конфигурация.

backup_ct – архивиране на LXC контейнер от Proxmox

Една от полезните функции е backup_ct.

Тя приема идентификатор на контейнер, търси най-новия подходящ vzdump архив на Proxmox сървъра и го копира локално чрез rsync.

Използването е просто:

backup_ct 105

Вътрешната логика включва:

  1. Проверка дали е подаден идентификатор на контейнер.
  2. Търсене на най-новия архив за съответния CT.
  3. Проверка дали архивът е намерен.
  4. Извличане на името на файла.
  5. Копиране чрез rsync.
  6. Проверка на резултата от копирането.

Това е типичен пример за задача, при която функцията е много по-подходяща от alias.

Тя приема аргумент, използва локални променливи и изпълнява няколко последователни операции.

bekap – бърз локален архив

Функцията bekap създава архивно копие на файловете в текущата директория.

Може да се използва по няколко начина:

bekap
bekap md
bekap py

Без аргумент копира всички подходящи файлове. При подаване на разширение може да се ограничиш само до определен тип файлове.

Например:

bekap md

ще копира Markdown файловете.

Функцията създава директория с дата и час, запазва структурата на поддиректориите и пропуска вече създадените архивни директории и .git.

Това е удобен начин за бързо локално копие преди промени по даден проект. Не замества пълноценна backup система, но е полезна допълнителна предпазна мярка.

gp – Git commit и push с една команда

За Git използвам функцията gp.

Пример:

gp "Поправка на навигацията"

Тя проверява дали има промени, добавя файловете към staging area, създава commit и изпраща промените към origin main.

Ако няма промени, функцията прекратява изпълнението.

Това спестява няколко команди при обичайна работа, но има важна особеност: git add -A добавя всички промени в работното хранилище, включително нови и изтрити файлове.

Затова не използвам подобна автоматизация без да съм прегледал какво ще бъде включено в commit.

Функцията е настроена да изпраща към main и не изпълнява предварително git pull. При работа в екип или при промени от друго устройство това трябва да се има предвид.

fa – търсене сред alias командите и функциите

Това е една от най-интересните функции в конфигурацията ми.

С течение на времето броят на личните команди става достатъчно голям, за да не помня всяка от тях наизуст.

Затова създадох fa, която използва fzf за интерактивно търсене.

fa

Тя събира заредените alias команди и функции, показва ги в интерактивен списък и позволява търсене по име, команда или описание.

В списъка има обозначения:

  • [A] – alias;
  • [F] – функция.

След избор с Enter се показва дефиницията чрез type.

Това е много по-удобно от ръчното търсене в два големи конфигурационни файла.

Функцията използва описанията в коментарите над дефинициите. Затова се старая всяка нова функция да има кратко описание и пример за употреба.

find_history_fzf – търсене в историята с Ctrl+H

Друга полезна функция е find_history_fzf.

Тя използва fzf, за да търси в Bash history. Избраната команда се поставя обратно в командния ред, вместо да се изпълнява автоматично.

Свързал съм я с клавишната комбинация:

Ctrl + H

Това е особено удобно, когато трябва да намеря команда, която съм използвал преди няколко дни, но не помня точното ѝ изписване.

tyrsi и tyrsi_all – търсене с български имена

В конфигурацията има и функции с български alias имена.

Основните функции са:

tyrsi дума
tyrsi дума файл

Първата търси в стандартния файл с моите alias команди, а втората позволява да се посочи друг файл.

За рекурсивно търсене в директория използвам:

tyrsi_all дума
tyrsi_all дума /път/до/директория

Така мога да търся текст в множество файлове, без да изписвам всеки път пълната команда с grep.

7. Alias или функция – как да избера?

Това е най-важното практическо разграничение.

ЗадачаПодходящо решение
Кратко име на често използвана командаAlias
Команда с фиксирани параметриAlias
Работа с аргументи $1, $2 и $@Функция
Условни проверки и циклиФункция
Няколко последователни операцииФункция
Обработка на грешки и кодове за изходФункция

Например:

alias d='docker'

е напълно достатъчно за съкращаване на командата docker.

Но:

backup_ct 105

изисква функция, защото трябва да обработи подадения идентификатор, да намери архив и да провери резултата от копирането.

Има и още една особеност: Bash alias командите обикновено се разширяват в интерактивни shell сесии. Не бива да разчиташ, че ще работят по същия начин в неинтерактивни скриптове. Bash функциите също не се предават автоматично на отделни child процеси, освен ако изрично не бъдат експортирани с export -f.

8. Как да проверя дали всичко работи?

След като направиш промените, има няколко лесни проверки.

Проверка на синтаксиса

bash -n ~/.bashrc
bash -n ~/.fedya_aliases
bash -n ~/.fedya_functions

Опцията -n проверява синтаксиса, без да изпълнява командите.

Ако няма изход и командата приключи с код 0, синтактичната проверка е преминала успешно.

Това обаче не доказва, че всички външни инструменти са инсталирани или че всяка функция ще работи правилно при реално изпълнение.

Зареждане на конфигурацията

След проверката можеш да заредиш настройките отново:

source ~/.bashrc

Другият вариант е да отвориш нов терминал.

Проверка на конкретна команда

За alias:

alias ll

За функция:

declare -f backup_ct

За обща проверка на дадено име:

type backup_ct
type dcu

Ако искаш да разбереш дали дадено име съществува като alias, функция или външна команда, можеш да използваш:

type -a име

Това е полезно и при диагностика на неочаквано поведение.

9. Няколко важни предупреждения от моята конфигурация

Когато създаваш лични команди, удобството не трябва да бъде за сметка на безопасността.

В моя .fedya_aliases има няколко команди, които изискват особено внимание.

Например:

alias drm='docker rm $(docker ps -a -q)'

Тази команда подава на docker rm идентификаторите на всички контейнери. Без -f Docker няма да премахне работещите контейнери, но може да премахне всички спрени контейнери. Това не е команда за безразборна употреба.

Също така:

alias drmi='docker rmi $(docker images -q)'

опитва да премахне всички Docker images. Ако някои се използват от контейнери, операцията може да бъде отказана.

А:

alias dstop='docker stop $(docker ps -q)'

спира всички работещи контейнери.

Това са удобни помощни команди, но трябва да знаеш точно какво правят, преди да ги изпълниш.

Имам и SSH съкратена команда с изключена проверка на host key:

alias sship='ssh \
    -o StrictHostKeyChecking=no \
    -o UserKnownHostsFile=/dev/null \
    -o LogLevel=ERROR'

Тя заобикаля важна защита на SSH и не е подходяща за обичайни връзки към сървъри. Използвай подобен подход само в контролирана среда и когато разбираш риска от атака тип Man-in-the-Middle.

Същото внимание важи и за Git функциите, които автоматично добавят всички промени и изпращат commit към отдалечено хранилище. Удобството не отменя необходимостта от преглед.

Моят съвет: не копирай сляпо чужди alias команди. Прегледай всяка от тях и се увери, че разбираш последствията от изпълнението ѝ.

10. Работи ли този подход в Linux и WSL 2?

Да. Това е обикновена Bash организация и не зависи от конкретна Linux дистрибуция.

Можеш да използваш същия подход в:

  • Ubuntu;
  • Debian;
  • Linux Mint;
  • други дистрибуции с Bash;
  • WSL 2 с Ubuntu или Debian.

Има обаче една особеност при WSL 2.

Ако използваш команди, които сочат към Windows директории, например /mnt/c/..., тези пътища трябва да бъдат адаптирани към твоя Windows потребител и структурата на дисковете.

Същото важи за инструменти като clip.exe, които са специфични за WSL и Windows интеграцията.

Самите файлове .fedya_aliases и .fedya_functions не са обвързани с WSL. Можеш да ги използваш и в обикновена Linux инсталация, стига зависимостите на конкретните команди да са налични.

Например функция, която използва fzf, няма да работи, ако fzf не е инсталиран. Функция за копиране през xclip изисква съответния инструмент и работеща графична среда или clipboard услуга.

Затова е добре всяка функция да описва зависимостите си в коментарите.

11. Как бих започнал, ако сега организирам своя .bashrc?

Ако досега си държал всичко в един файл, не е необходимо да променяш цялата конфигурация наведнъж.

Бих препоръчал следния ред:

Стъпка 1. Направи резервно копие:

cp ~/.bashrc ~/.bashrc.backup

Стъпка 2. Създай двата нови файла:

touch ~/.fedya_aliases
touch ~/.fedya_functions

Стъпка 3. Премести alias командите в .fedya_aliases.

Групирай ги по предназначение и добави кратки коментари.

Стъпка 4. Премести функциите в .fedya_functions.

Провери дали всяка функция има ясно име, описание и пример за употреба.

Стъпка 5. Добави блока за зареждане в края на .bashrc.

Стъпка 6. Провери синтаксиса:

bash -n ~/.bashrc
bash -n ~/.fedya_aliases
bash -n ~/.fedya_functions

Стъпка 7. Зареди конфигурацията и провери няколко команди:

source ~/.bashrc

type ll
type backup_ct

Не изтривай старите дефиниции, преди да се увериш, че новата конфигурация работи. Най-добре е да преместваш постепенно и да тестваш след всяка група промени.

Заключение

Разделянето на .bashrc, .fedya_aliases и .fedya_functions не е някаква сложна Linux техника. Това е начин да поддържаш работната си среда подредена, предвидима и лесна за разширяване.

В моя случай резултатът е ясен:

  • 69 alias команди, организирани в 12 тематични групи;
  • 15 Bash функции за по-сложни и повтарящи се задачи;
  • един основен .bashrc, който съдържа системните настройки и зарежда личните файлове;
  • автоматично зареждане при всяка нова интерактивна Bash сесия.

Най-голямата полза не е само в по-кратките команди. Тя е в това, че знам къде се намира всяка настройка и мога да променям отделна част от конфигурацията, без да засягам останалите.

С времето личната командна среда се превръща в нещо като собствен инструментариум. В него има команди за Docker, Git, Proxmox, архивиране, разработка и ежедневна работа. Когато е добре организиран, този инструментариум спестява време всеки ден.

И точно затова си струва да му отделиш малко внимание още в началото.