1

How can I detect changes on a mounted NAS?

It is mounted via fstab:

//fritz.box/FRITZ.NAS /media/fritz cifs username=foo,password=bar,vers=1.0 0 0

Since I tried entr and inotify to no avail, I'm happy to any scripted suggestions e.g. polling va systemd.timer etc. Aparently watching a NAS needs special care (inode).

7
  • why the vers=1.0? Commented Aug 7 at 11:04
  • Probably because they're using their wireless router as the 'NAS', but as far as the protocol is concerned, SMB 1 already supports remote change notifications – it's the Linux kernel cifs client that does not, regardless of protocol version (unless I missed a recent implementation of that). Commented Aug 7 at 11:30
  • @u1686_grawity I think the SMB protocol version would be uhhh 3.0 or upwards for NT_NOTIFY_… to work? Commented Aug 7 at 11:31
  • @MarcusMüller: Ahh, looks like I indeed missed a patch that implements client side support for SMB3 only. But at the same time, no, NT_TRANSACT_NOTIFY_CHANGE is part of the "CIFS" (SMBv1) spec; it used to work as far back as Win98. Commented Aug 7 at 11:41
  • 1
    @MarcusMüller: And still, the Linux client implementation isn't actually hooked up to inotify/fanotify/etc. as far as I can tell – it's only accessible through a special ioctl – so I think it still can be said that "Linux doesn't support it" for most purposes. Commented Aug 7 at 11:42

1 Answer 1

1

Aparently watching a NAS needs special care (inode).

This sentence makes no sense - an inode is the representation of a file system entry in the file system, and as you can see there's files, so there's representations of files.

How can I detect changes on a mounted NAS?

The problem here is that the Linux client implementation of the CIFS network protocol, used to access the files on the NAS, does not support requesting notifications from the NAS. In fact, that seems to be implemented for none of the major network file systems.

One way around that would be using

smbclient //fritz.box/fritz.nas --user foo%bar -c 'notify \\'

(you can replace \\ with the name of the directory you want to watch, if you don't want to watch the whole share)

and whenever that gives you output, you then go and check what has changed in your mount.

Problem: For an unspecified reason, you use vers=1.0` in your mount options. That's not a good sign. I don't know why you're doing that, I hope it's not because something is broken about the implementation of CIFS on the NAS, that would stop it from working with notifications.

In that case:

Some kind of regular polling will be required; whether you use a systemd timer, or a scripted daemon that re-reads file or directory data regularly: up to your implementation / problem. You probably don't want to run a systemd.timer every 0.1s, but that might be very feasible for a daemon to achieve as polling rate without putting much load on the network.

The question hence becomes, primarily, at which intervals you want to get updated. That's sadly not clear at all from your question – and would be the primary design decision to be made.

Are we sure that updating files is the right mechanism here?

Generally, gut feeling tells me that if you use a shared network file system without very strict coherence gaurantees to synchronize stuff, you might be doing something unwise. (For example, computer A might be in the process of updating a file on the server, but it does so in multiple transactions. Computer B detects the change immediately, and gets the file, while it's not completely updated yet. You end up with incoherent data and have a big problem.)

It might be better to use some kind of message passing to exchange data (and even if it's just "I just finished putting new data on the NAS") between the machine(s) where this data originates from, and your local client. Now, this is a Fritz!Box, and you're having an unencrypted password in your /etc/fstab, using a version of SMB that doesn't support useful encryption, so I'm sure this is a local network only, and not the internet (please!!!).

In that case, the simplest solution might really be a tiny server running on your machine – something like nc --listen --udp ${portnumber}, and send tiny messages that convey only the information that an update has happened, from the updating host. More versatile would be you sitting down and writing an actual RPC server. I found the Python Flask framework to be really easy to use;

update_receiver.py:

from flask import Flask

app = Flask(__name__)

@app.route("/update/<what>")
def receive_update(what: str):
    # Do whatever you want to do when an update arrives here.
    # Finally, return what the updating client should get
    return f"Update for '{what}' successfully received"

run it as

flask --app update_receiver run --port 1234

and trigger it with any HTTP client, most likely simply curl, from another machine:

curl http://hostname_running_the_flask_application:1234/update/thingsandstuff

Flask can also allow you to upload files directly (HTTP PUT or POST requests), or to implement complex remote calling logic ("I've put a video for transcoding at {filename}. Please inform me via call to http://myhost:5050/callbacks/finished/{id} when it's done. Please reply with an {id} that you choose for the file.").

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .