• Просто прекрасные чужие стихи

  • Чёрная Курица


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

    Ранее была описана процедура настройки php-интерпретатора и его автозапуск через rc.local. Для единичного сервиса - это, в принципе, еще допустимо, но при установке более сложных программ и библиотек, которые могут взаимодействовать друг с другом, такой вариант уже не является приемлемым. Изложим более корректный способ установки приложений на внешний USB-диск или флешку.


    Настройка 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:

    /mnt/optware/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 && rmdir $DSTDIR 2>/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:

    /etc/hotplug.d/block/50-autostart:

    #!/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 /", размещенном в нужном каталоге, приведет к довольно печальным последствиям. Следите за содержимым подключаемых накопителей. :)

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





  • Просто прекрасные чужие стихи

  • Чёрная Курица