OpenWrt: установка программ на USB

Для установки объемных приложений во встроенной в устройство flash-памяти может не хватить свободного места, и тогда возникает предсказуемое желание держать “тяжелые” программы на внешнем подключаемом накопителе данных. Но тут сразу можно столкнуться с вопросом, а как их оттуда правильно запускать?

Настройка opkg

Для начала добавим в утилиту установки приложений opkg дополнительную точку для установки программ. Для этого дописываем в /etc/opkg.conf строку следующего вида:

dest usb /mnt/optware

Вместо /mnt указываем точку монтирования внешнего накопителя.

Теперь при установке приложений указываем дополнительный ключ -d так:

opkg -d usb install <...>

Линковка файлов

Главная проблема заключается в том, что программы и утилиты ищут свои компоненты и библиотеки по стандартным путям относительно корня файловой системы, а каталоги на внешнем накопителе среди них по понятным причинам отсутствуют. Вообще говоря, ничто не мешает добавить в PATH каталог /mnt/optware/bin, а в LD_LIBRARY_PATH – /mnt/optware/lib, но при этом все равно многие init-скрипты (да и не только они) будут предполагать хранение файлов конфигурации в именно корневом /etc, а отнюдь не в /mnt/optware/etc. Понятно, что переписывать все скрипты – это возможный, но далеко не самый оптимальный подход.

Для решения этой проблемы на просторах сети можно найти шелл-скрипт opkg-link:

#!/bin/sh
# Copyright (C) 2010 OpenWrt.org

COMMAND=$1
PACKAGE=$2

setdest () {
	for i in `grep dest /etc/opkg.conf | cut -d ' ' -f 3`; do
		if [ -f $i/usr/lib/opkg/info/$PACKAGE.list ]; then
			DEST=$i
		fi
	done
	if [ "x$DEST" = "x" ]; then
		echo "Can not locate $PACKAGE."
		echo "Check /etc/opkg.conf for correct dest listings";
		echo "Check name of requested package: $PACKAGE"
		exit 1
	fi
}

addlinks () {
	setdest;
	cat $DEST/usr/lib/opkg/info/$PACKAGE.list | while read LINE; do
	SRC=$LINE
	DST=`echo $SRC | sed 's%'$DEST'%%'`
	DSTNAME=`basename $DST`
	DSTDIR=`echo $DST | sed 's%/'$DSTNAME'%%'`
	test -f "$SRC"
	if [ $? = 0 ]; then
		test -e "$DST"
		if [ $? = 1 ]; then
			mkdir -p $DSTDIR
			ln -sf $SRC $DST
		else
			echo "Not linking $SRC to $DST"
			echo "$DST Already exists"
		fi
	else
		test -d "$SRC"
		if [ $? = 0 ]; then
			test -e $DST
			if [ $? = 1 ]; then
				mkdir -p $DST
			else
				echo "directory already exists"
			fi
		else
			echo "Source directory $SRC does not exist"
		fi
	fi
	done
}

removelinks () {
	setdest;
	cat $DEST/usr/lib/opkg/info/$PACKAGE.list | while read LINE; do
	SRC=$LINE
	DST=`echo $LINE | sed 's%'$DEST'%%'`
	DSTNAME=`basename $DST`
	DSTDIR=`echo $DST | sed 's%/'$DSTNAME'%%'`
	test -f $DST
	if [ $? = 0 ]; then
		rm -f $DST
		test -d $DSTDIR &amp;&amp; rmdir $DSTDIR 2&gt;/dev/null
	else
		test -d $DST
		if [ $? = 0 ]; then
			rmdir $DST
		else
			echo "$DST does not exist"
		fi
	fi
	done
}

mountdest () {
	test -d $PACKAGE
	if [ $? = 1 ]; then
		echo "Mount point does not exist"
		exit 1
	fi
	for i in $PACKAGE/usr/lib/opkg/info/*.list; do
		$0 add `basename $i .list`
	done
}

umountdest () {
	test -d $PACKAGE
	if [ $? = 1 ]; then
		echo "Mount point does not exist"
		exit 1
	fi
	for i in $PACKAGE/usr/lib/opkg/info/*.list; do
		$0 remove `basename $i .list`
	done
}

case "$COMMAND" in
	add)
		addlinks
		;;
	remove)
		removelinks
		;;
	mount)
		mountdest
		;;
	umount)
		umountdest
		;;
	*)
		echo "Usage: $0 "
		echo " Commands: add, remove, mount, umount"
		echo " Targets: , "
		echo "Example: $0 add kismet-server"
		echo "Example: $0 remove kismet-server"
		echo "Example: $0 mount /mnt/usb"
		echo "Example: $0 umount /mnt/usb"
		exit 1
		;;
esac
exit 0

Логика работы здесь довольно проста – по команде “opkg-link add” автоматически для всех файлов выбранного пакета будут созданы символьные ссылки в корневой файловой системе. Тогда с точки зрения системы пакет начнет выглядеть установленным обычным образом, а не на внешний накопитель. Следовательно, уходят все проблемы с несовпадением путей.

Настройка автозагрузки

Еще одним вполне логичным желанием было бы автоматически запускать находящиеся на накопителе программы при его подключении к устройству. Напишем для этого простой скрипт, реализующий своего рода “авторан”, и разместим его в /etc/hotplug.d/block:

#!/bin/sh
# Copyright (C) 2011 OpenWrt.org

blkdev=`dirname $DEVPATH`
if [ `basename $blkdev` != "block" ]
then
	case "$ACTION" in
		add)
			if [ -d /mnt/optware/etc/init.d ]
			then
				logger "initiating autorun"
				for SCRIPT in /mnt/optware/etc/init.d/*
				do
					if [ -x $SCRIPT ]
					then
						/bin/sh -l -c "$SCRIPT start"
					fi
				done
			fi
			;;
	esac
fi

Как можно заметить, о безопасности в такой реализации говорить не приходится, и подключение флешки со скриптом типа “rm -fr /”, размещенном в нужном каталоге, приведет к довольно печальным последствиям. Следите за содержимым подключаемых накопителей. :)

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

This entry was posted in Сеть и интернет and tagged . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>