Цель этой статьи - продемонстрировать подход к синхронизации сред оболочки путем написания сценария сценария оболочки.
Цель состоит в том, чтобы поддерживать чистоту домашнего каталога нашего пользователя, открывая только стандартные файлы среды Bash и обеспечивая быстрый доступ к исходному коду из файлов .sources. Результат будет таким:
/. /.. /.bash_logout -> ~/.dotfiles/src/bash_logout /.bash_profile -> ~/.dotfiles/src/bash_profile /.bashrc -> ~/.dotfiles/src/bashrc /.profile -> ~/.dotfiles/src/profile /.dotfiles /bash_script /src /scripts /custom aliases /custom functions, etc .... /.sources -> ~/.dotfiles/bash_<unix-timestamp>
Мы рассмотрим сценарий, который я использую для синхронизации моей среды Bash между моим домашним компьютером с Ubuntu, удаленной песочницей Linux и моим ноутбуком Mac для работы.
Этот скрипт должен удовлетворять некоторым основным требованиям:
- Может использовать MacOs и Ubuntu (терминал iTerm / Gnome)
- Может предоставить самоорганизующуюся структуру для организации моих точечных файлов
- Может самостоятельно документировать себя и обеспечивает локальный контроль версий
- Можно быстро модифицировать среду Linux
Ссылки на ресурсы и материалы будут перечислены в порядке цитирования внизу статьи. Давайте начнем!
Самоорганизующаяся структура каталогов
Перейдите в свой домашний каталог и создайте новый каталог вместе с новым файлом: «bash_script». Вы можете включить расширение .sh или .bash, но я предпочитаю устанавливать shebang # внутри сценария. (См. справку по StackOverflow)
[local@~] $ mkdir -p .dotfiles && cd .dotfiles [[email protected]] $ touch bash-script && ls -1 /.dotfiles /bash-script
Откройте файл в любом редакторе кода и добавьте следующие строки кода. Это позволяет нам захватить путь к каталогу относительно корня пользователя из любого каталога, в котором запускается скрипт. Это позволяет нам динамически создавать методы и функции там, где требуется путь.
#!/usr/bin/env bash DIR=”$(cd “$( dirname “${BASH_SOURCE[0]}”)” >/dev/null 2>&1 && pwd)” cd $DIR
Предоставьте себе локальный доступ для выполнения сценария:
[[email protected]] $ chmod u+w bash_script && ls -l bash_script -rwxr-xr-x 1 jon staff 135 Dec 4 21:41 bash_script
Если вы еще этого не сделали, создайте репозиторий Git и инициализируйте наш каталог. Вы также можете получить имя репозитория, добавив в сценарий следующую строку.
REPO="`git rev-parse --show-toplevel`"
Создайте следующие каталоги:
[[email protected]] $ mkdir -p src && mkdir -p src/scripts
Скопируйте / переместите любые существующие файлы bash как обычные файлы без расширений в наш репозиторий, чтобы они соответствовали следующему. Обязательно сделайте резервную копию своих файлов на всякий случай.
[[email protected]] $ ls -1 src /. /.. /bash_logout /bash_profile /bashrc /profile /scripts /custom_file(s) ...
Создание простой локальной истории контроля версий
Наличие локального контроля версий полезно для конфигураций оболочки для песочницы.
Наш скрипт сгенерирует файл, который будет служить единым источником достоверных данных для пользовательских файлов в нашей среде Bash. Для этого мы создадим символическую ссылку на ~ / .sources из сгенерированного файла: ~ / .dotfiles / bash_1575527908.
[[email protected]] $ ls -a | grep .sources /.sources -> /Users/example_usr/.dotfiles/bash_1575525908
Файл .sources связан символической ссылкой на сгенерированный файл, содержащий все строки кода, полученные при запуске сценария. Это позволяет нам эффективно хранить историю файла в одном файле, а также иметь возможность быстро ссылаться на него из домашнего каталога пользователя.
Я нашел это полезным для быстрого обращения или отладки в командной строке.
Добавьте следующую функцию #init в наш скрипт и создайте вызов функции.
function init() { BASH_DIR=$REPO/src SCRIPTS=$BASH_DIR/scripts BASH_SRC=bash_”$(date +%s)” # Create our generated file with timestamp touch -f $BASH_SRC # Create directory for history reference mkdir -p $REPO/history # Store file mv -v $REPO/bash_* $REPO/history } init
Обратите внимание, что область действия переменной в сценариях оболочки динамически ограничена. Это означает, что область видимости объявленной переменной будет существовать, пока функция все еще выполняется. Это важно отметить и не путать с такими понятиями, как замыкания в JS или локальная область в языках ООП.
Дважды запустите скрипт, чтобы убедиться, что он работает правильно:
Бег №1
[[email protected]] $ ./bash_script [[email protected]] $ ls -l /. /.. /history /bash_1575525908
Прогон №2
[[email protected]] $ ./bash_script [[email protected]] $ ls -l /. /.. /history /bash_1575525908 /bash_1575525909
Создать файл единого источника истины в качестве источника
Поскольку область видимости переменной будет существовать до конца процесса функции, мы можем использовать их определения в следующей функции с плохим названием «generate_stuff».
Добавьте вызов функции в #generate_stuff конец функции # init, определенной на предыдущем шаге.
function init() { ... generate_stuff echo "Done." }
Давайте применим текущую структуру каталогов на практике. Между моими средами Ubuntu и Mac я храню пользовательские определения псевдонимов и функций в каталоге. / src / scripts репозитория.
Добавьте в наш скрипт следующую функцию. Этот метод довольно прост и выполняет итерацию по файлам в папке и добавляет содержимое в наш сгенерированный файл временных меток Unix.
function generate_stuff() { for f in $SCRIPTS/* do echo $f cat $f >> $BASH_SRC done }
Это хорошее место для программного добавления псевдонимов или исполняемых файлов, которым может потребоваться путь к каталогу. Например, вам может понадобиться псевдоним оболочки для перехода в этот каталог, а другой - для вызова сценария из любого места.
echo "alias dotfiles='cd $DIR'" >> $REPO/$BASH_SRC echo "alias srcbash='. $DIR/install'" >> $REPO/$BASH_SRC
Затем сделайте этот файл доступным из домашнего каталога. Создайте символическую ссылку на созданный исходный файл в домашний каталог (~).
Добавьте следующие строки в #generate_stuff.
function generate_stuff() { ... #Remove existing source file during subsequent runs rm -rf ~/.sources || true # Link generated file source file: ~/.sources" ln -fsn -v $REPO/$BASH_SRC ~/.sources }
Давайте снова запустим сценарий и выведем список скрытых файлов из домашнего каталога. Должно получиться так:
[[email protected]] $ ./bash_script [local@dotfiles] $ ls -l /. /.. /history /bash_1575525909 /bash_1575525908 /bash_1575530763 [local@dotfiles] $ ls -la ~ /.sources -> /User/example_usr/.dotfiles/bash_1575530763
Окружение Bash и совместимость
Ранее мы переместили наши bash-файлы в наш новый репозиторий dotfiles. Добавьте следующую функцию в скрипт для символьной ссылки на файлы конфигурации bash. Это необходимо, потому что интерпретатор Linux будет искать файлы конфигурации bash в домашнем каталоге пользователя перед поиском файлов конфигурации bash на системном уровне.
function link_bash() { for f in $BASH_DIR/* do FILENAME=$(basename $f) [[ -f $f ]] && ln -fsn -v $f $HOME/.$FILENAME done } init link_bash
Снова запустите скрипт и выведите список файлов из дома:
[[email protected]] $ ls -a ~ /. /.. /.bash_logout -> /Users/example_usr/.dotfiles/src/bash_logout /.bash_profile -> /Users/example_usr/.dotfiles/src/bash_profile /.bashrc -> /Users/example_usr/.dotfiles/src/bashrc /.profile -> /Users/example_usr/.dotfiles/src/profile
Наконец, загрузите скрипт в Github. Обязательно .gitignore папку history и сгенерированный файл. Их следует игнорировать, чтобы избежать проблем с совместимостью в разных средах.
Для решения проблем совместимости я использую в своих скриптах следующий метод.
function os_patch() { OS="`uname -s`" case $OS in 'Linux') OS='Linux' echo "alias ls='ls --color=auto'" >> $BASH_SRC ;; 'Darwin') OS='Mac' ;; *) ;; esac }
Надеюсь, это поможет тем, кто пишет свои собственные сценарии. Ниже я привел суть, содержащую готовый сценарий, который я использую для синхронизации сред Ubuntu и Mac Bash. Спасибо за прочтение.