USB Stick - Mounted detection

Hello.

Using udev tools I know nearly every things about my usb stick.
With udev rule, I can tell when a specific usb stick is inserted or remove using its id ( ex : usb-Multiple_Card_Reader_058F63666438-0:0-part1 ).

I have not found myself a rule to tell when it is really mounted ( files and folders are accessible ).
I need that rule to trigger a systemd service of mine.

Any help is welcome.

This command will show you what is mounted

systemctl list-units --type mount

For example, I have a memory stick labelled T9I11A (vfat filesystem). When it is mounted via udisks (desktop-mounting), the above command will report

run-media-dean-T9I11A.mount    loaded active mounted /run/media/dean/T9I11A

and of course it will be reported via ‘mount’ command like this

/dev/sdb1 on /run/media/dean/T9I11A type vfat (rw,nosuid,nodev,relatime,uid=1000,gid=100,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,showexec,utf8,flush,errors=remount-ro,uhelper=udisks2)

I could write a custom unit (/etc/systemd/system/mount-trigger.service) like this


[Unit]
Description=My custom mount-trigger script
Requires=run-media-dean-T9I11A.mount
After=run-media-dean-T9I11A.mount

[Service]
ExecStart=/path/to/your/custom-script.sh

[Install]
WantedBy=run-media-dean-T9I11A.mount

Don’t forget to enable and start the custom service.

Hope this helps.

Thank you for your quick answer.
I have tried already something like that (Failed to run) but in addition the problem is that is user dependent.
I look something just hardware dependent or if I can use a variable to replace (in your example) dean by $(logname).
I have tried to use ( in systemd notation ) dev-disk-by-uuid-12BD3AE67CF89 in WantedBy,Requires et After but I got syntax error.
Do you have any ideas that I can develop?

I have:

karl@erlangen:~> grep GARMIN /etc/fstab 
UUID=6914-84F3                             /GARMIN                 vfat   user,noauto                   0  0
karl@erlangen:~> ll /GARMIN/
insgesamt 8
-rwxr-xr-x  1 root root   94 13. Dez 2016  autorun.inf
drwxr-xr-x 13 root root 4096 14. Apr 2020  Garmin
karl@erlangen:~> 

For monitoring see man systemd.path.

In this case consider having removable devices mount to /media instead (for shared filesystems)…
https://wiki.archlinux.org/index.php/Udisks#Mount_to_/media_(udisks2)

Once the necessary rule is in place (99-udisks2.rules)

ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{UDISKS_FILESYSTEM_SHARED}="1"

you’ll find that the mount looks more like this

media-T9I11A.mount            loaded active mounted /media/T9I11A

ie not user-specfic, so the unit file can be more generic too…


[Unit]
Description=Custom mount-trigger service
Requires=media-T9I11A.mount
After=media-T9I11A.mount

[Service]
ExecStart=/path/to/your/custom-script.sh

[Install]
WantedBy=media-T9I11A.mount

That should do the trick. :wink:

It indeed does:

erlangen:~ # systemctl list-unit-files GARMIN.*
UNIT FILE      STATE    
GARMIN.mount   generated
GARMIN.service enabled  

2 unit files listed.
erlangen:~ # systemctl cat GARMIN.mount 
# /run/systemd/generator/GARMIN.mount
# Automatically generated by systemd-fstab-generator

[Unit]
SourcePath=/etc/fstab
Documentation=man:fstab(5) man:systemd-fstab-generator(8)
Before=local-fs.target

[Mount]
Where=/GARMIN
What=/dev/disk/by-uuid/6914-84F3
Type=vfat
Options=user,noauto

erlangen:~ # systemctl cat GARMIN.service 
# /etc/systemd/system/GARMIN.service
[Unit]
Description=Get Garmin tracks
Requires=GARMIN.mount
After=GARMIN.mount

[Service]
ExecStart=/usr/bin/rsync -av /GARMIN/Garmin/GPX/ /home/karl/Dokumente/etrex/GPX/

[Install]
WantedBy=GARMIN.mount
erlangen:~ # 

erlangen:~ # journalctl -b -u GARMIN.service 
-- Logs begin at Sun 2020-03-29 16:41:11 CEST, end at Wed 2020-04-15 07:51:51 CEST. --
Apr 15 07:50:50 systemd[1]: Started Get Garmin tracks.
Apr 15 07:50:50 rsync[5166]: sending incremental file list
Apr 15 07:51:03 rsync[5166]: Current/Current.gpx
Apr 15 07:51:05 rsync[5166]: sent 109,177 bytes  received 40 bytes  7,532.21 bytes/sec
Apr 15 07:51:05 rsync[5166]: total size is 80,908,749  speedup is 740.81
Apr 15 07:51:05 systemd[1]: GARMIN.service: Succeeded.
erlangen:~ # 

Thank you for your interest.
But I would like to avoid changing anywhere ‘/etc/fstab’ whenever I enable or disable a flash drive.

I will try that.
I will give news as soon as possible.

By the way, can you tell me where is(are) the rules(s) which tell udisks2 to mount usb disks in ‘/run/media/$USER/LABEL_OF_THE_USB_DISK’.
I have not found any config file(s) mentioned in man udisks
I have also search for the string ‘UDISKS_FILESYSTEM_SHARED’ in /etc and /usr and not found any place.
Any help is welcome

The udisks2 rules file is /usr/lib/udev/rules.d/80-udisks2.rules (the mounting location is handled within udisks2 code)

man udisks

In particular

UDISKS_FILESYSTEM_SHARED
If set to 1, the filesystem on the device will be mounted in a shared directory (e.g. /media/VolumeName) instead of a
private directory (e.g. /run/media/$USER/VolumeName) when the Filesystem.Mount() method is handled.

Yes, best left to udev/udisks for removable media handling.

I have also search for the string ‘UDISKS_FILESYSTEM_SHARED’ in /etc and /usr and not found any place.

Just to clarify here that you need to create a custom udev rules file as I explained earlier in this thread.

I buy a GARMIN device and add it to /etc/fstab once. Whenever I plug it into USB the GARMIN gets mounted and new GPX data are transferred automatically. After a few years the drive has become obsolete. I buy a new one and fix the UUID in /etc/fstab. Any shorter and simpler procedure available?

You could just let the desktop environment mount it automatically when connected.

What you currently get is (changes were made through decades):

erlangen:~ # lsblk /dev/sdc
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sdc      8:32   1 14.2M  0 disk 
└─sdc1   8:33   1 14.2M  0 part **/run/media/karl/111A-3A00**
erlangen:~ # 

I used ‘yast2 partitioner’ to improve on that, see https://forums.opensuse.org/showthread.php/539891-USB-Stick-Mounted-detection?p=2932978#post2932978

The GARMIN is a partition which is treated the same way as /, /boot/efi, /home and others. No need to dive into udev rules. Yast GUI does the trick.

I think you’ve missed the whole point of this thread. The OP is wanting to detect a particular ‘auto-mounted’ removable device. However, they also didn’t want it to be user-specific. The udev rule was ONLY used to cause the ‘shared’ removable device to then be mounted to ‘/media/…’. To clarify further, it does not do the mounting - that is done by the desktop environment. :wink:

I have understood the direction you gave me earlier in the thread.
But I was imagining if :

UDISKS_FILESYSTEM_SHARED

==1: mount filesystem to a shared directory (/media/VolumeName)

==0: mount filesystem to a private directory (/run/media/$USER/VolumeName)

See udisks(8)

I would find a rule somewhere event if ‘/run/media/$USER/VolumeName’ is the default rule.

Ok this particular point is closed for me.

Exactly what I try to do.

I have a problem with systemd. I am preparing a question with a very simple example.

Ok. I’m sure we’ll be able to be of further guidance. :slight_smile:

During one of my tests I use this configuration :
( Don’t pay attention to the file name of unit.path and unit.service. I have use the same files for different criteria)

USB LABEL : ‘BESTRUNNER-8Go-14’

FILE 1 : THIS_IS_THE_TRIGGER_FILE.txt
Location : on the usb stick : /run/media/user_install/BESTRUNNER-8Go-14
Each time it is modified then saved, it is suppose to trigger my systemd unit.

FILE 2 : trigger.sh
Location : in home user : /home/user_install/bin
Activated each time the unit.service is triggered : write text to a tmp file

/usr/bin/date >> /tmp/udev.log

FILE 3 : USB_TEST_is_mounted.path
Location : /etc/systemd/system
Activate the configured unit paired whenever a change occured, when the file which was open for writing gets closed.

#    /etc/systemd/system/USB_TEST_is_mounted.path
#                                                #

[Unit]
Description=Trigger the systemd unit paired when the monitored file have changed :  THIS_IS_THE_TRIGGER_FILE.txt

[Path]
PathChanged=/run/media/user_install/BESTRUNNER-8Go-14/THIS_IS_THE_TRIGGER_FILE.txt
Unit=USB_TEST_is_mounted.service

[Install]
WantedBy=multi-user.target

FILE 4 : USB_TEST_is_mounted.service
Location : /etc/systemd/system
This unit is triggered by the paired unit.path

#    /etc/systemd/system/USB_TEST_is_mounted.service

[Unit]
Description=Executes script when   'THIS_IS_THE_TRIGGER_FILE.txt'    has changed.

[Service]
Type=simple
ExecStart=/home/user_install/bin/trigger.sh

[Install]
WantedBy=multi-user.target


This works as the documentation indicates, with one detail: after about ten tests, the name of the mountpoint has changed.
Normally I got ‘/run/media/user_install/BESTRUNNER-8Go-14/…/…’. But after a while I got ‘/run/media/user_install/BESTRUNNER-8Go-141/…/…’ or ‘/run/media/user_install/BESTRUNNER-8Go-142/…/…’
Even after multiple reboot.
That mean that under certain circumstances, we could not rely on /run/media/$USER/USB_LABEL/…/…

Any comment is welcome