Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Bind mounts with an OpenRC service
Davyd McColl
Davyd McColl

Posted on

     

Bind mounts with an OpenRC service

Recently, Windows 10 is refusing to connect to my SMB service on my desktopGentoo Linux machine. It basically refuses to use anything other than domain auth, and my Gentoo machine doesn't know anything about a domain, most especially my work domain (which is what the laptop wants to use --.\username doesn't seem to help, and giving my Gentoo machine's name as the domain doesn't help either, most likely because I don't have a domain controller running -- and I really don't need one at home).

After about 1/2 an hour of trying to convince the Windows machine to connect to SMB shares it had had no problem with a few months ago (before the last Great Windows Update), I thought "stuff it, I'll just go old-school and install VSFTPD on my Gentoo machine so I can copy some stuff off to watch during the impending load-shedding".

For those of you lucky enough not to live in South Africa, "load-shedding" is a phenomenon where the state-owned electricity provider, due to rampant corruption and mismanagement for the last 20 years, is unable to provide power to the entire country, so, for fear of rolling blackouts caused by overloading the grid, certain neighborhoods are literally turned off for two hours at a time.

Yes, it's about as much fun as it sounds. Fortunately, I have a nice laptop and plenty of media stored offline. I just have to get the media onto the laptop. Hence the fun with connections.

Now,VSFTPD (the Very Secure File Transfer Protocol Daemon) lives up to its name: it's Very Secure. Part of that security is that users who log in to the server -- even the anonymous user -- are confined to a chroot jail so that they cannot possibly access files outside of their allowed domain. This works quite well for regular users, who are confined to their home folders by default, as well as the anonymous user, who is also confined to a special place on disk. The problem comes in when you'd like to allow access tosome parts of the filesystem: VSFTPD does not follow symlinks (for security reasons), so I can't just symlink in my media drives. Another plan has to be made.

The generally accepted answer is to usebind mounts, which worked, but leaving these mounts in/etc/fstab as auto-mounting resulted in odd behavior: after booting, the mounts wouldn't be showing the same contents as the folders they were linked against. If I unmounted and remounted them, they worked just fine. I have a feeling they were being mountedbefore their targets were being mounted, perhaps because my original script, run via cron at@reboot wasn't waiting for local mounts to complete.

So first attempt was to:

  • set the mounts asnoauto
  • alter my hacky script to do the mounting for me
    • that script could take arguments like-d 120 to delay the mounting
  • add this as a@reboot line in my crontab for root (withcrontab -e)

here it is (don't judge me! I know it's hacky! I was trying to figure out wtf was going on, and I also was getting tired of debugging this issue with only a few minutes until the power is cut, and no media to watch on my laptop (: ):

#!/bin/shBASE=/var/ftp/pubLAST=""DELAY=0whiletest!-z"$1";do  iftest-z"$LAST";thenLAST="$1"else    iftest"$LAST"="-d";thenDELAY="$1"fiLAST=""fishiftdoneiftest"$DELAY"!="0";thenecho"delaying by$DELAY seconds"sleep$DELAYfiformin$BASE/*;doumount$m &> /dev/nulliftest-z"$(mount |grep$m)";thenmount$melseecho"Unable to (re-)mount$m: already mounted and umount denied"fidone

If you're new to bash, the while loop at the top, with theshift command near the end, is a way of cycling through arguments provided to the script until we run out:

  • shift, like Javascript'sArray.prototype.shift, removes the first element from the array of arguments that this script was invoked with
  • test ! -z "$1" tests the first argument in the args list to see if it's empty -- so once all arguments have been shifted off,$1 is empty (:

I figured someone else might like to have a look at the OpenRC init script:

  • it's an example of how simple OpenRC scripts can be, unlike the dumpster-fire that is systemd 🔥
    • all flaming aside: everything sucks in its own special way, so I'm sure OpenRC isn't perfect -- but systemd has so many "features" which make me dislike it intensely
  • it's an example of
    • line-by-line file reading with bash
    • some of the simplest, but very powerful GNU utils
      • awk
      • grep
#!/sbin/openrc-rundepend(){  need localmount}start(){forMOUNT_POINTin$(find_bind_mounts);dodo_mount$MOUNT_POINTdone}stop(){forMOUNT_POINTin$(find_bind_mounts);dodo_umount$MOUNT_POINTdone}do_mount(){iftest-z"$(mount |grep-E"\s$1\s")";thenecho"  mount$1"      mount$1elseecho"  already mounted:$1"fi}do_umount(){iftest-z"$(mount |grep-E"\s$1\s")";thenecho"  already unmounted:$1"elseecho"  umount$1"      umount$1fi}find_bind_mounts(){whilereadLINE;doOPTS="$(echo$LINE |awk'{print $4}' |grep-E'(,)?bind(,)?')"iftest-z"$OPTS";then      continue    fiecho$LINE |awk'{print $2}'done < /etc/fstab}

Some explanations:

  1. This script should be run with/sbin/openrc-run (see the hash-bang line) because that stub provides a lot of base functionality:
    • provides defaultstart,stop andstatus functions
    • understands how to get dependencies fromdepend()
  2. we declare services that this one depends on in thedepend function, one per-line. Simple!
  3. OpenRC scripts can be as short as just a few lines long because there are default implementations forstart,stop andstatus (see here:https://github.com/OpenRC/openrc/blob/master/service-script-guide.md
    • in this case though, I'm not starting a daemon process: I want to do some work at startup and some more at shutdown, so I implementstart andstop myself
  4. fromstart() andstop()
    • while read LINE; do echo $LINE; done < some_file is how you can work over a file line-by-line in bash. Now you know (:
  5. fromfind_bind_mounts()

    • awk '{print $1}' prints the first field found on a line -- this is a really simple way to get a field out of a line which is broken up by whitespace -- like fstab entries! Field 4 in /etc/fstab describes the mount options...
    • so bind mounts will havebind in there somewhere. Now we need to invokegrep with-E to use Extended syntax and the regex I'm using searches for the word "bind" preceded either by whitespace or a comma, and followed either by whitespace or a comma, so matches would be, eg:auto,bind,bind,noatime,noauto ornoatime,bind,noauto, remembering that the mount options field isnot the last field, so there would be whitespace before and after it.

      • we get lines like:
      /mnt/monolith /var/ftp/pub/monolith none defaults,bind,noauto 0 0
  • once we have a line describing a bind mount, we select out the second field withawk, since this is the directory into which we would be mounting, so the shorthand syntax ofmount <mount-point> would work
    • from the above line, we would get/mnt/monolith
  1. fromdo_mount() anddo_umount()
    • just to be safe, we check if the mount point retrieved from/etc/fstab is already mounted withmount | grep -E "\s$MOUNT_POINT\s", which would look for that mount-point by name, surrounded by whitespace, from themount command
    • mount would print lines like:/dev/sdh1 on /mnt/monolith type fuseblk (rw,nosuid,nodev,noexec,noatime,user_id=0,group_id=0,default_permissions,allow_other,blksize=4096) and the second field in that line is the mount-point
    • if we're starting up and the mount-point is already mounted, we don't do it again (a bind mount can be done again onto the same directory!)
    • if we're shutting down and the mount-point is not mounted, we also don't attempt to unmount it

And whilst booting, we get the following output from OpenRC:

mount-binds        |  mount /var/ftp/pub/monolithmount-binds        |  mount /var/ftp/pub/piggymount-binds        |  mount /var/ftp/pub/dump [ ok ]

And that's about all (:

Top comments(1)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
bes profile image
Vladimir Varlamov
  • Joined

If you are looking for a solution for delayed bind in fstab when using ZFS (and you don't want to change the default zfs dataset mountpoint) and you are using OpenRC (because systemd has a solution in the form x-systemd.requires=zfs-mount.service), then don't forget add dependency service to openrc for this:

...depend() {  need localmount zfs-mount}...
Enter fullscreen modeExit fullscreen mode

Thanks to the author!

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Code monkey extraordinaire
  • Location
    Durban
  • Work
    Full stack dev at Codeo
  • Joined

Trending onDEV CommunityHot

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp