Linuxで、USBメモリが挿されたことを検出して処理を実行したく、調べてみました。
- GNOMEが立ち上がっていると自動でマウントするので、マウントポイント(一般的には/media/disk)をポーリングする
- dmesgのログを解析する(/var/log/messagesに出されるkernelログあたりか)
- hotplugを使ってUSBメモリ挿入を検出
- dbusを使ってUSBメモリ挿入を検出
といった方法がありそうです。
ここで、1, 2,は周期的にポーリングするのでちょっと避けたい。
3.は簡単そうだったが、今後はdbusに一元化されるようなので、4.の方法が本命かな。とりあえず、dbus-monitorというコマンドがあるので、実行してからUSBを挿抜して調べます。
$ dbus-monitor --system : signal sender=:1.0 -> dest=(null destination) path=/org/freedesktop/Hal/Manager; interface=org.freedesktop.Hal.Manager; member=DeviceAdded string "/org/freedesktop/Hal/device/usb_device_XXX_XX_XXXXXXXXX" :
USBメモリを挿入すると、interface="org.freedesktop.Hal.Manager; member=DeviceAddedのDBusメッセージが複数回発生します。違いは、stringの内容です。
usb_device_XXX_XX_XXXXXXXXXX usb_device_XXX_XX_XXXXXXXXXX_if0 usb_device_XXX_XX_XXXXXXXXXX_if0_scsi_host usb_device_XXX_XX_XXXXXXXXXX_usbraw usb_device_XXX_XX_XXXXXXXXXX_if0_scsi_host_scsi_device_lun0 usb_device_XXX_XX_XXXXXXXXXX_if0_scsi_host_scsi_device_lun0_scsi_generic storage_serial_NNNN_XXXXXXXXXX volume_uuid_UUUU_UUUU
USBメモリは、SCSIデバイスを模擬するので、USBデバイスとしての認識後、SCSIとしての設定が行われて、storageとして認識されたあとに、diskとして認識されるという流れのようです。
ちなみに、ここで、/dev/disk/by-uuidディレクトリを見ると、
$ ls -l /dev/disk/by-uuid UUUU-UUUU -> ../../sda1 :
のように、DBusのメッセージで流れたvolume_uuid_UUUU_UUUUの部分と同じIDでデバイスファイル(へのシンボリックリンク)が作成されていました。
なお、XXXXやNNNN、UUUUは、メモリ個別にIDや名称が入ります。
ここで、GNOMEデスクトップを起動し、GNOMEによるUSBメモリの自動マウントが発生したときのdbus-monitor出力を見ると、以下のメッセージが関連していそうです。
signal sender=:1.0 -> dest=(null destination) path=/org/freedesktop/Hal/Devices/volume_uuid_UUUU_UUUU; interface=org.freedesktop.Hal.Device; member=PropertyModified int32 2 array [ struct { string "volume.mount_point" boolean false boolean false } struct { string "volume.is_mounted" boolean false boolean false } ]
ちなみに、GNOME上でアンマウント操作をすると、
signal sender=:1.0 -> dest=(null destination) path=/org/freedesktop/Hal/devices/volume_uuid_UUUU_UUUU; interface=org.freedesktop.Hal.Device; member=PropertyModified int32 2 array [ struct { string "volume.mount_point" boolean false boolean false } struct { string "volume.is_mounted" boolean false boolean false } ]
USBメモリを抜くと、
signal sender=:1.0 -> dest=(null destination) path=/org/freedesktop/Hal/Manager; interface=org.freedesktop.Hal.Manager; member=DeviceRemoved string "/org/freedesktop/Hal/devices/usb_device_XXX_XX_XXXXXXXXXX_if0_scsi_host_scsi_device_lun0_scsi_generic" :
と、member=DeviceRemovedとしてあとは同様のメッセージが流れます。
usb_device_XXX_XX_XXXXXXXXXX_if0_scsi_host_scsi_device_lun0_scsi_generic volume_uuid_UUUU_UUUU usb_device_XXX_XX_XXXXXXXXXX_if0_scsi_host_scsi_device_lun0 storage_serial_NNNN_XXXXXXXXXX usb_device_XXX_XX_XXXXXXXXXX_if0 usb_device_XXX_XX_XXXXXXXXXX usb_device_XXX_XX_XXXXXXXXXX_usbraw usb_device_XXX_XX_XXXXXXXXXX_if0_scsi_host