Repository navigation
Expand file tree
/
Copy pathsetup-android-build.sh
More file actions
523 lines (459 loc) · 24 KB
/
Copy pathsetup-android-build.sh
File metadata and controls
523 lines (459 loc) · 24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
#!/bin/bash
# setup-android-build.sh
# Установка всех зависимостей для сборки Android / LineageOS
# Поддержка: Ubuntu 20.04, 22.04, 24.04, 26.04+, Debian 11+, Linux Mint 20+
# Запускать от обычного пользователя с sudo-правами.
set -e
# ─── Цветной вывод ────────────────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
info() { echo -e "${BLUE}[INFO]${NC} $*"; }
ok() { echo -e "${GREEN}[OK]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
# ─── Настройки JDK ────────────────────────────────────────────────────────────
ANDROID_JDK_VERSION="${ANDROID_JDK_VERSION:-17}"
# Если ANDROID_JDK_VERSION=none — скрипт не будет трогать Java.
# ─── Проверка, что скрипт не запущен от root ──────────────────────────────────
if [ "$(id -u)" -eq 0 ]; then
error "Не запускайте скрипт от root. Запустите от обычного пользователя — sudo будет вызван по мере необходимости."
exit 1
fi
if ! command -v sudo >/dev/null 2>&1; then
error "sudo не найден. Установите sudo и повторите."
exit 1
fi
# ─── Определение дистрибутива и версии ────────────────────────────────────────
if [ -f /etc/os-release ]; then
. /etc/os-release
OS_ID="$ID"
OS_VERSION_ID="$VERSION_ID"
OS_NAME="$PRETTY_NAME"
else
error "Не удалось определить дистрибутив (/etc/os-release отсутствует)."
exit 1
fi
info "Обнаружена система: $OS_NAME"
OS_MAJOR="$(echo "$OS_VERSION_ID" | cut -d. -f1)"
case "$OS_ID" in
ubuntu)
case "$OS_MAJOR" in
20|22|24|25|26)
ok "Ubuntu $OS_VERSION_ID поддерживается."
;;
*)
warn "Ubuntu $OS_VERSION_ID официально не тестировалась. Продолжаю на свой страх и риск."
;;
esac
;;
linuxmint|pop|debian|zorin|elementary)
ok "Дистрибутив '$OS_ID' поддерживается (на базе Ubuntu/Debian)."
;;
*)
warn "Дистрибутив '$OS_ID' официально не тестировался. Продолжаю на свой страх и риск."
;;
esac
# ─── Определение архитектуры ──────────────────────────────────────────────────
ARCH="$(uname -m)"
info "Архитектура: $ARCH"
if [ "$ARCH" != "x86_64" ]; then
warn "Вы собираете не на x86_64. Официальные предсобранные инструменты AOSP"
warn "могут не работать (Exec format error, SIGSEGV в Rust)."
fi
# ─── Обновление системы ───────────────────────────────────────────────────────
info "Обновляю список пакетов и систему..."
sudo apt update -y
sudo apt upgrade -y
# ─── Вспомогательная функция: есть ли реальный кандидат на установку? ─────────
pkg_available() {
local candidate
candidate="$(LANG=C apt-cache policy "$1" 2>/dev/null | awk '/Candidate:/ {print $2; exit}')"
[ -n "$candidate" ] && [ "$candidate" != "(none)" ]
}
# ─── Установка Git LFS через официальный репозиторий PackageCloud ─────────────
info "Настраиваю официальный репозиторий Git LFS (PackageCloud)..."
if ! command -v git-lfs >/dev/null 2>&1; then
if pkg_available git-lfs; then
info "Устанавливаю git-lfs из репозитория Ubuntu..."
sudo apt install -y git-lfs
else
warn "git-lfs отсутствует в репозитории Ubuntu. Подключаю PackageCloud..."
curl -fsSL https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash
sudo apt install -y git-lfs
fi
if command -v git-lfs >/dev/null 2>&1; then
git lfs install --skip-repo
ok "git-lfs установлен и настроен."
else
warn "Не удалось установить git-lfs."
fi
else
ok "git-lfs уже установлен, пропускаю."
fi
# ─── Формирование списка основных пакетов ─────────────────────────────────────
info "Формирую список основных пакетов..."
BASE_PKGS=(
git gnupg flex bison build-essential zip curl
zlib1g-dev libc6-dev-i386 x11proto-core-dev libx11-dev
lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip fontconfig
)
if pkg_available libncurses5 && pkg_available lib32ncurses5-dev; then
BASE_PKGS+=(libncurses5 libncurses5-dev lib32ncurses5-dev)
ok "Использую libncurses5 / lib32ncurses5-dev (схема для Ubuntu 22.04 и старше)."
else
BASE_PKGS+=(libncurses6 libncurses-dev)
if pkg_available lib32ncurses-dev; then
BASE_PKGS+=(lib32ncurses-dev)
elif pkg_available lib32ncurses6; then
BASE_PKGS+=(lib32ncurses6)
fi
ok "Использую libncurses6 / libncurses-dev (схема для Ubuntu 24.04+)."
fi
info "Устанавливаю основной набор пакетов..."
sudo apt install -y "${BASE_PKGS[@]}"
# ─── Дополнительный набор для LineageOS / AOSP ────────────────────────────────
info "Формирую список дополнительных пакетов..."
EXTRA_PKGS=(
bc ccache rsync schedtool squashfs-tools
pngcrush lzop imagemagick python3 python3-pip python-is-python3
g++-multilib gcc-multilib lib32readline-dev
libsdl1.2-dev libssl-dev libelf-dev
libdw-dev libgnutls28-dev protobuf-compiler python3-protobuf
lz4 xxd
# ─── Дополнительные пакеты ────────────────────────────────────────────────
gperf
mc
pngquant
meld
brotli
qt5-qmake
texinfo
maven
swapspace
u-boot-tools
tofrodos
)
# ─── p7zip-full: в Ubuntu 24.04+ заменён на 7zip ──────────────────────────────
if pkg_available p7zip-full; then
EXTRA_PKGS+=(p7zip-full)
ok "Использую p7zip-full (старая схема)."
elif pkg_available 7zip; then
EXTRA_PKGS+=(7zip)
ok "p7zip-full отсутствует. Использую 7zip (Ubuntu 24.04+)."
else
warn "Не удалось найти p7zip-full или 7zip."
fi
# ─── libwxgtk3.0-gtk3-dev: переименован в libwxgtk3.2-dev ─────────────────────
if pkg_available libwxgtk3.0-gtk3-dev; then
EXTRA_PKGS+=(libwxgtk3.0-gtk3-dev)
elif pkg_available libwxgtk3.2-dev; then
EXTRA_PKGS+=(libwxgtk3.2-dev)
ok "libwxgtk3.0-gtk3-dev отсутствует. Использую libwxgtk3.2-dev."
fi
# ─── Android tools (adb/fastboot) ─────────────────────────────────────────────
if pkg_available android-tools-adb; then
EXTRA_PKGS+=(android-tools-adb)
elif pkg_available adb; then
EXTRA_PKGS+=(adb)
ok "android-tools-adb отсутствует. Использую adb."
fi
if pkg_available android-tools-fastboot; then
EXTRA_PKGS+=(android-tools-fastboot)
elif pkg_available fastboot; then
EXTRA_PKGS+=(fastboot)
ok "android-tools-fastboot отсутствует. Использую fastboot."
fi
# ─── libxml2: в Ubuntu 26.04 переименован в libxml2-16 ────────────────────────
if pkg_available libxml2; then
EXTRA_PKGS+=(libxml2)
ok "Использую libxml2 (схема для Ubuntu 22.04 и старше)."
elif pkg_available libxml2-16; then
EXTRA_PKGS+=(libxml2-16)
ok "Пакет 'libxml2' отсутствует. Использую 'libxml2-16' (Ubuntu 26.04+)."
else
warn "Не удалось найти пакет libxml2 или libxml2-16."
fi
# ─── liblz4-tool: transitional-пакет, заменён на lz4 ──────────────────────────
if ! pkg_available liblz4-tool; then
ok "Пакет 'liblz4-tool' отсутствует (заменён на 'lz4', который уже в списке)."
fi
# ─── erofs-utils ──────────────────────────────────────────────────────────────
if pkg_available erofs-utils; then
EXTRA_PKGS+=(erofs-utils)
fi
# ─── Фильтруем пакеты, которых нет в репозитории ──────────────────────────────
INSTALLABLE=()
for p in "${EXTRA_PKGS[@]}"; do
if pkg_available "$p"; then
INSTALLABLE+=("$p")
else
warn "Пакет '$p' недоступен в репозитории, пропускаю."
fi
done
sudo apt install -y "${INSTALLABLE[@]}"
# ─── repo (всегда устанавливаем свежую версию в ~/bin) ────────────────────────
info "Устанавливаю repo в ~/bin..."
mkdir -p ~/bin
export PATH=~/bin:$PATH
if curl -fsSL https://storage.googleapis.com/git-repo-downloads/repo -o ~/bin/repo; then
chmod a+x ~/bin/repo
if head -n1 ~/bin/repo | grep -qE '^#!'; then
REPO_VER="$(~/bin/repo --version 2>&1 | head -n1 || true)"
if echo "$REPO_VER" | grep -qi "repo not installed"; then
warn "repo скачан, но сообщает '<repo not installed>'."
warn "Это нормально для первого запуска — полная версия установится при 'repo init'."
warn "Проверьте вручную: ~/bin/repo --version"
else
ok "repo установлен: $REPO_VER"
fi
else
warn "repo скачан некорректно (не похож на скрипт). Проверьте соединение."
fi
else
warn "Не удалось скачать repo."
fi
# Добавляем ~/bin в PATH через ~/.bashrc, если ещё не добавлено
if ! grep -q 'export PATH=~/bin:\$PATH' "$HOME/.bashrc" 2>/dev/null; then
info "Добавляю ~/bin в PATH через ~/.bashrc..."
{
echo ""
echo "# Добавлено setup-android-build.sh"
echo 'export PATH=~/bin:$PATH'
} >> "$HOME/.bashrc"
ok "PATH обновлён (применится после перезапуска оболочки)."
else
ok "~/bin уже добавлен в PATH."
fi
# ─── libtinfo5 ────────────────────────────────────────────────────────────────
if ! pkg_available libtinfo5 && ! dpkg -s libtinfo5 >/dev/null 2>&1; then
info "libtinfo5 отсутствует в репозитории. Устанавливаю из архива Ubuntu..."
TMPDIR_NC="$(mktemp -d)"
pushd "$TMPDIR_NC" >/dev/null
LIBTINFO_URL="https://archive.ubuntu.com/ubuntu/pool/universe/n/ncurses/libtinfo5_6.3-2_amd64.deb"
if curl -fsSLO "$LIBTINFO_URL"; then
if sudo dpkg -i libtinfo5_6.3-2_amd64.deb; then
ok "libtinfo5 установлен."
else
warn "Не удалось установить libtinfo5. Возможно, потребуется вручную."
fi
else
warn "Не удалось скачать libtinfo5 из архива. Пропускаю."
fi
popd >/dev/null
rm -rf "$TMPDIR_NC"
else
ok "libtinfo5 уже доступен, пропускаю."
fi
# ─── Java (JDK) — с автоматическим переключением на JDK 17 ────────────────────
if [ "$ANDROID_JDK_VERSION" = "none" ]; then
info "Пропускаю настройку Java (ANDROID_JDK_VERSION=none)."
else
info "Проверяю Java (целевая версия: JDK $ANDROID_JDK_VERSION)..."
JDK_PKG="openjdk-${ANDROID_JDK_VERSION}-jdk"
JDK_HOME_CANDIDATE="/usr/lib/jvm/java-${ANDROID_JDK_VERSION}-openjdk-amd64"
NEED_INSTALL=false
CURRENT_JAVA_MAJOR=""
if command -v java >/dev/null 2>&1; then
JAVA_VER="$(java -version 2>&1 | head -n1)"
info "Текущая Java: $JAVA_VER"
CURRENT_JAVA_MAJOR="$(java -version 2>&1 | head -n1 | grep -oE '"[0-9]+' | tr -d '"')"
if [ -z "$CURRENT_JAVA_MAJOR" ]; then
CURRENT_JAVA_MAJOR="$(java -version 2>&1 | head -n1 | grep -oE '[0-9]+' | head -n1)"
fi
if [ "$CURRENT_JAVA_MAJOR" = "$ANDROID_JDK_VERSION" ]; then
ok "Java $CURRENT_JAVA_MAJOR уже используется — это подходящая версия."
else
warn "Текущая Java — $CURRENT_JAVA_MAJOR, а для сборки нужна JDK $ANDROID_JDK_VERSION."
NEED_INSTALL=true
fi
else
warn "Java не найдена. Устанавливаю JDK $ANDROID_JDK_VERSION..."
NEED_INSTALL=true
fi
if [ "$NEED_INSTALL" = true ]; then
if pkg_available "$JDK_PKG"; then
info "Устанавливаю $JDK_PKG..."
sudo apt install -y "$JDK_PKG"
else
warn "Пакет '$JDK_PKG' недоступен. Пробую альтернативы..."
for alt in 17 21 11; do
if pkg_available "openjdk-${alt}-jdk"; then
warn "Устанавливаю openjdk-${alt}-jdk вместо JDK $ANDROID_JDK_VERSION."
sudo apt install -y "openjdk-${alt}-jdk"
ANDROID_JDK_VERSION="$alt"
JDK_HOME_CANDIDATE="/usr/lib/jvm/java-${alt}-openjdk-amd64"
break
fi
done
fi
if [ -d "$JDK_HOME_CANDIDATE" ]; then
JAVA_BIN="$JDK_HOME_CANDIDATE/bin/java"
JAVAC_BIN="$JDK_HOME_CANDIDATE/bin/javac"
if [ -x "$JAVA_BIN" ]; then
info "Переключаю Java на $JDK_HOME_CANDIDATE..."
sudo update-alternatives --install /usr/bin/java java "$JAVA_BIN" 2000
sudo update-alternatives --set java "$JAVA_BIN"
ok "Java переключена."
fi
if [ -x "$JAVAC_BIN" ]; then
info "Переключаю javac на $JDK_HOME_CANDIDATE..."
sudo update-alternatives --install /usr/bin/javac javac "$JAVAC_BIN" 2000
sudo update-alternatives --set javac "$JAVAC_BIN"
ok "javac переключён."
fi
if ! grep -q "JAVA_HOME=.*java-${ANDROID_JDK_VERSION}-openjdk" "$HOME/.bashrc" 2>/dev/null; then
info "Добавляю JAVA_HOME в ~/.bashrc..."
{
echo ""
echo "# Java для сборки Android (добавлено setup-android-build.sh)"
echo "export JAVA_HOME=\"$JDK_HOME_CANDIDATE\""
echo "export PATH=\"\$JAVA_HOME/bin:\$PATH\""
} >> "$HOME/.bashrc"
ok "JAVA_HOME добавлен в ~/.bashrc (применится после перезапуска оболочки)."
fi
else
warn "Каталог $JDK_HOME_CANDIDATE не найден. Возможно, JDK установлен в другое место."
warn "Проверьте: ls /usr/lib/jvm/"
fi
fi
if command -v java >/dev/null 2>&1; then
JAVA_VER_FINAL="$(java -version 2>&1 | head -n1)"
info "Итоговая Java: $JAVA_VER_FINAL"
FINAL_MAJOR="$(java -version 2>&1 | head -n1 | grep -oE '"[0-9]+' | tr -d '"')"
if [ "$FINAL_MAJOR" != "$ANDROID_JDK_VERSION" ]; then
warn "Итоговая версия Java ($FINAL_MAJOR) отличается от целевой ($ANDROID_JDK_VERSION)."
warn "Если сборка упадёт — переключите вручную:"
warn " sudo update-alternatives --config java"
warn " sudo update-alternatives --config javac"
else
ok "Java $FINAL_MAJOR готова к сборке."
fi
fi
fi
# ─── QEMU (для не-x86_64 архитектур) ──────────────────────────────────────────
if [ "$ARCH" != "x86_64" ]; then
info "Устанавливаю QEMU для эмуляции x86_64..."
sudo apt install -y qemu-user-static binfmt-support || \
warn "QEMU не установился. Возможно, потребуется ручная настройка binfmt_misc."
fi
# ─── Символические ссылки для совместимости ───────────────────────────────────
if [ ! -e /usr/lib/x86_64-linux-gnu/libncurses.so.5 ] && \
[ ! -e /lib/x86_64-linux-gnu/libncurses.so.5 ]; then
if [ -e /usr/lib/x86_64-linux-gnu/libncurses.so.6 ]; then
info "Создаю совместимую ссылку libncurses.so.5 → libncurses.so.6..."
sudo ln -sf /usr/lib/x86_64-linux-gnu/libncurses.so.6 \
/usr/lib/x86_64-linux-gnu/libncurses.so.5
ok "Ссылка создана."
fi
fi
if [ ! -e /usr/lib/x86_64-linux-gnu/libtinfo.so.5 ] && \
[ ! -e /lib/x86_64-linux-gnu/libtinfo.so.5 ]; then
if [ -e /usr/lib/x86_64-linux-gnu/libtinfo.so.6 ]; then
info "Создаю совместимую ссылку libtinfo.so.5 → libtinfo.so.6..."
sudo ln -sf /usr/lib/x86_64-linux-gnu/libtinfo.so.6 \
/usr/lib/x86_64-linux-gnu/libtinfo.so.5
ok "Ссылка создана."
fi
fi
if [ ! -e /usr/lib/x86_64-linux-gnu/libxml2.so.2 ] && \
[ ! -e /lib/x86_64-linux-gnu/libxml2.so.2 ]; then
if [ -e /usr/lib/x86_64-linux-gnu/libxml2.so.16 ]; then
info "Создаю совместимую ссылку libxml2.so.2 → libxml2.so.16..."
sudo ln -sf /usr/lib/x86_64-linux-gnu/libxml2.so.16 \
/usr/lib/x86_64-linux-gnu/libxml2.so.2
ok "Ссылка создана (только для совместимости)."
fi
fi
# ─── Установка пользовательских приложений ────────────────────────────────────
info "Устанавливаю пользовательские приложения..."
# 1. Google Chrome
info "Устанавливаю Google Chrome..."
if ! command -v google-chrome >/dev/null 2>&1; then
CHROME_DEB="/tmp/google-chrome-stable_current_amd64.deb"
if curl -fsSL -o "$CHROME_DEB" "https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb"; then
if sudo apt install -y "$CHROME_DEB"; then
ok "Google Chrome установлен."
else
warn "Не удалось установить Google Chrome."
fi
rm -f "$CHROME_DEB"
else
warn "Не удалось скачать Google Chrome."
fi
else
ok "Google Chrome уже установлен, пропускаю."
fi
# 2. AnyDesk
info "Устанавливаю AnyDesk..."
if ! command -v anydesk >/dev/null 2>&1; then
if curl -fsSL "https://keys.anydesk.com/repos/DEB-GPG-KEY" | sudo gpg --dearmor -o /usr/share/keyrings/anydesk-archive-keyring.gpg 2>/dev/null; then
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/anydesk-archive-keyring.gpg] http://deb.anydesk.com/ all main" | \
sudo tee /etc/apt/sources.list.d/anydesk.list > /dev/null
if sudo apt update -y >/dev/null 2>&1 && sudo apt install -y anydesk; then
ok "AnyDesk установлен."
sudo systemctl enable anydesk >/dev/null 2>&1
ok "AnyDesk добавлен в автозапуск."
else
warn "Не удалось установить AnyDesk."
fi
else
warn "Не удалось добавить GPG-ключ AnyDesk."
fi
else
ok "AnyDesk уже установлен, пропускаю."
fi
# 3. Telegram
info "Устанавливаю Telegram..."
if ! command -v telegram-desktop >/dev/null 2>&1; then
if sudo apt install -y telegram-desktop; then
ok "Telegram установлен."
else
warn "Не удалось установить Telegram. Пробую через Snap..."
if command -v snap >/dev/null 2>&1; then
sudo snap install telegram-desktop || warn "Не удалось установить Telegram через Snap."
else
warn "Snap не установлен, пропускаю Telegram."
fi
fi
else
ok "Telegram уже установлен, пропускаю."
fi
# 4. Visual Studio Code
info "Устанавливаю Visual Studio Code..."
if ! command -v code >/dev/null 2>&1; then
if curl -fsSL "https://packages.microsoft.com/keys/microsoft.asc" | sudo gpg --dearmor -o /usr/share/keyrings/microsoft.gpg 2>/dev/null; then
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/microsoft.gpg] https://packages.microsoft.com/repos/code stable main" | \
sudo tee /etc/apt/sources.list.d/vscode.list > /dev/null
if sudo apt update -y >/dev/null 2>&1 && sudo apt install -y code; then
ok "Visual Studio Code установлен."
else
warn "Не удалось установить Visual Studio Code."
fi
else
warn "Не удалось импортировать GPG-ключ Microsoft."
fi
else
ok "Visual Studio Code уже установлен, пропускаю."
fi
# ─── Настройка ccache ─────────────────────────────────────────────────────────
if command -v ccache >/dev/null 2>&1; then
ok "ccache установлен: $(ccache --version | head -n1)"
else
warn "ccache не установлен (не критично, но ускоряет повторные сборки)."
fi
# ─── Финальная проверка ───────────────────────────────────────────────────────
echo
info "Проверка ключевых инструментов:"
for tool in git git-lfs curl python3 java javac ccache repo adb fastboot google-chrome anydesk telegram-desktop code; do
if command -v "$tool" >/dev/null 2>&1; then
ok "$tool: $(command -v "$tool")"
else
warn "$tool: НЕ НАЙДЕН"
fi
done
echo
echo
ok "Установка завершена!"