storaged-project / udisks

The UDisks project provides a daemon, tools and libraries to access and manipulate disks, storage devices and technologies.
https://storaged.org/doc/udisks2-api/latest/
Other
349 stars 142 forks source link

Provide a scripting-friendly interface for udisksctl #475

Open ghost opened 6 years ago

ghost commented 6 years ago

Please can a scripting-friendly interface be provided for udisksctl?

Here is an example of a use-case (albeit one that will disappear if #476 gets fixed), but it is easy to envisage other use-cases.

At the moment, there does not seem to be a way for a user, from a Bash shell, to unlock and mount a LUKS-encrypted drive in one step.

A Bash script can be written to act as a wrapper, parsing the output of udisksctl unlock and passing the appropriate device name to the input of udisksctl mount, but this appears to go against the intentions of the authors/maintainers of udisksctl, who warn in the man page:

[This] program is not intended to be used by scripts or other programs - options/commands may change in incompatible ways in the future even in maintenance releases.

With a scripting-friendly interface, this and other problems could be solved by people writing wrapper scripts, as per the Unix philosophy.

vpodzime commented 6 years ago

Another option is to use e.g. busctl to do the DBus calls directly (the DBus API is stable/backwards-compatible). But that's not really optimal either.

This is definitely worth considering. Maybe all we need is to remove that warning from the man page? I doubt the options have really changed in any significant way in the last few years. The bigger issue I see are interactive password prompts and similar things.

ghost commented 6 years ago

vpodzime commented Dec 15, 2017:

Another option is to use e.g. busctl to do the DBus calls directly (the DBus API is stable/backwards-compatible). But that's not really optimal either.

I've never attempted to use busctl to unlock and mount a partition. What would that look like, and in which ways would it be suboptimal?

This is definitely worth considering. Maybe all we need is to remove that warning from the man page? I doubt the options have really changed in any significant way in the last few years.

If the interface is stable for the foreseeable future, then yes, that warning should be dropped ;)

Even if the interface is stable, it would be nice for an option to be available that would modify the output for easier machine readability (a bit like gpg's --with-colons option, but with a more obvious name, maybe --strict or --api or --script).

The bigger issue I see are interactive password prompts and similar things.

Interactive prompts are common in UNIX-like systems. Scripts either leave them interactive, for the user to respond to manually; or else feed them answers via expect or suchlike. So, this shouldn't be a problem :)

MestreLion commented 5 months ago

Maybe all we need is to remove that warning from the man page? I doubt the options have really changed in any significant way in the last few years.

The problem are not the options, its the output format that's very machine-unfriendly to parse.

Consider this:

$ udisksctl loop-setup -f "/some/path with spaces.sqsh"
Mapped file /some/path with spaces.sqsh as /dev/loop12.

$ udisksctl mount /dev/loop12
Mounted /dev/loop12 at /media/mestrelion/disk.

How am I supposed to parse that? Are the strings Mapped file, Mounted, as, and at translatable? What about the trailing period .? One must make a lot of assumptions to properly grep for /dev/loop12 and /media/mestrelion/disk and hope for the best.

So the warning on the man page still holds: udisksctl's output is meant for humans, not scripts. Which hinders a lot its amazing potential.

tbzatek commented 5 months ago

@MestreLion, have you tried using the D-Bus API? That's the primary point how UDisks is supposed to be interfaced. udisksctl is just a convenient tool, it makes no sense to make just another layer on top of it.

marcusmueller commented 5 months ago

@tbzatek I'm probably the reason @MestreLion showed up, as I asked around how to use udisks from a shell script.

So, I honestly can say that, yes, I've tried to use the D-Bus API from a shell context; you end up with command lines that, unless you go and copy&paste them, you won't reproduce them correctly a second time. So, honestly, I like the clean and slim CLI that udisksctl has; going through D-Bus directly is basically infeasible to do free of mistake, compared to it.

If I had to write a D-Bus utility to do what I want, it'd be pretty much udisksctl minus the "human readable" output: I'd just g_print("%s\0\%s\0", …); instead of g_print ("Mapped file %s as %s.\n",… , basically.)

MestreLion commented 5 months ago

@MestreLion, have you tried using the D-Bus API?

Yes I did. It's not fun in Python using dbus module, would be much more painful in shell scripting.

That's the primary point how UDisks is supposed to be interfaced.

Isn't it libudisks (or wrappers such as Python's)? Sure, it has its shortcomings, but whenever possible it's much more convenient than directly speaking to D-Bus.

udisksctl is just a convenient tool, it makes no sense to make just another layer on top of it.

But it's an extremely convenient and powerful tool!

Think about udisksctl mount for example: it does not only mounts a drive, it also creates the temporary mount point under /media, named after the partition label, taking care of corner cases (duplicated or empty labels), all without requiring sudo! It's really an amazing tool. For humans.

And it's just a --plain machine-readable output away of being amazing to scripts as well.

MestreLion commented 5 months ago

I'm probably the reason MestreLion showed up

Well, this is not my first rodeo with UDisks. But yeah, your post made me realize that if I'm not alone in struggling to use udisksctl, maybe it was time to request this upstream. And alas, someone else had already, years ago, and here we are.

Btw, @tbzatek , I'd gladly provide a PR to implement a --plain or similar option to udisksctl (maybe -m|--machine?) if you give the green light. My C skills are a bit rusty (not pun intended), but it'll be fun. And hopefully useful to the community. Certainly for myself.

tbzatek commented 4 months ago

@tbzatek I'm probably the reason @MestreLion showed up, as I asked around how to use udisks from a shell script.

Thanks for the link. It's true we don't pay much attention to udisksctl output format. This tool hasn't changed much though.

So, I honestly can say that, yes, I've tried to use the D-Bus API from a shell context; you end up with command lines that, unless you go and copy&paste them, you won't reproduce them correctly a second time. So, honestly, I like the clean and slim CLI that udisksctl has; going through D-Bus directly is basically infeasible to do free of mistake, compared to it.

The resulting command line may be long, but it gives you precise result that you can interpret. You may even choose between dbus-send, gdbus, busctl and others ;-) I'm also missing operation result code in your script snippet.

See e.g.

$ gdbus call --system --dest org.freedesktop.UDisks2 --object-path /org/freedesktop/UDisks2/block_devices/nvme0n1p1 --method org.freedesktop.UDisks2.Filesystem.Mount -- '{}'
Error: GDBus.Error:org.freedesktop.UDisks2.Error.NotAuthorizedDismissed: The authentication dialog was dismissed
$ gdbus call --system --dest org.freedesktop.UDisks2 --object-path /org/freedesktop/UDisks2/block_devices/nvme0n1p1 --method org.freedesktop.UDisks2.Filesystem.Mount -- '{}'
('/run/media/tbzatek/EFI',)

The command may seem visually long due to addressing.

That's the primary point how UDisks is supposed to be interfaced.

Isn't it libudisks (or wrappers such as Python's)? Sure, it has its shortcomings, but whenever possible it's much more convenient than directly speaking to D-Bus.

That's a secondary interface - most of libudisks is just a machine generated boilerplate code around D-Bus calls. It uses gdbus/gio library that might not integrate well with other mainloop implementations. There are also some extra convenience methods in the library that are useful in scripts.

Think about udisksctl mount for example: it does not only mounts a drive, it also creates the temporary mount point under /media, named after the partition label, taking care of corner cases (duplicated or empty labels), all without requiring sudo! It's really an amazing tool. For humans.

This is all done by udisksd. udisksctl only conveniently looks up a block object e.g. for a given device path.

Btw, @tbzatek , I'd gladly provide a PR to implement a --plain or similar option to udisksctl (maybe -m|--machine?) if you give the green light. My C skills are a bit rusty (not pun intended), but it'll be fun. And hopefully useful to the community. Certainly for myself.

I'm not against any kind of contributions like this, just want to try to convince people to use more direct methods first, instead of using a wrapper around a wrapper :-) As an inspiration, some projects do implement --json output as a common scripting format.