Скрыть
Цель: при вставке устройства хранения данных вызывать цепочку баш скриптов, делающее с вставленным и отмонтированным носителем разные непотребства.
Реализация: Раньше для этого я использовал ivman, но чего-то он слишком громоздкий был. За основу взят комментер событий на питоне от radiofun, из которого вырезана часть составляющая комментарии (теперь комментируем события из баш скриптов, по мере надобности. На моей станции комментирует самописная прога на сях lsay ( проприетарный цепстраловский синтез + зажигание светодиодов в lpt в зависимости от амплитуды речи ))
Собственно сырец маунт манагера и комменты к нему ниже
python
#!/usr/bin/python
# -*- coding: utf-8 -*-
###########################################################################
# Event Commenter + automount via hal + bash handlers #
# ------------------------------ #
# copyright : © 2008 radiofun; © 2009 Necromant #
# jabber : [email protected] #
# jabber : [email protected] #
# #
###########################################################################
# #
# This program is free software; you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation; either version 2 of the License, or #
# (at your option) any later version. #
# #
###########################################################################
import gobject
import threading
import math
import dbus
import dbus.mainloop .glib
import os
handler_script = "/home/aifiltr0/.config/NMountManager/storage_handler.sh"
class NMountMgr( ) :#threading.Thread):
def __init__ ( self ) :
#threading.Thread.__init__(self)
self .__bus = dbus.SystemBus ( )
self .__hm = self .__bus.get_object ( 'org.freedesktop.Hal' ,'/org/freedesktop/Hal/Manager' )
self .__hm.connect_to_signal ( 'DeviceAdded' , self .deviceAdded )
self .__hm.connect_to_signal ( 'DeviceRemoved' , self .deviceRemoved )
self .handler_script = handler_script
self .__connectedDevices = dict ( ) ;
def deviceAdded( self , devID) :
device = dbus.Interface ( self .__bus.get_object ( "org.freedesktop.Hal" , devID) ,
"org.freedesktop.Hal.Device" )
exec_line = self .__prepareAction( device)
if len ( exec_line) > 0:
self .__connectedDevices[ devID] =exec_line
os .system ( self .handler_script + " connect " + exec_line) ;
def deviceRemoved( self , devID) :
if devID in self .__connectedDevices:
exec_line = self .__connectedDevices.pop ( devID)
os .system ( self .handler_script + " disconnect " + exec_line) ;
#self.__say(message);
#prepare device comment!
def __prepareAction( self , device) :
exec_line = ""
if device.PropertyExists ( 'info.capabilities' ) :
isCD = device.QueryCapability ( 'volume.disc' )
#if "volume"
if device.QueryCapability ( 'volume' ) and not isCD:
size =self .__getHumanReadableSize( device.GetProperty ( 'volume.size' ) )
label = device.GetProperty ( 'volume.label' )
if len ( label) < 1 :
label = device.GetProperty ( 'volume.fsversion' )
#message += "Volume connected: label is " + label + ", Total size "+ size
#device.Mount(label,"rw");
uuid = device.GetProperty ( 'volume.uuid' )
uuid = uuid.replace ( "-" ,"_" )
vol = self .__bus.get_object ( 'org.freedesktop.Hal' , '/org/freedesktop/Hal/devices/volume_uuid_' + uuid)
#Dirty hack for vfat unicode mount
#
if ( device.GetProperty ( 'volume.fstype' ) =='vfat' ) :
mopts=( "utf8" ,"uid=1000" ,"shortname=mixed" ) ;
else :
mopts=( "uid=1000" ) ;
vol.Mount ( '' , device.GetProperty ( 'volume.fstype' ) , mopts , dbus_interface="org.freedesktop.Hal.Device.Volume" )
mpoint = device.GetProperty ( 'volume.mount_point' )
exec_line = " volume \" " + mpoint + "\" \" " + label + "\" " + uuid
# if CD or dvd
# I have no cd/dvd on my netbook, so the following is not well tested
if isCD:
label = ""
if device.GetProperty ( 'volume.disc.has_audio' ) :
label += " audio "
if device.GetProperty ( 'volume.disc.is_blank' ) :
label += " empty "
label += device.GetProperty ( 'volume.disc.type' ) + " "
label += device.GetProperty ( 'volume.label' )
uuid = device.GetProperty ( 'volume.uuid' )
uuid = uuid.replace ( "-" ,"_" )
vol = self .__bus.get_object ( 'org.freedesktop.Hal' , '/org/freedesktop/Hal/devices/volume_uuid_' + uuid)
vol.Mount ( '' , device.GetProperty ( 'volume.fstype' ) , "" , dbus_interface="org.freedesktop.Hal.Device.Volume" )
mpoint = device.GetProperty ( 'volume.mount_point' )
exec_line = " cd \" " + mpoint + "\" \" " + label + "\" " + uuid
#if storage
elif device.QueryCapability ( 'storage' ) :
#message += 'Device connection detected: '
#message += self.__getDeviceName(device) + " storage"
exec_line = "stgdev \" " + self .__getDeviceName( device) + "\" "
#это должно быть саммы последним!
elif ( device.PropertyExists ( 'linux.subsystem' )
and ( device.GetProperty ( 'linux.subsystem' ) == 'usb' ) ) :
category = device.GetProperty ( 'info.category' )
devName = self .__getDeviceName( device)
#message += devName + " " + category
exec_line = "usbdev \" " + self .__getDeviceName( device) + "\" "
return exec_line
# in uint64!
def __getHumanReadableSize( self , size) :
dim = int ( math .log ( size, 1024) )
result = {
0 : lambda x: str ( x) + ' bytes' ,
1 : lambda x: str ( int ( x/1024 +0.5 ) ) + ' kilobytes' ,
2 : lambda x: str ( int ( x/1.048576e6+0.5 ) ) + ' megabytes' ,
3 : lambda x: str ( int ( x/1.073741824e9+0.5 ) ) + ' gigabytes'
} [ dim] ( size)
return result
def __getDeviceName( self , device) :
result = ""
if device.PropertyExists ( 'info.vendor' ) :
result = device.GetProperty ( 'info.vendor' ) + " "
if device.PropertyExists ( 'info.product' ) :
result += device.GetProperty ( 'info.product' )
else :
result += "unknown"
return result
def __say( self , text) :
#pipe = os.popen('espeak -vmb/mb-fr4-en -s 150 -a 100','w')
pipe = os .popen ( 'lsay \' ' + text+ '\' ' ,'w' )
print text
#pipe.write(text)
pipe.close ( )
def __del__ ( self ) :
self .__bus.close ( )
dbus.mainloop .glib .DBusGMainLoop ( set_as_default=True )
ec = NMountMgr( )
mainloop = gobject.MainLoop ( )
mainloop.run ( )
В самом начале поправьте урл скрипта-хэндлера. у меня он на баше, но Вы можете его на чем угодно делать. Его задача минимальна, исходник привожу ниже. из папки handler_dir (не забудьте выставить свою!) Вызывает все скрипты предварительно установив полученные аргументы в переменные к которым легко обращаться и export’нув их.
bash
#!/bin/bash
handler_dir ="/home/aifiltr0/.config/NMountManager/stg_handlers.d/"
report( )
{
kdialog --passivepopup "$1" --title "NMountManager" &
lsay "$1"
}
#Comment this if you do not want reports about what is connected
early_report( )
{
report $1
}
export report
echo $1 $2 $3 $4 $5
ACTION =$1
export ACTION
TYPE =$2
export TYPE
case "$TYPE " in
volume)
MPOINT =$3
LABEL =$4
UUID =$5
export MPOINT
export LABEL
export UUID
if [ $ACTION == "connect" ] ; then
report "A new storage volume has been connected. Label is $LABEL . I have attached it to $MPOINT "
else
report "Storage volume $LABEL removed"
fi
;;
cd )
MPOINT =$3
LABEL =$4
UUID =$5
export MPOINT
export LABEL
export UUID
if [ $ACTION == "connect" ] ; then
report "A compact disk has been inserted. Label is $LABEL . I have attached it to $MPOINT "
else
report "Compact disk ejected."
fi
;;
stgdev)
DEVICENAME =$3
export DEVICENAME
if [ $ACTION == "connect" ] ; then
report "A storage device called $DEVICENAME has been connected. "
fi
;;
usbdev)
DEVICENAME =$3
export DEVICENAME
if [ $ACTION == "connect" ] ; then
report "A USB device called $DEVICENAME has been connected. "
else
report "A USB device called $DEVICENAME has been disconnected. "
fi
;;
esac
BROWSEABLE =0
if [ $ACTION == "connect" ] ; then
if [ $TYPE == "cd" ] ; then
echo "cd"
BROWSEABLE =1
fi
if [ $TYPE == "volume" ] ; then
echo "vol"
BROWSEABLE =1
fi
fi
export BROWSEABLE
echo "$ACTION TYPE: $TYPE MPOINT=$MPOINT LABEL=$LABEL UUID=$UUID BROWSEABLE=$BROWSEABLE "
cd $handler_dir
rm * ~
for file in ` ls ` ; do
. $file
done ;
В папке с хэндлерами мы можем складывать свои баш скрипты на все случае жизни. Из каждого скрипта нам доступно: $ACTION – connect или disconnect $TYPE – тип устройства: usbdev, stgdev, cd, volume. Последние два монтируются автоматом, а куда именно – узнать можем через $MPOINT. Там путь к точке монтирования. $BROWSEABLE – это для ленивых, чтобы не проверять несколько разом и сэкономить на ифе: Если 1 – значит нечто отмонтировано и в $MPOINT можно минимум почитать данные. usbdev и stgdev выставляют $DEVICENAME, для cd и volume есть еще $LABEL и $UUID, так что свои флешки распознатиь легко.
Вот примеры простых скриптов-хэндлеров: Этот проверяет по ууиду (ам) моя ли эта флешка и экспортирует переменную STG_OWNER.
bash
#!/bin/bash
# This script checks who does this storage belong to.
# And exports a variable
# This can be: 0 - ours 1 - foreign, quite simple, but nevertheless
stg_pdacard =B4DC_999E
verify_storage( )
{
for dev in $@ ; do
if [ "$dev " == "$UUID " ] ; then
echo "$dev matched owner list!"
return 0 ;
fi
done ;
return 1
}
if [ $BROWSEABLE -eq "1" ] ; then
verify_storage $stg_pdacard
STG_OWNER =$?
echo "OWNER IS: $STG_OWNER "
export STG_OWNER
fi
Я задолбался сносить с флешки автораны с вирусней, когда попользую ее на вендовозных машинах в инсте. Надо бы написать парсер авторан.инфа чтобы еще и сообразить где лежит вирусня, но лень.
bash
#!/bin/bash
#ToDo: Properly parse ini file to locate the f*cking shit
echo "==> $ACTION $TYPE "
if [ $ACTION == "connect" ] ; then
if [ $TYPE == "volume" ] ; then
if [ -e $MPOINT / autorun.inf ] ; then
report "Security alert! The removable device has probably been infected and is dangerous for windows systems. Initiating disinfection sequence."
rm $MPOINT / autorun.inf
report "Disinfection complete"
fi
fi
fi
Коммуниздим потихоньку музочку с флешек друзей в фоновом режиме. Всю, какую находим и складываем в ~/msx4sort/UUID. Зависит от первого скрипта-хэндлера, который проверяет наша ли это флешка и если наша – то игнорирует. (свою-то музыку нафига копировать?)
bash
#!/bin/bash
#This script make sure you get all the mp3 from a flash drive of your friend without him/her ever noticing it
#Just make sure you fill in the data required
TARGET_DIR =~/ msx4sort/
sync_type( )
{
echo "`pwd` $1"
find . -iname $1 | while read FILE; do
if [ -f "$FILE " ] ; then
if [ ! -f "$TARGET_DIR $FILE " ] ; then
cp --parents "$FILE " "$TARGET_DIR "
echo "==>" $FILE
fi
fi
done
}
if [ $BROWSEABLE -eq "1" ] ; then
if [ $STG_OWNER ! = "0" ] ; then
report "Music leech in progress."
mkdir $TARGET_DIR $UUID
TARGET_DIR =$TARGET_DIR $UUID
cd $MPOINT
sync_type \* mp3
sync_type \* ogg
sync_type \* avi
sync_type \* flv
else
echo "skipping owned devices"
fi
fi
Ну и на последок: автоматом скопировать фотографии с карточки фотика, которую определяем по ууид.
bash
#!/bin/bash
target_dir ="/home/aifiltr0/Фотографии"
target_vid_dir ="/home/aifiltr0/кЫно/видеозаписи/с коммуникатора"
if [ $BROWSEABLE -eq "1" ] ; then
if [ $UUID == "B4DC_999E" ] ; then
report "This is your smartphone's card. Multimedia data transfer in progress."
cd "$MPOINT /My Pictures"
for file in ` find . -iname \* jpg` ; do
mv "$file " "$target_dir /$file "
done ;
cd "$MPOINT /My Videos"
for file in ` find . -iname \* 3gp` ; do
mv "$file " "$target_vid_dir /$file "
done ;
report "Transfer complete"
fi
fi
Все скрипты пронумерованы, то есть в имени в лучших традиция 00, 01, 02 в самом начале. Так можно задать очередность выполнения. Все. спасибо radiofun за начальный скрипт.
З.Ы. Там в самом первом баш скрипте определен report() так как я кдешник, вывожу сообщения через kdialog и на синтез речи. гномерам и прочим просто поправить и все будет ку. Не забудьте на всех скриптах сделать chmod +x ну и запускать ./mount_manager.py при загрузке. Вот собственно и все, хотя по хорошему надо бы еще и код подчистить местами.
Автор статьи AiFiLTr0
Репост статьи с http://invyl.ath.cx:8080/wp/?p=35