Вопрос или проблема
Я пытаюсь добавить возможность для моего скрипта-установщика ArchLinux проверять, актуален ли он, на основе того, совпадает или нет его версия с номером версии, указанным на gitlab. Основной скрипт, который запускает установщик (и все пронумерованные файлы скриптов) — это скрипт aalis.sh
, который по сути запускает другие файлы вместе. Нумерация версий будет в формате 1.2.3
(major.minor.patch).
Вообще говоря, всякий раз, когда я вношу изменения в скрипт, я изменяю номер версии скрипта на gitlab; и я хочу, чтобы сам скрипт мог определить, что его номер версии не совпадает с номером на github (в случае, когда кто-то использует устаревшую версию скрипта и пытается его запустить); и автоматически обновлялся с помощью git fetch origin master
, а затем перезапускался с использованием обновленного содержимого.
Поместите все в функции перед обновлением скрипта. Это гарантирует, что весь код загружен до того, как содержимое скрипта будет заменено.
function some_function {
...
}
function main {
...
}
main "$@"
Если вы можете поместить вашу версию в отдельный файл, например version.sh
. Это будет еще безопаснее.
Я разобрался! Я нашел ответ для получения файла из онлайн-репозитория скрипта, используя команду curl и изменив URL, чтобы просто получить файл VERSION.txt (который будет содержать только номер версии, такой как 2.4.0
, и нашел ответ для фактической функциональности сравнения версий. После объединения двух ответов (и изменения вывода для скрипта test_compare_versions
мой результат выглядит так
# Ответ от https://stackoverflow.com/a/49351294/17812185 авторства Maxxim
# Сравнить две строки версии [$1: строка версии 1 (v1), $2: строка версии 2 (v2)]
# Возвращаемые значения:
# 0: v1 == v2
# 1: v1 > v2
# 2: v1 < v2
# Основано на: https://stackoverflow.com/a/4025065 авторства Dennis Williamson
function compare_versions() {
# Тривиальное тестирование v1 == v2 на основе строкового сравнения
[[ "$1" == "$2" ]] && return 0
# Локальные переменные
local regex="^(.*)-r([0-9]*)$" va1=() vr1=0 va2=() vr2=0 len i IFS="."
# Разбить строки версии на массивы, извлечь конечные ревизии
if [[ "$1" =~ ${regex} ]]; then
va1=(${BASH_REMATCH[1]})
[[ -n "${BASH_REMATCH[2]}" ]] && vr1=${BASH_REMATCH[2]}
else
va1=($1)
fi
if [[ "$2" =~ ${regex} ]]; then
va2=(${BASH_REMATCH[1]})
[[ -n "${BASH_REMATCH[2]}" ]] && vr2=${BASH_REMATCH[2]}
else
va2=($2)
fi
# Привести va1 и va2 к одинаковой длине, заполняя пустые поля нулями
(( ${#va1[@]} > ${#va2[@]} )) && len=${#va1[@]} || len=${#va2[@]}
for ((i=0; i < len; ++i)); do
[[ -z "${va1[i]}" ]] && va1[i]="0"
[[ -z "${va2[i]}" ]] && va2[i]="0"
done
# Добавить ревизии, увеличить длину
va1+=($vr1)
va2+=($vr2)
len=$((len+1))
# *** DEBUG ***
echo "TEST: '${va1[@]} (?) ${va2[@]}'"
# Сравнить элементы версии, проверить, если v1 > v2 или v1 < v2
for ((i=0; i < len; ++i)); do
if (( 10#${va1[i]} > 10#${va2[i]} )); then
return 1
elif (( 10#${va1[i]} < 10#${va2[i]} )); then
return 2
fi
done
# Все элементы равны, значит, v1 == v2
return 0
}
# Тест compare_versions [$1: строка версии 1, $2: строка версии 2, $3: ожидаемый результат]
function test_compare_versions() {
compare_versions "$1" "$2"
case $? in
0) op="==" ;;
1) op=">" ;;
2) op="<" ;;
esac
if [[ "$op" == "==" ]]; then
output ${LIGHT_GREEN} "Скрипт актуален!"
elif [[ "$op" == "<" ]]; then
output ${RED} "Скрипт устарел!!"
elif [[ "$op" == ">" ]]; then
output ${YELLOW} "Скрипт опережает релизную версию, значит, это должен быть релиз-кандидат или бета-версия!"
else
banner ${RED} "ЧТО-ТО ПОШЛО НЕ ТАК, ПОЖАЛУЙСТА, СООБЩИТЕ ОБ ЭТОЙ ОШИБКЕ НА GITLAB ПРОЕКТА"
fi
}
VERSION=1.2.0
ONLINE_VERSION=$(curl -s https://gitlab.com/NovaViper/testing-for-aalis-version-checker/-/raw/main/VERSION.txt)
test_compare_versions $VERSION $ONLINE_VERSION
.
Ответ или решение
Рассмотрим задачу обновления скрипта bash, который будет проверять наличие обновлений и самостоятельно обновляться с помощью системы Git, прежде чем пользоваться его основным функционалом. Представленная проблема заключается в необходимости разработки механизма, который будет проверять версию установленного скрипта с версией на репозитории и, в случае несоответствия, обновлять его до актуальной версии.
Теория
Основная идея заключается в применении версии контроля Git для отслеживания и обновления скрипта. При любом изменении скрипта в репозитории посередством повышения версии, пользователям будет предложено обновить свою локальную копию, чтобы скрипт всегда использовал последние изменения. Это предотвращает возможные ошибки при выполнении устаревших команд или функционала и гарантирует работу с актуальными версиями.
Для достижения этой цели используется несколько важных шагов:
-
Автоматизированная проверка версии: перед выполнением основной логики скрипта, необходимо реализовать функцию, которая будет сравнивать локальную версию скрипта и версию в репозитории GitLab.
-
Скачивание актуальной версии: если версии не совпадают, скрипт должен скачать последнюю версию из репозитория.
-
Самообновление: После скачивания новой версии, старый скрипт должен быть заменен на новый, и скрипт должен быть перезапущен.
Пример
Пример кода, приведенный ниже, детально объясняет, как можно интегрировать данный функционал в bash-скрипт. Основной фокус здесь — на функции сравнения версий и последовательности действий обновления:
#!/bin/bash
function compare_versions() {
[[ "$1" == "$2" ]] && return 0
local IFS=. i ver1=($1) ver2=($2)
for ((i=0; i<${#ver1[@]}; i++)); do
if [[ -z ${ver2[i]} ]]; then ver2[i]=0; fi
if ((10#${ver1[i]} > 10#${ver2[i]})); then
return 1
elif ((10#${ver1[i]} < 10#${ver2[i]})); then
return 2
fi
done
return 0
}
function check_for_update() {
local CURRENT_VERSION="1.2.0"
local ONLINE_VERSION=$(curl -s https://gitlab.com/NovaViper/testing-for-aalis-version-checker/-/raw/main/VERSION.txt)
compare_versions $CURRENT_VERSION $ONLINE_VERSION
case $? in
0) echo "Скрипт обновлен.";;
1) echo "Скрипт новее, чем версия на GitLab.";;
2)
echo "Доступна новая версия скрипта. Выполняется обновление..."
git fetch origin master
git reset --hard origin/master
exec ./$(basename $0)
exit
;;
esac
}
function main() {
check_for_update
echo "Выполнение основной функциональности скрипта..."
# ... основная логика ...
}
main "$@"
Применение
-
Запуск на сервере или локальной машине: Убедитесь, что установлен и настроен Git, а также предоставлены права доступа к репозиторию в GitLab, чтобы скрипт мог извлекать данные.
-
Упрощенная актуализация пользователей: Пользователи, скачивающие или клонирующие репозиторий, будут автоматически проверять версию скрипта, что облегчит им пребывание на актуальной версии. Это особенно полезно для проектов, которые регулярно обновляют конфигурации и требования.
-
Обработка возможных ошибок: Хорошо заметить, что наличие проверок на ошибки — жизненно необходимая часть скрипта, которая должна быть включена, чтобы избежать неправильного выполнения команд или сбоев в середине выполнения обновлений.
Подобный подход будет правильным и эффективным способом поддержания актуальности bash-скриптов, особенно если они часто используются в критически важных системах, где устаревание инструментов может привести к нежелательным результатам. Такой метод позволяет не только упростить управление версионностью, но и существенно сократить временные затраты на обновление программного обеспечения.