Цель: при вставке устройства хранения данных вызывать цепочку баш скриптов, делающее с вставленным и отмонтированным носителем разные непотребства.
Реализация: Раньше для этого я использовал ivman, но чего-то он слишком громоздкий был. За основу взят комментер событий на питоне от radiofun, из которого вырезана часть составляющая комментарии (теперь комментируем события из баш скриптов, по мере надобности. На моей станции комментирует самописная прога на сях lsay ( проприетарный цепстраловский синтез + зажигание светодиодов в lpt в зависимости от амплитуды речи ))
EDIT: Вордпресс нещадно корябает форматирование, так что вот ссыль на архив с ними: http://invyl.ath.cx:8080/files/nmm.tar.gz
Собственно сырец маунт манагера и комменты к нему ниже
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | #!/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’нув их.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | #!/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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #!/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 |
Я задолбался сносить с флешки автораны с вирусней, когда попользую ее на вендовозных машинах в инсте. Надо бы написать парсер авторан.инфа чтобы еще и сообразить где лежит вирусня, но лень.
1 2 3 4 5 6 7 8 9 10 11 12 | #!/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. Зависит от первого скрипта-хэндлера, который проверяет наша ли это флешка и если наша — то игнорирует. (свою-то музыку нафига копировать?)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #!/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 |
Ну и на последок: автоматом скопировать фотографии с карточки фотика, которую определяем по ууид.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #!/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 при загрузке.
Вот собственно и все, хотя по хорошему надо бы еще и код подчистить местами.
Я перепосчу статью на ЛОРНГ
> Я перепосчу статью на ЛОРНГ
Дык тама уже я отпостил!
Для CD DVD надо поправить =)
строчка № 90
vol = self.__bus.get_object(‘org.freedesktop.Hal’, ‘/org/freedesktop/Hal/devices/volume_uuid_’ + uuid)
я заменил на
mdm_cd_dvd = device.GetProperty(‘volume.label’)
vol = self.__bus.get_object(‘org.freedesktop.Hal’, ‘/org/freedesktop/Hal/devices/volume_label_’ + mdm_cd_dvd)
Бо в хале с сидюками и дивидюками по ууиду не работают.
ЗЫ lshal откроет глаза.
Угу, спасибо сейчас внесу. просто делалось на нетбуке где привода нет, да и не пользуюсь я болванками практически.
еще лучше будет вот как сделать:
# if CD or dvd
# I have no cd/dvd on my netbook, so the following is not well tested
if isCD:
label = «»
mpoint = «»
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(«-«,»_»)
#mdm_cd_dvd = device.GetProperty(‘volume.label’)
if not device.GetProperty(‘volume.disc.is_blank’):
vol = self.__bus.get_object(‘org.freedesktop.Hal’, ‘/org/freedesktop/Hal/devices/volume_label_’ + label)
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
Это позволит не монтировать пустые болванки.
ЗЫ я потихонечку буду доводить до ума =)
хочу прикрутить еще и блютуз.
Тогда стукнись мне в жаббер. aifiltr0 (at) invyl.ath.cx Сообразим на двоих что можно допилить и как.
)))))))))) я вам не могу поверить 🙂