http://mitroko.com
:: Тренировки sh/bash'иста...

В начало...

Приступим?

$ sudo cat /var/log/messages | tail -n 40 | grep "sd" | grep "[Rr]emovable

Понятно, что из всего вывода будет отфильтрованы только строчки содержащие "sd" и слова "removable" и "Removable".
Почему "строчки" а не "одна строка"?
Потому, что в 40 строк может вместиться два или три раза журналируемого блока текста о подключаемом устройстве. И мы получим три раза одно и тоже.
Чтобы предотвратить такое поведение - подрежем полученный хвост:

> $ sudo cat /var/log/messages | tail -n 40 | grep "sd" | grep "[Rr]emovable | tail -n 1

Получим на выходе искомую строку:

sd 2:0:0:0: [sda] Attached SCSI removable disk

Теперь избавимся от лишнего текста.
В этом нам поможет awk (gawk) Самое простое, что можно придумать - это:

$ awk -F"]" '{print $1}'

"Разрезать" фразу разделителями "]" и распечатать первую подстроку.

Вот, и искомая команда:

$ sudo cat /var/log/messages | tail -n 40 | grep "sd" | grep "[Rr]emovable | tail -n 1 | awk -F"]" '{print $1}' | awk -F"[" '{print $2}'

На выходе получим:

sda

Теперь еще один фокус, ради которого все это размусоливаливалось.
Переменная есть, есть отфильтрованное ее значение. Как записать?

Для записи в переменную вывода сторонних программ используют обратные кавычки - "`".
Наш скрипт теперь получает вторую строчку:

SDev=`sudo cat /var/log/messages | tail -n 40 | grep "sd" | grep "[Rr]emovable | tail -n 1 | awk -F"]" '{print $1}' | awk -F"[" '{print $2}'`

Проверить, что содержит переменная SDev просто.
Это делается командой echo..

Чтобы ты понял, как удобно работать в командной строке приведу еще один трюк.

> Команды могут выполняться последовательно и параллельно.
Чтобы выполнялись последовательно одна за другой - используй знак ";"

$ mkdir NewFolder; mkdir NewFolder/NewSubFolder; date > NewFolder/time;

Это же используется при построении многокомандного цикла или блока в одну строку.

Конструкция

if [ -x "/mnt/usb" ];
	then
		echo Good;
	else
		echo Bad;
fi

будет преобразована в:

$ if [ -x "/mnt/usb" ]; then echo Good; else echo Bad; fi

Чтобы "отпустить" выполнение процесса в свободное плавание и "освободить" вывод командной строки, достаточно добавить в конце команды знак "&"

$ play /home/lilo/sample.wav &

Теперь вернемся к нашим баранам: переменной и ее значении.
для теста вне скрипта все уже известно:

$ SDev=`sudo cat /var/log/messages | tail -n 40 | grep "sd" | grep "[Rr]emovable | tail -n 1 | awk -F"]" '{print $1}' | awk -F"[" '{print $2}'`; echo $SDev

Теперь поговорим о партициях.
Конечно, ты мог верно подметить, что в журнале появилась строка, где сообщили, что псевдоустройство sda имеет дочернее под-устройство sda1

Так мы приходим к еще одной известной "проблеме".
Некоторые флеш-диски отформатированы с таблицей FAT, а некоторые (например, устройства файловых систем мобильных телефонов) - нет!
Вот, у меня такая ситуация! С чем меня можно поздравить!
Флеш-диски видятся, как /dev/sda1, а при подключении телефона кабелем DKU-2 в гнездо USB, система его определяет, как диск, но без таблицы ФАТ.
Просто /dev/sda

Забавно, правда?

Но и это не главное! В журнале может и не появиться такой замечательной инормации от других флеш-дисков.
Информацию о том, на какое псевдоустройство будет завязан тот или иной флеш-накопитель, мы будем получать всегда!

Чтобы избежать службы в армии, неразберихи, что монтировать (/dev/sda или /dev/sda1), проанализируем псевдоустройство сами.

Команда fdisk поможет нам в этом.

$ sudo fdisk -l /dev/$SDev

На выходе получим:

Disk /dev/sda: 1050 MB, 1050146816 bytes
33 heads, 61 sectors/track, 254 cylinders
Units = cylinders of 2013 * 2048 = 4122624 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1               1         254     1022482    b  W95 FAT32

Вот, тебе и диск...

Отфильтруем:

$ sudo fdisk -l /dev/$SDev | grep "/dev/" | grep -v "Disk"

Получим:

/dev/sda1               1         254     1022482    b  W95 FAT32

Подгоним по ширине напильником, awk...

По-умолчанию, awk в роли разделителя берет пробел.

$ sudo fdisk -l /dev/$SDev | grep "/dev/" | grep -v "Disk" | awk '{print $1}'

Запишем в переменную.
Это будет нашей третьей строчкой скрипта.

VerifyDev=`sudo fdisk -l /dev/$SDev | grep "sd" | grep -v "Disk" | awk '{print $1}'`;

А, вот, если подключу телефон, то переменной VerifyDev ничего не присвоится. Так, как партиций у псевдоустройства не будет.

Это мы тоже обработаем.

Конструкция if будет такой:

if [ -n "$VerifyDev" ];
	then
		echo Good;
		...
	else
		echo Bad;
		...
if

Распознавать, есть ли у устройства таблица ФАТ или нет, мы научились и научились обрабатывать это.

Во время монтирования, утилита mount считывает сначала данные об устройстве в /etc/fstab, если оно там описано, а затем дополняет назначениями от пользователя.

Я бы хотел, чтобы любой флеш-носитель монтировался в одну директорию /mnt/usb.
Если указывать это в /etc/fstab, то получим конфликт двух строк.
Строки о /dev/sda и о /dev/sda1

Предлагаю скопировать /etc/fstab в /etc/fstab.orig
Затем "анализировать" журнал. Исходя из полученных данных, дописывать /etc/fstab необходимой строчкой и в конце - монтировать.

Вот, как это сделал я.
Думаю, дальше мусолить - бесполезно...

cp --reply=yes /etc/fstab.orig /tmp/fstab.new;

if [ -n "$VerifyDev" ]; then
	echo "$VerifyDev		/mnt/usb		auto	noauto,owner,kudzu,ro 0 0">>/tmp/fstab.new;
else
	echo "/dev/$SDev		/mnt/usb		auto	noauto,owner,kudzu,ro 0 0">>/tmp/fstab.new;
fi

sudo cp --reply=yes /tmp/fstab.new /etc/fstab
rm -rf /tmp/fstab.new
sudo mount -o iocharset=utf8 /mnt/usb

Я еще раз повторюсь. Пишу, не для изобретения велосипеда.
Есть демон automount, который за все это отвечает.

Но, как устроено - всегда узнать интересно. И попрактиковаться.
К тому же, как сравнить, какой из способов эффективнее?







This site is better to surf with Mozilla Firefox.

Mozilla Firefox Project