install.sh 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. #!/bin/bash
  2. # --- НАСТРОЙКИ ---
  3. # Цвета для вывода
  4. GREEN="\033[1;32m"
  5. YELLOW="\033[1;33m"
  6. RED="\033[1;31m"
  7. NC="\033[0m" # No Color
  8. # Путь к этому скрипту и его папке
  9. SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
  10. # Имена файлов с пакетами
  11. PACMAN_PKGS="pkglist.txt"
  12. AUR_PKGS="aurlist.txt"
  13. # --- НАСТРОЙКИ СИМЛИНКОВ (Имена папок в репозитории) ---
  14. # Просто добавляйте файлы в эти папки.
  15. # 1. Папка для конфигов в $HOME/.config
  16. # (например, ~/dotfiles/config/bspwm -> ~/.config/bspwm)
  17. CONFIG_DIR_NAME="config"
  18. # 2. Папка для конфигов в $HOME
  19. # (например, ~/dotfiles/home/.zshrc -> ~/.zshrc)
  20. HOME_DIR_NAME="home"
  21. # 3. Папка для системных конфигов (управляется отдельной командой)
  22. # (например, ~/dotfiles/system/etc/vconsole.conf -> /etc/vconsole.conf)
  23. SYSTEM_DIR_NAME="system"
  24. # --- ХЕЛПЕРЫ ---
  25. msg() {
  26. echo -e "${GREEN}[INFO]${NC} $1"
  27. }
  28. warn() {
  29. echo -e "${YELLOW}[WARN]${NC} $1"
  30. }
  31. err() {
  32. echo -e "${RED}[ERROR]${NC} $1"
  33. }
  34. # --- ФУНКЦИИ ---
  35. # 1. Установка YAY (AUR Helper)
  36. install_yay() {
  37. if ! command -v yay &>/dev/null; then
  38. msg "YAY не найден. Установка YAY..."
  39. # Проверяем наличие git и base-devel перед установкой yay
  40. if ! pacman -Q git &>/dev/null || ! pacman -Q base-devel &>/dev/null; then
  41. sudo pacman -S --needed git base-devel
  42. fi
  43. git clone https://aur.archlinux.org/yay.git /tmp/yay
  44. (cd /tmp/yay && makepkg -si)
  45. rm -rf /tmp/yay
  46. msg "YAY установлен."
  47. else
  48. msg "YAY уже установлен."
  49. fi
  50. }
  51. # 2. Установка пакетов (Pacman и YAY)
  52. install_packages() {
  53. # --- Сбор пакетов для установки ---
  54. msg "Сбор пакетов для установки..."
  55. # Основные пакеты
  56. local pacman_args=$(sed 's/#.*//' "$SCRIPT_DIR/$PACMAN_PKGS" | grep -vE '^\s*$' | xargs)
  57. local aur_args=$(sed 's/#.*//' "$SCRIPT_DIR/$AUR_PKGS" | grep -vE '^\s*$' | xargs)
  58. # --- Поиск и выбор дополнительных пакетов ---
  59. # Ищем файлы вида pkglist-*.txt и aurlist-*.txt, исключая основные
  60. local optional_pacman_lists=($(find "$SCRIPT_DIR" -maxdepth 1 -name "pkglist-*.txt" ! -name "$PACMAN_PKGS"))
  61. local optional_aur_lists=($(find "$SCRIPT_DIR" -maxdepth 1 -name "aurlist-*.txt" ! -name "$AUR_PKGS"))
  62. if [ ${#optional_pacman_lists[@]} -gt 0 ] || [ ${#optional_aur_lists[@]} -gt 0 ]; then
  63. warn "Найдены дополнительные списки пакетов:"
  64. for list in "${optional_pacman_lists[@]}"; do echo " -> $(basename "$list") (Pacman)"; done
  65. for list in "${optional_aur_lists[@]}"; do echo " -> $(basename "$list") (AUR)"; done
  66. read -p "Хотите выбрать пакеты из этих списков для установки? [y/N]: " choice < /dev/tty
  67. if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
  68. # Добавляем пакеты из выбранных списков
  69. for list in "${optional_pacman_lists[@]}"; do
  70. read -p " -> Установить из '$(basename "$list")'? [y/N]: " list_choice < /dev/tty
  71. if [[ "$list_choice" == "y" || "$list_choice" == "Y" ]]; then
  72. pacman_args+=" $(sed 's/#.*//' "$list" | grep -vE '^\s*$' | xargs)"
  73. fi
  74. done
  75. for list in "${optional_aur_lists[@]}"; do
  76. read -p " -> Установить из '$(basename "$list")'? [y/N]: " list_choice < /dev/tty
  77. if [[ "$list_choice" == "y" || "$list_choice" == "Y" ]]; then
  78. aur_args+=" $(sed 's/#.*//' "$list" | grep -vE '^\s*$' | xargs)"
  79. fi
  80. done
  81. fi
  82. fi
  83. # --- Установка пакетов Pacman ---
  84. if [[ ! -z "$pacman_args" ]]; then
  85. msg "Установка пакетов из Pacman..."
  86. # Убрали --noconfirm, чтобы можно было решать конфликты вручную
  87. sudo pacman -S --needed $pacman_args
  88. else
  89. msg "Список Pacman для установки пуст."
  90. fi
  91. # --- Установка пакетов AUR ---
  92. if [[ ! -z "$aur_args" ]]; then
  93. msg "Проверка и установка YAY..."
  94. install_yay
  95. msg "Установка пакетов из AUR..."
  96. # Убрали --noconfirm
  97. yay -S --needed $aur_args
  98. else
  99. msg "Список AUR для установки пуст."
  100. fi
  101. msg "Установка пакетов завершена."
  102. }
  103. # 3. Создание символических ссылок (ОБНОВЛЕНО)
  104. link_dotfiles() {
  105. msg "Создание символических ссылок (симлинков)..."
  106. local source_dir=""
  107. local target_dir=""
  108. # --- 1. Линкуем файлы в $HOME (из папки 'home') ---
  109. msg " -> Линковка в $HOME (из '$HOME_DIR_NAME')"
  110. source_dir="$SCRIPT_DIR/$HOME_DIR_NAME"
  111. target_dir="$HOME"
  112. if [ -d "$source_dir" ]; then
  113. # Ищем все файлы и папки на первом уровне в 'home/'
  114. # -mindepth 1 (чтобы не найти саму папку 'home')
  115. # -maxdepth 1 (чтобы найти '.zshrc', 'bin', но не 'bin/скрипт')
  116. for item_path in $(find "$source_dir" -mindepth 1 -maxdepth 1); do
  117. local item_name=$(basename "$item_path")
  118. local source_path="$item_path"
  119. local target_path="$target_dir/$item_name"
  120. # Бэкапим, если в $HOME уже что-то есть (и это не симлинк)
  121. if [ -e "$target_path" ] && [ ! -L "$target_path" ]; then
  122. warn "Файл/папка '$target_path' уже существует. Бэкап в '$target_path.bak'..."
  123. mv "$target_path" "$target_path.bak"
  124. fi
  125. ln -sfn "$source_path" "$target_path"
  126. msg " -> $target_path -> $source_path"
  127. done
  128. else
  129. warn "Папка '$source_dir' не найдена. Пропуск $HOME линков."
  130. fi
  131. # --- 2. Линкуем файлы в $HOME/.config (из папки 'config') ---
  132. msg " -> Линковка в $HOME/.config (из '$CONFIG_DIR_NAME')"
  133. source_dir="$SCRIPT_DIR/$CONFIG_DIR_NAME"
  134. target_dir="$HOME/.config"
  135. # Создаем ~/.config, если его нет (на новой системе)
  136. mkdir -p "$target_dir"
  137. if [ -d "$source_dir" ]; then
  138. # Аналогичная логика для папки 'config'
  139. for item_path in $(find "$source_dir" -mindepth 1 -maxdepth 1); do
  140. local item_name=$(basename "$item_path")
  141. local source_path="$item_path"
  142. local target_path="$target_dir/$item_name"
  143. # Бэкапим, если в ~/.config уже есть такой конфиг (и это не симлинк)
  144. if [ -e "$target_path" ] && [ ! -L "$target_path" ]; then
  145. warn "Файл/папка '$target_path' уже существует. Бэкап в '$target_path.bak'..."
  146. mv "$target_path" "$target_path.bak"
  147. fi
  148. ln -sfn "$source_path" "$target_path"
  149. msg " -> $target_path -> $source_path"
  150. done
  151. else
  152. warn "Папка '$source_dir' не найдена. Пропуск $HOME/.config линков."
  153. fi
  154. msg "Симлинки созданы."
  155. }
  156. # 4. Проверка текущей конфигурации
  157. check_config() {
  158. # ... (проверка пакетов остается без изменений) ...
  159. msg "Проверка установленных пакетов Pacman..."
  160. local missing_pacman=0
  161. for f in $(find "$SCRIPT_DIR" -maxdepth 1 -name "pkglist*.txt"); do
  162. while IFS= read -r line || [[ -n "$line" ]]; do
  163. local pkg=$(echo "$line" | sed 's/#.*//' | xargs)
  164. if [[ -z "$pkg" ]]; then continue; fi
  165. # Исключение для 'xorg', т.к. это группа пакетов и pacman -Q для нее не работает.
  166. if [[ "$pkg" == "xorg" ]]; then
  167. continue
  168. fi
  169. if ! pacman -Q "$pkg" &>/dev/null; then
  170. warn " -> Не найден (Pacman, из $(basename $f)): $pkg"
  171. missing_pacman=1
  172. fi
  173. done < "$f"
  174. done
  175. if [ $missing_pacman -eq 0 ]; then msg "Все пакеты Pacman из списков 'pkglist*.txt' установлены."; fi
  176. msg "Проверка установленных пакетов AUR..."
  177. local missing_aur=0
  178. for f in $(find "$SCRIPT_DIR" -maxdepth 1 -name "aurlist*.txt"); do
  179. while IFS= read -r line || [[ -n "$line" ]]; do
  180. local pkg=$(echo "$line" | sed 's/#.*//' | xargs)
  181. if [[ -z "$pkg" ]]; then continue; fi
  182. if ! pacman -Q "$pkg" &>/dev/null; then
  183. warn " -> Не найден (AUR, из $(basename $f)): $pkg"
  184. missing_aur=1
  185. fi
  186. done < "$f"
  187. done
  188. if [ $missing_aur -eq 0 ]; then msg "Все пакеты AUR из списков 'aurlist*.txt' установлены."; fi
  189. msg "Проверка симлинков..."
  190. # --- 1. Проверка $HOME (из папки 'home') ---
  191. local source_dir="$SCRIPT_DIR/$HOME_DIR_NAME"
  192. if [ -d "$source_dir" ]; then
  193. for item_path in $(find "$source_dir" -mindepth 1 -maxdepth 1); do
  194. local item_name=$(basename "$item_path")
  195. if [ ! -L "$HOME/$item_name" ]; then
  196. warn " -> Симлинк не найден: $HOME/$item_name"
  197. fi
  198. done
  199. fi
  200. # --- 2. Проверка $HOME/.config (из папки 'config') ---
  201. source_dir="$SCRIPT_DIR/$CONFIG_DIR_NAME"
  202. if [ -d "$source_dir" ]; then
  203. for item_path in $(find "$source_dir" -mindepth 1 -maxdepth 1); do
  204. local item_name=$(basename "$item_path")
  205. if [ ! -L "$HOME/.config/$item_name" ]; then
  206. warn " -> Симлинк не найден: $HOME/.config/$item_name"
  207. fi
  208. done
  209. fi
  210. msg "Проверка завершена."
  211. }
  212. # 5. Проверка драйверов
  213. check_drivers() {
  214. msg "Проверка оборудования и рекомендации по драйверам..."
  215. warn "Это только рекомендации! Не устанавливайте автоматически."
  216. # Видеокарта
  217. local vga=$(lspci -k | grep -A 2 -E "(VGA|3D)")
  218. if echo "$vga" | grep -iq "NVIDIA"; then
  219. warn "Найдена карта NVIDIA. Рекомендуемые пакеты:"
  220. warn " -> nvidia (или nvidia-lts, nvidia-dkms)"
  221. warn " -> lib32-nvidia-utils (для 32-bit)"
  222. elif echo "$vga" | grep -iq "Intel"; then
  223. msg "Найдена карта Intel. Рекомендуемые пакеты (обычно уже в списке):"
  224. msg " -> mesa, lib32-mesa, vulkan-intel"
  225. if ! pacman -Q xf86-video-intel &>/dev/null; then
  226. warn " -> xf86-video-intel (старый 2D драйвер, может быть не нужен)"
  227. fi
  228. elif echo "$vga" | grep -iq "AMD"; then
  229. msg "Найдена карта AMD/ATI. Рекомендуемые пакеты (обычно уже в списке):"
  230. msg " -> mesa, lib32-mesa, vulkan-radeon"
  231. fi
  232. # Wi-Fi / Bluetooth
  233. if lspci -k | grep -iq "broadcom"; then
  234. warn "Найден чип Broadcom. Вам может понадобиться:"
  235. warn " -> broadcom-wl-dkms (для Wi-Fi)"
  236. fi
  237. msg "Проверка драйверов завершена."
  238. }
  239. # 6. Интерактивная установка системных конфигов
  240. apply_system_configs() {
  241. msg "--- РЕЖИМ: ПРИМЕНЕНИЕ СИСТЕМНЫХ КОНФИГОВ ---"
  242. local system_source_dir="$SCRIPT_DIR/$SYSTEM_DIR_NAME"
  243. if [ ! -d "$system_source_dir" ]; then
  244. err "Папка '$system_source_dir' не найдена. Создайте ее и поместите туда конфиги."
  245. return 1
  246. fi
  247. # Ищем все *файлы* внутри папки 'system'
  248. find "$system_source_dir" -type f | while read -r source_file; do
  249. # Получаем относительный путь (например, "etc/vconsole.conf")
  250. local rel_path=${source_file#$system_source_dir/}
  251. # Получаем абсолютный целевой путь (например, "/etc/vconsole.conf")
  252. local target_file="/$rel_path"
  253. msg "Найден конфиг: $rel_path"
  254. # 1. Проверяем, существует ли оригинал
  255. if [ ! -f "$target_file" ]; then
  256. warn "Файл '$target_file' не существует. Хотите скопировать новый?"
  257. read -p " [y/N] (Да/Нет): " choice < /dev/tty
  258. if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
  259. # Создаем дирректорию, если нужно
  260. sudo mkdir -p "$(dirname "$target_file")"
  261. sudo cp "$source_file" "$target_file"
  262. msg " -> СКОПИРОВАНО: $target_file"
  263. else
  264. msg " -> Пропущено."
  265. fi
  266. continue # Переходим к следующему файлу
  267. fi
  268. # 2. Оригинал существует, показываем diff
  269. if command -v diff &>/dev/null; then
  270. msg "Разница между вашим конфигом (dotfiles) и системным (/) :"
  271. # diff [оригинал] [новый]
  272. diff -u "$target_file" "$source_file" || true # || true чтобы скрипт не падал, если есть разница
  273. else
  274. warn "Команда 'diff' не найдена. Не могу показать разницу."
  275. fi
  276. # 3. Запрос на замену
  277. warn "Заменить системный файл '$target_file'?"
  278. read -p " [y/N/b] (Да / Нет / Бэкап и замена): " choice < /dev/tty
  279. case "$choice" in
  280. y|Y)
  281. sudo cp "$source_file" "$target_file"
  282. msg " -> ЗАМЕНЕНО: $target_file"
  283. ;;
  284. b|B)
  285. sudo mv "$target_file" "$target_file.bak"
  286. sudo cp "$source_file" "$target_file"
  287. msg " -> БЭКАП СОЗДАН: $target_file.bak"
  288. msg " -> ЗАМЕНЕНО: $target_file"
  289. ;;
  290. *)
  291. msg " -> Пропущено."
  292. ;;
  293. esac
  294. done
  295. msg "--- СИСТЕМНЫЕ КОНФИГИ ОБРАБОТАНЫ ---"
  296. }
  297. # 7. (НОВАЯ ФУНКЦИЯ) Создание стандартных папок пользователя
  298. create_user_dirs() {
  299. msg "Cоздание стандартных папок пользователя"
  300. # Создаем стандартный набор
  301. mkdir -p \
  302. "$HOME/Documents" \
  303. "$HOME/Downloads" \
  304. "$HOME/Pictures"
  305. msg " -> Базовые папки созданы."
  306. }
  307. # --- ГЛАВНЫЙ БЛОК (ВЫБОР РЕЖИМА) ---
  308. show_help() {
  309. echo "Скрипт управления конфигурацией Arch Linux (Dotfiles)"
  310. echo "Использование: $0 [команда]"
  311. echo
  312. echo "Команды:"
  313. echo " install - Установить все пакеты и создать симлинки (полная установка)."
  314. echo " check - Проверить, все ли установлено и настроено."
  315. echo " update - Обновить конфиг из Git и применить изменения (пакеты, симлинки)."
  316. echo " drivers - Проверить оборудование и предложить драйверы."
  317. echo " system - Интерактивно применить системные конфиги из папки '$SYSTEM_DIR_NAME'."
  318. echo " help - Показать это сообщение."
  319. }
  320. # Проверяем, что скрипт не запущен от root
  321. if [ "$EUID" -eq 0 ]; then
  322. err "Не запускайте этот скрипт от имени root (используйте 'sudo' только когда он сам попросит)."
  323. exit 1
  324. fi
  325. # Если нет аргументов, показать помощь
  326. if [ $# -eq 0 ]; then
  327. show_help
  328. exit 0
  329. fi
  330. case "$1" in
  331. install)
  332. msg "--- РЕЖИМ: ПОЛНАЯ УСТАНОВКА ---"
  333. install_packages
  334. link_dotfiles
  335. create_user_dirs # <-- ДОБАВЛЕНО
  336. msg "--- УСТАНОВКА ЗАВЕРШЕНА ---"
  337. msg "Для применения системных конфигов (vconsole.conf и т.д.) запустите: $0 system"
  338. ;;
  339. check)
  340. msg "--- РЕЖИМ: ПРОВЕРКА КОНФИГУРАЦИИ ---"
  341. check_config
  342. ;;
  343. update)
  344. msg "--- РЕЖИМ: ОБНОВЛЕНИЕ КОНФИГУРАЦИИ ---"
  345. msg "1. Получение изменений из Git (git pull)..."
  346. if ! git pull; then
  347. err "Не удалось выполнить 'git pull'. Проверьте подключение и статус репозитория."
  348. exit 1
  349. fi
  350. msg "2. Применение изменений (установка/линковка)..."
  351. install_packages
  352. link_dotfiles
  353. create_user_dirs # <-- ДОБАВЛЕНО
  354. msg "--- ОБНОВЛЕНИЕ ЗАВЕРШЕНО ---"
  355. ;;
  356. drivers)
  357. msg "--- РЕЖИМ: ПРОВЕРКА ДРАЙВЕРОВ ---"
  358. check_drivers
  359. ;;
  360. system)
  361. # (НОВЫЙ РЕЖИМ)
  362. apply_system_configs
  363. ;;
  364. help|*)
  365. show_help
  366. ;;
  367. esac