The macosxhints Forums

The macosxhints Forums (http://hintsforums.macworld.com/index.php)
-   UNIX - General (http://hintsforums.macworld.com/forumdisplay.php?f=16)
-   -   rsync /Volumes question (http://hintsforums.macworld.com/showthread.php?t=95918)

tw 11-16-2008 09:58 PM

rsync /Volumes question
 
I have a script that automatically backs up certain folders whenever my external HD is attached. mostly it works fine, but occasionally (if I muck something up, like removing the drive too soon or launch the script when the drive isn't attached) rsync creates an actual folder in /Volumes and starts filling it up as though it were the external HD, with hilarious results. apparently rsync can't tell the difference between a separate volume and a folder in /Volumes. so I started poking around to see if I could make a check for myself, and oddly, I can't figure it out myself. how do you distinguish betwen a regular folder in ?volumes and an attached disk? the root drive shows up as a symbolic link, but attached drives seem to be represented as normal folders.

anyone have insights on this?

Hal Itosis 11-16-2008 11:03 PM

Quote:

Originally Posted by tw (Post 503603)
I have a script that automatically backs up certain folders whenever my external HD is attached. mostly it works fine, but occasionally (if I muck something up, like removing the drive too soon or launch the script when the drive isn't attached) rsync creates an actual folder in /Volumes and starts filling it up as though it were the external HD, with hilarious results. apparently rsync can't tell the difference between a separate volume and a folder in /Volumes. so I started poking around to see if I could make a check for myself, and oddly, I can't figure it out myself. how do you distinguish betwen a regular folder in ?volumes and an attached disk? the root drive shows up as a symbolic link, but attached drives seem to be represented as normal folders.

anyone have insights on this?

Hopefully, distinguishing between a "regular folder" and mounted disk isn't actually necessary.
Since your script (or rsync) seems to be the one creating the folder, just prevent that behavior
by checking for the target's presence *first*. If it's not there, don't let rsync proceed:

target=/Volumes/some\ disk\ name
:
:
[[ -d $target ]] || exit 1 # no target, no run

So that should solve the issue (by prevention).


I will note that listing /Volumes with the inode numbers option -i
has always shown real volumes with an inode number of "2"... but
some other strange (yet very low numbered) values have recently
come to my attention. [some 'Directory Services' mount was "7"?]

Anyway, simply testing the target path at the right time should do it.

-HI-

ataraxia 11-16-2008 11:04 PM

Check the inode number of the folder. A mount point will have inode number '2', a regular folder won't.

You could also parse the output of 'mount', 'df', or 'disktool -l' if you prefer.

Hal Itosis 11-16-2008 11:14 PM

Quote:

Originally Posted by ataraxia (Post 503613)
A mount point will have inode number '2', a regular folder won't.

I have previously observed this myself,
but know of no "official" documentation.

Do you know of such?

ataraxia 11-17-2008 09:32 AM

Quote:

Originally Posted by Hal Itosis (Post 503614)
I have previously observed this myself,
but know of no "official" documentation.

Do you know of such?

Afraid not, it's just observation on my part. If you have counterexamples, as you say above, I'm convinced.

tw 11-17-2008 12:25 PM

Quote:

Originally Posted by Hal Itosis (Post 503612)
I will note that listing /Volumes with the inode numbers option -i
has always shown real volumes with an inode number of "2"... but
some other strange (yet very low numbered) values have recently
come to my attention. [some 'Directory Services' mount was "7"?]

well, I was actually checking for the volume through the 'mount' command (mostly because I wanted to make sure it was the last volume mounted, not just if it was mounted - that would kick off the script whenever any later volume was mounted):
Code:

#!/bin/bash

lastMounted=`mount -t hfs | awk '/\/dev\/disk/{ v=q[split($3, q, /\//)] }; END {print v}' -`

if [ "$lastMounted" != "Backup" ]; then
        exit 0
fi

did I do that wrong? this doesn't solve the problem of the disk being unmounted too early, but if that inode thing works as expected I can have launchd check for non-disk folders and remove them.

cwtnospam 11-17-2008 12:34 PM

Quote:

Originally Posted by tw (Post 503680)
...if that inode thing works as expected I can have launchd check for non-disk folders and remove them.

But if rsync creates the folder, it's too late for launchd to help. You need to check the path before calling rsync and not make the call if the drive isn't mounted.

tw 11-17-2008 12:58 PM

Quote:

Originally Posted by cwtnospam (Post 503684)
But if rsync creates the folder, it's too late for launchd to help. You need to check the path before calling rsync and not make the call if the drive isn't mounted.

no - if I know that rsync is screwing up, I can run a script to kill the rsync process and remove the folder (which I'd like to do, because otherwise I find out about the problem when the system tells me I have 0 disk space left :)).

@HI and ataraxia: the inode man page says this:
Quote:

The root inode is the root of the file system. Inode 0 can't be used for normal purposes and historically bad blocks were linked to inode 1, thus the root inode is 2
so it looks like any normal file system root will have an inode of 2. why some are showing up as other low numbers, though...??? that would seem to imply that they are not mounted as root file systems, but as file systems somewhere farther down the food chain. can you set up a file system to mount inside of another file system?

cwtnospam 11-17-2008 01:32 PM

Quote:

Originally Posted by tw (Post 503692)
no - if I know that rsync is screwing up, I can run a script to kill the rsync process and remove the folder (which I'd like to do, because otherwise I find out about the problem when the system tells me I have 0 disk space left :))

:confused:
But wouldn't it be better to avoid running rsync if the external is not attached?

tw 11-17-2008 01:38 PM

Quote:

Originally Posted by cwtnospam (Post 503705)
:confused:
But wouldn't it be better to avoid running rsync if the external is not attached?

well, yes, and in an ideal world that would work exactly as planned. building a portal to an ideal world is my next project, though; this is just a temporary measure until I'm done that. :rolleyes:

cwtnospam 11-17-2008 01:53 PM

But if before you call rsync, you check to see if the path exists, and if it exists you check to see if it's a folder or a drive, you can decide whether or not to call rsync! It's not the perfect world, but it will let you get started on that portal. ;)

tw 11-17-2008 02:03 PM

Quote:

Originally Posted by cwtnospam (Post 503715)
But if before you call rsync, you check to see if the path exists, and if it exists you check to see if it's a folder or a drive, you can decide whether or not to call rsync! It's not the perfect world, but it will let you get started on that portal. ;)

well, yeah, I was doing that, but I still (occasionally) ended up with rsync writing to a folder rather than a disk. if you can figure out why that's happening, then I'll go with your plan. :)

cwtnospam 11-17-2008 02:08 PM

I'm assuming you'd use the same logic in launchd as you were in testing whether or not to run rsync. In that case, launchd might also see a folder as if it were a drive, so you'd be stuck with the same results.

Hal Itosis 11-17-2008 02:16 PM

Quote:

Originally Posted by tw (Post 503692)
the inode man page says this:
Quote:

The root inode is the root of the file system. Inode 0 can't be used for normal purposes and historically bad blocks were linked to inode 1, thus the root inode is 2
so it looks like any normal file system root will have an inode of 2.

Cool... thanks for finding that.

Quote:

Originally Posted by tw (Post 503692)
why some are showing up as other low numbers, though...??? that would seem to imply that they are not mounted as root file systems, but as file systems somewhere farther down the food chain. can you set up a file system to mount inside of another file system?


Here's a link to that other thread/post, where the "inode = 7" appeared: Unexpected directory in /Volumes
Turns out it was some remote NFS URL (nfs://meaty.inside/var/nfs/export) mounted as /Volumes/meaty.

The url there seems to support your phrasing "file systems somewhere farther down the food chain".

tw 11-17-2008 02:33 PM

Quote:

Originally Posted by cwtnospam (Post 503726)
I'm assuming you'd use the same logic in launchd as you were in testing whether or not to run rsync. In that case, launchd might also see a folder as if it were a drive, so you'd be stuck with the same results.

well, launchd is a bit limited. there's a key for triggering a job when a filesystem is mounted, but ld doesn't have any mechanism for seeing what filesystem was mounted, or for passing that information to a script. basically, ld just says 'something happened' and it's up to the script to figure it out.

basically, the script needs to account for the following conditions:
  • the backup disk is mounted
  • another disk or dmg is mounted (before or after) the backup disk is mounted
  • the backup disk is unmounted before rsync finishes its work

the first is easy. the second ought to be handled (and excluded) by the scriptlet I gave above (unless there's an error in the code). the third is problematic: ld doesn't have a trigger for when a file system is unmounted, and rsync is unaware of the file system change.

tw 11-17-2008 02:40 PM

Quote:

Originally Posted by Hal Itosis (Post 503730)
Here's a link to that other thread/post, where the "inode = 7" appeared: Unexpected directory in /Volumes
Turns out it was some remote NFS URL (nfs://meaty.inside/var/nfs/export) mounted as /Volumes/meaty.

The url there seems to support your phrasing "file systems somewhere farther down the food chain".

interesting... maybe Macs do something tricky with non-mac formats, like mount the disk inside an implicit HFS+ container whose job it is to translate the format into something readable. I'll have to poke around and see if I can find any docs on that.

Hal Itosis 11-17-2008 02:59 PM

Quote:

Originally Posted by tw (Post 503680)
well, I was actually checking for the volume through the 'mount' command (mostly because I wanted to make sure it was the last volume mounted, not just if it was mounted - that would kick off the script whenever any later volume was mounted):
Code:

#!/bin/bash
lastMounted=`mount -t hfs | awk '/\/dev\/disk/{ v=q[split($3, q, /\//)] }; END {print v}' -`
if [ "$lastMounted" != "Backup" ]; then exit 0; fi

did I do that wrong? this doesn't solve the problem of the disk being unmounted too early, but if that inode thing works as expected I can have launchd check for non-disk folders and remove them.

Not a big fan of split, preferring to go with sed when possible.
If I'm following that lastMounted assignment correctly, this might be how i'd do it:

lastMounted=$(mount -t hfs |sed '$!d;s:^/.*/::;s: (hfs.*)$::')

I'm not clear on what 'triggers' your main script.

Does it run all the time (via either periodic calls or some sleep period) to regularly
check for lastMounted... and then call some rsync subroutine if criteria is satisfied?

As cwtnospam points out, launchd can do some of that work nicely.
See man launchd.plist (or google, search here, etc.), for keywords like:
StartOnMount
WatchPaths
QueueDirectories

tw 11-17-2008 11:55 PM

Quote:

Originally Posted by Hal Itosis (Post 503752)
Not a big fan of split, preferring to go with sed when possible.
If I'm following that lastMounted assignment correctly, this might be how i'd do it:

lastMounted=$(mount -t hfs |sed '$!d;s:^/.*/::;s: (hfs.*)$::')

I'm not clear on what 'triggers' your main script.

Does it run all the time (via either periodic calls or some sleep period) to regularly
check for lastMounted... and then call some rsync subroutine if criteria is satisfied?

As cwtnospam points out, launchd can do some of that work nicely.
See man launchd.plist (or google, search here, etc.), for keywords like:
StartOnMount
WatchPaths
QueueDirectories

the main script is triggered from launchd, using the StartOnMount key (I'm pretty good with launchd, actually). on examination, it seems the problem only occurs when (a) I unintentionally unmount the disk while rsync is running, or (b - maybe) I mount another disc while the Backup disk is being removed (it seems there might be a short lag before the mount command recognizes that the file system has been removed).

and oy vey - sed! is there an advantage to using it over the awk? because I REALLY hate sed... :o

Hal Itosis 11-18-2008 06:30 PM

Quote:

Originally Posted by tw (Post 503837)
on examination, it seems the problem only occurs when (a) I unintentionally unmount the disk while rsync is running,

Still... I would think that if it were layed out like this...

[[ -d $target ]] || exit 1
rsync . . .

...that:
a) rsync would never even get called unless the target folder is there, and
b) once rsync does get called, wouldn't Finder *see* that the disk is "busy"?



Quote:

Originally Posted by tw (Post 503837)
or (b - maybe) I mount another disc while the Backup disk is being removed (it seems there might be a short lag before the mount command recognizes that the file system has been removed).

That part might be trickier. (perhaps add 2 seconds of sleep, somewhere in your script?)


Quote:

Originally Posted by tw (Post 503837)
and oy vey - sed! is there an advantage to using it over the awk? because I REALLY hate sed.

No real "advantage" i s'pose... the result is the main thing, for grabbing that string.
[i will note though that --as written-- sed is doing the work of both awk and split.]
Or is that "split" one of awk's built-in tools? (as opposed to /usr/bin/split)

tw 11-18-2008 06:48 PM

Quote:

Originally Posted by Hal Itosis (Post 504020)
Still... I would think that if it were layed out like this...

[[ -d $target ]] || exit 1
rsync . . .

...that:
a) rsync would never even get called unless the target folder is there, and
b) once rsync does get called, wouldn't Finder *see* that the disk is "busy"?

well, for (a) the -d option can't apparently distinguish between an actual folder and a disk (both show up in ls as a normal directory, at any rate), and for (b) - I would have thought that two, but the Finder doesn't seem to be aware of the rsync process, and is perfectly happy to unmount the disk while it's running. I suppose I could scam it by opening a file from the backup disk just to make the finder aware...

I've been considering writing a second launchd job that only runs when the backup job is activated (using KeepAlive when OtherJobEnabled) that checks periodically that the Backup folder has an inode of 2, and squelches the backup if it doesn't. I'll see how that works out, because I've never used KeepAlive before... and yes, split is one of awk's functions, though I may just rewrite that to be a grep test, since I don't really need a result returned, just a boolean test.

Hal Itosis 11-18-2008 07:15 PM

Quote:

the -d option can't apparently distinguish between an actual folder and a disk (both show up in ls as a normal directory, at any rate)
Right... but it shouldn't ever need to.
Just stop making folders in /Volumes!

(yes... you) ;)

i.e., as long as there is no folder there *now* - - - then

[[ -d $target ]] || exit 1
rsync . . .

stops rsync from making one.
Have you *tried* this yet?

tw 11-19-2008 05:31 PM

ok, well I threw the line in (since I can't see how it would hurt). :)

Hal Itosis 11-19-2008 07:25 PM

Quote:

Originally Posted by tw (Post 504212)
ok, well I threw the line in (since I can't see how it would hurt). :)

And I'll assume (when you just say "the line") that
it was done in such a way that $target is defined.
;)

tw 11-19-2008 07:32 PM

Quote:

Originally Posted by Hal Itosis (Post 504225)
And I'll assume (when you just say "the line") that
it was done in such a way that $target is defined.
;)

¿¿¿what do you mean??? shouldn't my mac just know what the appropriate target is? I mean, gosh... :p

Hal Itosis 11-19-2008 11:37 PM

... touché


All times are GMT -5. The time now is 05:46 PM.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2014, vBulletin Solutions, Inc.
Site design © IDG Consumer & SMB; individuals retain copyright of their postings
but consent to the possible use of their material in other areas of IDG Consumer & SMB.