http://qs321.pair.com?node_id=726364

renegadex has asked for the wisdom of the Perl Monks concerning the following question:

Hi! is there a way to detect a plugged usb flash drive or detect a cd inside the cd rom drive using Perl? I've been googling around and always end up with "how to mount a usb flash drive". I need a way to "scan" if a new usb / cd is inserted to the computer. Also I'm using Fedora 9.

Replies are listed 'Best First'.
Re: Detect Plugged USB Flash Drive / CD in CDROM Drive
by moritz (Cardinal) on Nov 27, 2008 at 10:51 UTC
    Most modern Linux systems come with some sort of framework for pluggable devices, usually udev or hotplug (or both, I've never quite understood the relation).

    Usually you can configure these monsters to run a program when such a new device is plugged in, and this program can also be a Perl script.

Re: Detect Plugged USB Flash Drive / CD in CDROM Drive
by Corion (Patriarch) on Nov 27, 2008 at 11:27 UTC

    I wrote DBD::WMI for that case. It only works under Windows, because WMI (or rather, WBEM) isn't as widespread elsewhere. I don't have the WMI query handy at the moment, but the links I have in DBD::WMI should point you towards the correct resources.

Re: Detect Plugged USB Flash Drive / CD in CDROM Drive
by zentara (Archbishop) on Nov 27, 2008 at 12:39 UTC
    I think you should google for "linux automount", set it up to run the automounter daemon, then you probably run a timer to check /etc/mtab. Or even more manually, you can tail /var/log/messages for the various messages.

    There is a difference in approach for detecting a cd insertion and a usb drive plugin. The cd would have to be mounted, (unless the situation is a usb cdrom drive getting plugged in). So you need to decide: do you want to look for actual mounts, or just the usb subsystem detecting an additional device, or both? Ubuntu does a good job of detection, maybe you should set it up and check out what it does?


    I'm not really a human, but I play one on earth Remember How Lucky You Are
Re: Detect Plugged USB Flash Drive / CD in CDROM Drive
by cdarke (Prior) on Nov 27, 2008 at 15:32 UTC
    You probably want to use an inotify on the /mnt or /media directory. Try Linux::Inotify (I have no experience of that module myself)
Re: Detect Plugged USB Flash Drive / CD in CDROM Drive
by Perlbotics (Archbishop) on Nov 27, 2008 at 21:40 UTC

    Hm, only some heuristics - very fragile, but maybe they work for you:

    Output of mount: a mounted CD/DVD has usually a filetype of iso9660 or udf and an ro attribute. USB sticks, -drives, iPods, etc. are often mounted with the flush attribute and might have filetype vfat (not sure: ntfs, msdos).

    pb> mount | perl -ne '@mnt = split /\s+/; print "Stick? $mnt[0] $mnt[2 +]\n" if $mnt[4] =~ /vfat|msdos|ntfs/ && $mnt[5] =~ /flush/;' Stick? /dev/sdd1 /media/BLUESTICK Stick? /dev/sde /media/IPOD pb> mount | perl -ne '@mnt = split /\s+/; print "CD/DVD? $mnt[0] $mnt[ +2]\n" if $mnt[4] =~ /udf|iso\d+/ && $mnt[5] =~ /ro/;' CD/DVD? /dev/sr0 /media/SOYLENT_GREEN CD/DVD? /dev/sr1 /media/IX0712
    .oO(mmmmmhhh Soylent Green™...)

    lsusb -v lists the USB devices currently attached but not necessarily mounted. Check e.g. for attribute bInterfaceClass 8 Mass Storage. Though, you might find empty memory card readers, iPODs, everything that has a filesystem interface...

    pb> lsusb -v 2>/dev/null | \ perl -ne '$dev=$_ if /^Bus/; print $dev if /bInterfaceClass\s+8\D/ +' Bus 002 Device 006: ID 05ac:1301 Apple Computer, Inc. Bus 002 Device 006: ID 05ac:1301 Apple Computer, Inc. Bus 002 Device 005: ID 1307:0163 Bus 002 Device 004: ID 05e3:070e Genesys Logic, Inc.

    Use with care.
Re: Detect Plugged USB Flash Drive / CD in CDROM Drive
by renegadex (Beadle) on Nov 28, 2008 at 04:40 UTC
    Hi! I tried to extract messages from the etc/mtab. Here's what I did, its very simple. I'm just beggining to learn RegEx, please bear with me hehe..
    sub scan_cddvd { # mtab file /etc/mtab # cd/dvd signature /dev/sr0 open(MYINPUTFILE, "</etc/mtab"); my $cddvd_path = 'not found'; while(<MYINPUTFILE>){ my($line) = $_; chomp($line); if($line =~ m/^\/dev\/sr/){ print "FOUND CD/DVD\n"; print $line , "\n"; #$line =~ /(\/media\/.*)\ /; $line =~ /(\/media\/\S+)\s+/; my $newline = $1; print $newline , "\n"; while($newline =~ m/\\040/){ $newline =~ s/\\040/ /; } print $newline , "\n"; $cddvd_path = $newline } } close MYINPUTFILE; return $cddvd_path; }
    I made a timer of some sort and calls this function to determine if a CD / DVD is inside the drive.works pretty ok. :D hehe. I would be applying the same concept with usb flash drives. Instead of looking for /dev/sr, I'd be looking for /dev/sdb hehe.hope it would work just fine.
    Mabuhay Civil Engineers! :D

      Your snipped might work for your PC only and you'll only see the last /dev/sr device - which might not be a CD or DVD at all. The following suggestion is only a tiny improvement:

      use strict; # returns list of CD/DVD mountpoints or empty list sub scan_cddvd { my @drives = (); my $mtabfile = "/etc/mtab"; open my $mtfh, "<", $mtabfile or die "cannot open $mtabfile - $!"; while( <$mtfh> ){ my ($dev, $mountpoint, $fstype, $options) = split /\s+/; next unless $fstype =~ /udf|iso\d+/ && $options =~ /ro\b/; #ro: the /ro/-test above should skip CDRW too $mountpoint =~ s/\\(0\d+)/chr(oct($1))/eg; # resolve oct chars push @drives, $mountpoint; } close $mtfh; return @drives; } print "o <", join(">\no <", scan_cddvd), ">\n";
      Things to note: uses strict; avoids "not found" as a special failure-indicator; returns list of mountpoints; expands all octal escapes; less HW-dependent (e.g. IDE, SCSI, SATA, ...), e.g. not restricted to /dev/sdb; tries a little harder to find a CD or DVD (iso/udf,ro), uses 3 param open and die; no globs (MYINPUTFILE); implicit use of $_; will fail for derviant mtab-formats; ...