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