|Anonymous | Login||2023-12-04 06:50 UTC|
|Main | My View | View Issues | Change Log | Docs|
|Viewing Issue Simple Details|
|ID||Category||Severity||Type||Date Submitted||Last Update|
|0001746||[1003.1(2016/18)/Issue7+TC2] Shell and Utilities||Objection||Clarification Requested||2023-06-13 15:58||2023-09-05 11:05|
|Priority||normal||Resolution||Accepted As Marked|
|Organization||The Open Group|
|Final Accepted Text||See Note: 0006406.|
|Summary||0001746: fuser output format clarification|
As discussed on the mailing list in October 2021, the use of "%d" as the output format for each PID written by fuser allows there to be no separation between multiple PIDs. The standard should require at least one blank before each PID (including the first: its preceding blank(s) separate it from the pathname written to standard error in the case that standard output and standard error are directed to the same file).
The "%d" format also allows the PID to be followed by <blank> characters, but I believe the intention (and current practice) is that the usage character written to standard error immediately follows the PID (when standard output and standard error are directed to the same file).
On page 2817 line 92698 section fuser, change:
On page 2817 line 92711 section fuser, change:
When standard output and standard error are directed to the same file, the output shall be interleaved so that the filename appears at the start of each line, followed by the process ID and characters indicating the use of the file. Then, if the -u option is specified, the user name or user ID for each process using that file shall be written.to:
When standard output and standard error are directed to the same file, the output shall be interleaved so that the pathname written to standard error appears at the start of each line and is immediately followed by the <blank> character(s) and process ID written to standard output, which are immediately followed by the characters written to standard error indicating the use of the file and, if the -u option is specified, the user name or user ID (in parentheses).
Why the change from %d to %1d ? The default for %d is %1d according
to XBD 5. Putting the '1' there just causes readers to wonder why?
Unless explicitly given as %0d, %d (and all the related ones) always
outputs at least one character.
You also omitted the "for each process using that file" from the final
But the STDOUT section still says:
The fuser utility shall write the process ID for each process using
each file given
So there can clearly be more than one pid printed for one file,
and hence possibly more than one user.
It isn't clear if the multiple user names/uids should each appear in
their own set of parentheses, or if one set should surround all of them,
and in the latter case if any separation is supplied. It also isn't clear,
as the -u option mentions nothing about what happens with multiple processes
whether each user name (or uid) is written just once, or once for each pid.
There is nothing, in the current, or proposed new, text which says there
should be any correlation between the order in which the pids are printed,
and the order the user names (or uids) are printed, nor for that matter,
the order in which any 'c' or 'r' characters are written, nor whether there
is intended to be any way to relate one of those to a pid, particularly if
an implementation chooses not to output other characters for other uses of
the file, nor what should be done if the same file is open by the same process
for several different uses (we may have the root directoru as our current
directory (both 'r' and 'c') and also have it open for reading to obtain a
directory listing (like "cd /; ls' when the "fuser /" command is given, and
that ls process is located as one user of that directory).
I can't test any of this, NetBSD has no fuser command - and given the
description of it, I'm not surprised, it looks foul to use (we do have
a utility which provides similar information in a totally different format).
I'd be in favour of obsoleting this trash... If not, I think its description
needs a complete rewrite, something I cannot assist with, as I have no idea
at all what it really does (I can see what it is intended for, just not the
details of how it really operates).
Also, there doesn't really need to be a space before the first pid to
allow it to be separated from the pathname - the latter is followed by
a ':' according to the spec. And while a ':' may be part of the pathname,
so might a space (and in both cases, that might be the trailing character
of the pathname).
This might not be an issue, if the pathname written is just the file arg
as given to the command - those would usually be able to compared with the
output - particularly if the output were constrained to be in the same order
as the file args were present (but nothing actually says that it is). But
that's also not what is output (apparently) rather it is "The pathname of
each named file" - but there's no clue given as to what that really means,
is it intended to run XSH/realpath on each file name given? If so, what
is done if that fails? Any other way of obtaining a pathname of the file
is just as likely to fail of course.
It is also not clear what (for the -c option)
The file is treated as a mount point
actually means. Is it saying that the file must be a mount point
(and what is "the file" there can be many of them, unless a -c only
applies to the file name immediately following, as if it were "-c file"
as the option) and it would be an error if "the" file is not a mount
point, or does it mean to treat the file as if it were a mount point, and
then list all open files that would be in the filesystem it would designate
(everything in the hierarchy rooted at that point) if it actually were a
mount point? Is this intended to work if "file" does not name a directory?
The more I look at the spec of this command, the more I think it useless.
(as a specification(, and the command as specified, almost useless as well.
How is anything supposed to distinguish diagnostic messages that may be
written to stderr, from the actual output that also goes there? Are those
even expected to start a new line, or do that just appear intermixed with
whatever output has already been written to stderr for that file?
Enough ... if I keep re-reading that "spec" I'll be here all night!
Re Note: 0006330
> Why the change from %d to %1d ? The default for %d is %1d according to XBD 5.
Read the description of the d conversion more carefully, particularly the last sentence. The diff, stty, and ulimit pages already use %1d for the same reason I'm proposing to use it here.
> You also omitted the "for each process using that file" from the final sentence.
Oops, thanks for spotting that. I removed it because it's in the wrong place, but must have got distracted while I was working out how/where to reintroduce it. The rest of your comment results from this text being out of place. With -u the output looks similar to this on the four implementations I tested:
/: 1805cr(root) 1806cr(root) 1807cr(root)and that is what I was trying to make the proposed new STDERR text match. Note that the paragraph being changed is not stand-alone; it follows a bullet list which describes each component written to standard error, so it just needs to make the ordering between what's written to standard output and what's written to standard error clear.
Re Note: 0006331
> Also, there doesn't really need to be a space before the first pid
True, but all the implementations I tested have one or more blanks there and I'm sure the original intention was to describe the existing practice.
> "The pathname of each named file" - but there's no clue given as to what that really means, is it intended to run XSH/realpath on each file name given?
Of the four implementations I tested, GNU coreutils uses realpath() but the others just write the argument as-is.
> It is also not clear what (for the -c option)
> The file is treated as a mount point
> actually means.
Currently I think the standard requires an error if the specified file is not a mount point (via the default CONSEQUENCES OF ERRORS requirements). However, only two of the four implementations I tested do that. So I think we should say the behaviour is unspecified if it's not a mount point.
> How is anything supposed to distinguish diagnostic messages that may be written to stderr, from the actual output that also goes there?
The format of diagnostic messages is unspecified, so they are always expected to be interpreted by a human, not a "thing". Distinguishing them doesn't seem hard for a human:
$ fuser foo . bar foo: fuser: No such file or directory .: 15164c 2545c bar: fuser: No such file or directory $ fuser foo . bar > /dev/null foo: fuser: No such file or directory .: cc bar: fuser: No such file or directory
Re Note: 0006332
On %1d OK ... normally I wouldn't like the spec over specifying something
like that, but here I can see that avoiding trailing space might actually
be important (but also perhaps not, see below).
Good luck with getting the rest of it right.
Not that I care a lot what this ends up saying, but I'd start by scrapping
the first two paragraphs of the Description. In order to get the output
format that Note: 0006332 shows - which is one possibility I considered for
what it might look like, but based on the current wording, about the least
plausible possibility I could come up with, separating the stdout/stderr
outputs that way doesn't work.
To do justice to this, the order of the output needs to be the primary
factor in the description - which part goes to stdout and which to stderr
is a more minor consideration. So I'd write it something like
For each file given, in order, fuser shall write one line
of output, some of it to standard output, and the rest to standard error.
The line shall consist of the file argument, or of a pathname that
refers to that file, followed immediately by a <colon> character (':').
("and then a <space> character" - perhaps - see below). That shall be
written to standard error.
Then for each process using that file, either with the file open, or as
its current, or root directory, or otherwise, fuser shall write the
process id of that process to standard output, in the format given below.
That shall be followed by a sequence of zero or more alphabetic characters,
each of which indicates a type of use of the file by that process.
The characters are specified below, and are written to standard error.
Then, if the -u option was given, the name or user-id of the
(effective/real/both/saved/all?) user associated with the process shall
immediately follow, in the format specified below, and shall be written
to standard error. The order in which the processes are listed is
unspecified (is it, or are they sorted in some fashion?) but each process
using the file shall be listed only once, regardless of how many uses
it is making of the file (assuming that is true: an implementation
might work through the kernel's open file list, then for each which qualifies
as representing the file in question, find all processes using that file.
In that case, a process which has opened the file twice (separate open()
calls, rather than open() dup()) might be found, and listed, twice).
When this information has been written for each process currently accessing
the file, a newline character shall be written to standard error, no newline
is written to standard output (?).
And then continue with the rest of the specification, which should just
concentrate on the specific format details, and exactly what "using"
the file means in the case where the aim is to find all processes using
any file on a filesystem or block device.
Also note that some of the above is still guesswork, even with your example.
Nothing currently says whether "The user name associated with each process ID"
means the real userid, effective userid, or saved userid (or perhaps 2 or all
3 of them, if they're different, and if more than one, which order they appear
in, and how that is formatted - I'm guessing probably just one of them, but
And from the example you gave:
$ fuser foo . bar > /dev/null
foo: fuser: No such file or directory
bar: fuser: No such file or directory
ignoring the errors for the minute, I currently see nothing which
justifies that ' ' between the ':' and the first 'c', unless that is
to be "Implementations may write other alphabetic characters to
indicate other uses of files.", with a rather loose interpretation of
what it means to be an alphabetic character. If leading spaces are
permitted before the "use type" characters. then there's no longer
any need for the '1' in %1d as there's no way to tell the difference
between white space added after the pid, and the white space inserted
before the first 'c' in this case (and since the second 'c' relates
to another process, there could be more white space before it as well).
On the other hand, maybe the format of the pathname output should say
"The pathname of each named file is written followed immediately by a
<colon> followed by a <space>." and that space comes from there, otherwise
where does the space between the first ':' and 'fuser' in the error messages
come from, unless you're assuming the disgnostic messages are starting with
a space (which seems unlikely, though obviously not forbidden).
The format of diagnostic messages is unspecified, so they are always
expected to be interpreted by a human, not a "thing".
Of course, that wasn't the point.
Distinguishing them doesn't seem hard for a human:
No, but the (combined) stdout+stderr stream must be intended to be
processed by "thing"s - or we wouldn't care at all about the precise
details of the format.
That is, if you expect common usage to be
kill -s KILL $(fuser -c /path/to/mountpoint 2>/dev/null)
which is the kind of thing I am expecting this is used for,
then the format of stderr really doesn't matter. Without the
pids (and particularly when -u is not used) the data on stderr
seems completely useless.
The point was more to how the "thing" is supposed to process that
combined stdout/stderr stream in the more general case of errors
beyond the simple ones you showed. eg: nothing in the spec says
that if it fails to map a uid to a user name, it cannot write a
diagnostic about that failure (which might be because of an I/O error
reading the mapping database (aka /etc/passwd or similar)). That's
likely to appear at a rather less appealing point in the output line
than the examples given. Similarly, if realpath() is being used,
and fails, there might be a diagnostic from that before the pathname
Also note that the volume of output might be large, so waiting for fuser
to exit, to get its exit status, is quite likely not practical.
Also before I forget, the -c option specification currently says:
the utility shall report on any files open in the file system
which, if it means what it says, would not include any use of
directories which are some process's current (or even root) directory
(not because directories aren't files, they are, but because the
cwd is not normally open by the process, or often, anything).
It might want to say "in use" instead of "open".
I also have no idea what the output is supposed to look like when the
-c option is given - is there just one long line of all of the pids of
any process with anything open (or probably a cwd or root, or other use)
[other uses include being mapped as shared text segment, or part thereof].
Or does: "shall report on any files open" mean that it should treat any
files open in the file system named as if it were a file arg to
the command, and generate an output line for each of them ?
The same applies to "fuser /dev/block-dev" type queries, intended to find
anything open on the device (which is really the same operation as -c,
except specifying the device from which the mount-point was mounted, rather
than the mount-point itself - block devices that aren't mounted don't
typically contain any files that can be in use.)
And once again, I will stop, before I spend all night on this utter
garbage utility, which really isn't worth anyone's effort.
Good luck coming up with a spec that actually describes how this thing
Oh, you're also definitely going to need an APPLICATION USAGE section for
this one (not just the current "None") - if for no other reason to point
out that the system is dynamic, processes are coming and going, those
processes are opening and closing files, all while fuser is trying to work
out what is going on, By the time fuser prints something, there can't
be any expectation that the something being printed is still valid.
For example, in the "kill -s KILL" example I gave above, it is entirely
possible that will (attempt to) kill a process that isn't using anything
under the mountpoint given - but some now dead process was, and the pid
has been reused while fuser has been running, before kill gets to see it).
Application writers need to be aware of the limitations of this nonsense.
Oh, one more weird possible requirement, in the case of
if the block device doesn't contain a file system, but instead
contains swap space, is fuser intended to report on any
processes which have pages swapped out to that device?
And in that line, what of systems that allow swapping/paging to
files in the filesystem, what's reported about one of those if
it is named on the command line? Typically no process will
have that file open (though the kernel will) so there would be
no process ids to report - but it is still an active file on
the filesystem (preventing umount(8) from working).
New proposal that (I hope) addresses all the points raised so far...
On page 2816 line 92653 section fuser (NAME), change:
list process IDs of all processes that have one or more files opento:
list process IDs of all processes that are using one or more named files
On page 2816 line 92657 section fuser (DESCRIPTION), change:
The fuser utility shall write to standard output the process IDs of processes running on the local system that have one or more named files open. For block special devices, all processes using any file on that device are listed.to:
For each file operand, in order, fuser shall write one line of output, some of it to standard output, and the rest to standard error, giving information about processes running on the local system that are using the file. A process shall be considered to be using a file if it has at least one open file descriptor associated with the file or if the file is a directory that is the current working directory or the root directory for the process, and may be considered to be using a file for other implementation-dependent reasons. If file names a block special device that contains a mounted file system, and the -f option is not specified, any processes using any file on that mounted file system and any processes that are using the device file itself shall be listed.
On page 2816 line 92667 section fuser (OPTIONS, -c), change:
The file is treated as a mount point and the utility shall report on any files open in the file system.to:
If a file operand names a directory that is the mount point of a mounted file system, all processes using any file on that file system shall be listed as if they were using the named directory. The behavior for any file operand that names an existing file that is not the mount point of a mounted file system is unspecified.
On page 2816 line 92674 section fuser (OPERANDS), change:
A pathname on which the file or file system is to be reported.to:
A pathname of a file for which the processes using the file are to be reported.
On page 2817 line 92696-92698 section fuser, replace the STDOUT section with:
On page 2817 line 92700-92716 section fuser, replace the STDERR section with:
The fuser utility shall write diagnostic messages to standard error.
On page 2818 line 92728 section fuser, change APPLICATION USAGE from "None" to:
Things can change while fuser is running; the snapshot it gives is only true for an instant, and might not be accurate by the time it is displayed.
On page 2818 line 92743 section fuser (EXAMPLES), change:
to:fuser <block device>writes to standard output the process IDs of processes that are using any file which is on the device named by <block device> and writes to standard error an indication of how those processes are using the file.
fuser <mounted block device>writes to standard output the process IDs of processes that are using any file on the mounted file system contained by <mounted block device> and of processes that are using the device file <mounted block device> itself, and writes to standard error an indication of how those processes are using the files.
Re Note: 0006431
Looks fine to me.
I am a little surprised by the stated requirement when a block
device is a file arg, but that's just from how I read the text
as it was before, not from any knowledge whatever of what the
implementations actually do, and if they act as described, then
that's fine (the whole utility is still badly designed rubbish,
but that's a different issue).
Don Cragun (manager)
The standard states that the process ID is written using the format "%d", and conforming implementations must conform to this. However, concerns have been raised about this which are being referred to the sponsor.
Format "%d" allows, but does not require a space or tab before the process ID. The standard should require separation between process IDs in order for the output to be usable.
Notes to the Editor (not part of this interpretation):
Make the changes in Note: 0006341
|Interpretation proposed: 27 July 2023|
|Interpretation approved: 31 August 2023|
|2023-06-13 15:58||geoffclare||New Issue|
|2023-06-13 15:58||geoffclare||Name||=> Geoff Clare|
|2023-06-13 15:58||geoffclare||Organization||=> The Open Group|
|2023-06-13 15:58||geoffclare||Section||=> fuser|
|2023-06-13 15:58||geoffclare||Page Number||=> 2817|
|2023-06-13 15:58||geoffclare||Line Number||=> 92698|
|2023-06-13 15:58||geoffclare||Interp Status||=> ---|
|2023-06-13 20:20||kre||Note Added: 0006330|
|2023-06-13 20:44||kre||Note Added: 0006331|
|2023-06-15 09:35||geoffclare||Note Added: 0006332|
|2023-06-15 13:58||kre||Note Added: 0006334|
|2023-06-15 14:36||kre||Note Added: 0006335|
|2023-06-20 15:56||geoffclare||Note Added: 0006341|
|2023-06-25 05:45||kre||Note Added: 0006348|
|2023-07-27 16:01||Don Cragun||Note Added: 0006406|
|2023-07-27 16:03||Don Cragun||Final Accepted Text||=> See Note: 0006406.|
|2023-07-27 16:03||Don Cragun||Status||New => Interpretation Required|
|2023-07-27 16:03||Don Cragun||Resolution||Open => Accepted As Marked|
|2023-07-27 16:03||Don Cragun||Tag Attached: tc3-2008|
|2023-07-27 16:05||agadmin||Interp Status||--- => Proposed|
|2023-07-27 16:05||agadmin||Note Added: 0006407|
|2023-08-31 13:29||ajosey||Interp Status||Proposed => Approved|
|2023-08-31 13:29||ajosey||Note Added: 0006437|
|2023-09-05 11:05||geoffclare||Status||Interpretation Required => Applied|
|2023-09-05 11:06||geoffclare||Tag Attached: applied_after_i8d3|
|Mantis 1.1.6[^] Copyright © 2000 - 2008 Mantis Group|