Толик Панков
hex_laden
............ .................. ................

October 2025
      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

Толик Панков [userpic]
Скрипт для поиска загрузчика Windows из Linux-окружения.

Преамбула


Найти загрузчик Windows на разделе жесткого диска, дело не очень сложное:

1. Надо проверить файловую систему раздела, она должна быть FAT32 или NTFS
2. Проверить наличие файла ntldr (Windows XP и ранее) или bootmgr (Windows Vista и позднее) в корне раздела. Windows XP и старше, при установке по умолчанию, записывают файл ntldr в корень системного раздела, а более новые - создают отдельный загрузочный раздел, в корне которого лежит bootmgr.

Для чего? Например, для создания своего скрипта автоматической настройки загрузчика Grub или Syslinux

Поиск разделов NTFS и FAT32


Я недавно писал о том, как узнать файловую систему раздела (диска) в Linux Копия. В данном случае действовать будем примерно также.

Обработать вывод команды blkid (вывод данных о блочных устройствах) можно в цикле for:

echo "Find Windows loaders..."

IFS=$'\n'

for DEVDATA in $(blkid); do
...
done


Перед циклом необходимо установить значение переменной IFS, как \n (перенос строки)
IFS - переменная, задающая разделители полей при работе со строками в shell, по умолчанию разделители это табуляция, перенос строки и пробел, если не установить ее значение, как "только перенос строки", то строка с описанием каждого раздела (например, /dev/sda1: UUID="68DF-FF87" TYPE="vfat" PARTUUID="00003214-01") распадется на части, что поломает алгоритм.

В цикле for:

1. Вытаскиваем в переменную VOL нужные данные - путь к устройству и файловую систему:

VOL=`echo "$DEVDATA" |sed -n 's/\(.*:\).* TYPE=\"\([^\"]*\)\".*/\1\2/p'`

Для вышеуказанного /dev/sda1 получится строка /dev/sda1:vfat

2. Получаем путь к устройству и тип файловой системы отдельно в переменные, соответственно, VOLNAME и VOLFS.

VOLNAME=`echo "$VOL"|awk -F ":" '{print $1}'`
VOLFS=`echo "$VOL"|awk -F ":" '{print $2}'`


Параметр -F ":" устанавливает двоеточие в качестве разделителя полей awk.

3. Далее, проверяем, не пуста ли строка в переменной VOLFS, и проверяем ее значение. Если VOLFS равна ntfs или vfat, то запускаем функцию find_loader(), проверяющую наличие загрузчика в корне соответствующего раздела. Если файловая система раздела другая - выводится сообщение, что это не Windows-раздел.

if [ -n "$VOLFS" ]; then
	if [[ "$VOLFS" == "ntfs" || "$VOLFS" == "vfat" ]];then
		find_loader $VOLNAME  $VOLFS
	else
		echo "$VOLNAME not windows volume"
	fi
fi


Можно было бы еще исключать разделы FAT16, но решил не загромождать скрипт лишней проверкой.

Поиск загрузчика Windows


В функцию find_loader() передаются два параметра: путь к устройству (разделу) и его файловая система.

1. Заведем переменную-флаг, указывающую, был ли раздел временно смонтирован
TMPMOUNT=0

2. Получаем выхлоп команды mount. grep'ом фильтруем вывод по соответствующему разделу, с помощью awk вытаскиваем точку монтирования.

MOUNTPOINT=`mount|grep -w "$1"|awk '{print $3}'`

3. Если переменная MOUNTPOINT пустая, раздел не смонтирован. Создаем временную точку монтирования, пытаемся смонитровать раздел, если получилось - устанавливаем TMPMOUNT=1, в переменную MOUNTPOINT записываем временную точку монтирования и приступаем к поиску загрузчика, если не получилось - выходим из функции:

if [ -z "$MOUNTPOINT" ]; then
	mkdir -p "/tmp/tmpmount"
	mount -t "$2" "$1" "/tmp/tmpmount"
	if [ $? -ne 0 ]; then
		echo "$1 not mounted"
		return
	fi
	MOUNTPOINT="/tmp/tmpmount"
	TMPMOUNT=1
fi


Примечание: ключ -p команды mkdir позволяет создать путь вместе со всеми подкаталогами, а если путь уже создан, то команда mkdir не выдаст ошибки, что путь уже существует.

Надо обратить внимание на то, что Windows нечувствительна к регистру имен файлов, так что загрузчик может быть и bootmgr и BOOTMGR, и даже BoOtMgR (аналогично и ntldr). Поэтому придется воспользоваться командой find.

find <path> -maxdepth 1 -iname <filename>

где:
<path> - путь к каталогу, с которого начинать поиск
-maxdepth - глубина поиска в подкаталогах (начиная с указанного в <path>, 1 - только каталог <path> без подкаталогов).
-iname - игнорировать регистр имени файла
<filename> - имя файла (или маска), который будем искать.

В данном случае надо обязательно установить -maxdepth 1, иначе будут большие тормоза, а при отмонтировании возможны глюки.

4. Ищем загрузчик Vista и выше и сохраняем выхлоп в переменную FOUND:

FOUND=`find "$MOUNTPOINT" -maxdepth 1 -iname "bootmgr"`

5. Если нашли (переменная FOUND не пустая), выводим соответствующее сообщение, если нет - ищем загрузчик Windows XP, и выводим сообщение в зависимости от того, нашли или нет:

if [ -n "$FOUND" ];then
	echo "$1: found bootmgr (Windows Vista and newer)"
else
	#ntldr - Win XP and older
	FOUND=`find "$MOUNTPOINT" -maxdepth 1 -iname "ntldr"`
	if [ -n "$FOUND" ];then
		echo "$1: found ntldr (Windows XP and older)"
	else
		echo "$1: Windows loader not found"
	fi
fi


6. Проверяем флаг TMPMOUNT, если он был установлен в 1, отмонтируем временно смонтированный раздел:

if [ $TMPMOUNT -eq 1 ]; then 
	sleep 1
	umount "/tmp/tmpmount"
fi


Результат работы скрипта


Запуск на тестовой машине с разделами FAT32/NTFS, но без установленной Windows:



Запуск на машине с установленной Windows 7:



Запуск на машине с установленной Windows XP



Скрипт целиком


На GitHub
На PasteBin

Источники


1. Определение файловой системы раздела диска в Linux Копия
2. Команда find в Linux Копия

Это репост с сайта http://tolik-punkoff.com
Оригинал: http://tolik-punkoff.com/2019/03/27/skript-dlya-poiska-zagruzchika-windows-iz-linux-okruzheniya/

Tags: , ,
Comments

Потому что GitHub и Pastebin удобнее, это сервисы в "обычном" интернете, и если кто-то вдруг захочет взять файл, то сможет просто пройти по ссылке, не заморачиваясь установкой дополнительного ПО.
---
Because GitHub and Pastebin are more convenient, these are services on the "regular" Internet, and if someone suddenly wants to take a file, they can simply follow the link, without bothering to install additional software.