0

As far as I can tell, some of the output generated by the command /usr/bin/modulecmd goes neither to stdout nor stderr, as illustrated by the following example:

% /usr/bin/modulecmd bash help null >/dev/null 2>&1
        This module does absolutely nothing.
        It's meant simply as a place holder in your
        dot file initialization.

        Version 3.2.9

Is there any way invoke a command (such as /usr/bin/modulecmd) so that all its output goes to either stdout or stderr? Alternatively, is there some way for code that invokes /usr/bin/modulecmd to capture all the output that it would normally send to the termnal?

5
  • Is that a C Shell (csh)? If so, the 2>&1 construct will mean nothing to it. Please confirm the shell in your question Sep 4, 2021 at 18:55
  • @Bib no it wouldn't have errored, which why I'm asking the question Sep 4, 2021 at 19:01
  • @roaima, my tcsh doesn't give an error for 2>&1 alone, but does for the combination of > /dev/null 2>&1. Similarly to how it complains about > foo > bar. I think it parses 2>&1 as the plain argument 2, and the redirection of both stderr/stdout >& to file 1.
    – ilkkachu
    Sep 4, 2021 at 19:30
  • I get no error in csh for echo hello >/dev/null 2>&1. I'd still like to know if the OP is using csh, as I would suspect given the % prompt Sep 4, 2021 at 20:58
  • @roaima: the shell is zsh. (I apologize for the delayed reply to your comment!)
    – kjo
    Sep 5, 2021 at 12:42

2 Answers 2

2

Depends on what the program does. In addition to standard output (fd 1) and error (fd 2), standard input (fd 0) is often also opened read-write when a program is started from the terminal without redirections, and it could be used for writing output. Another option is to explicitly open /dev/tty, which gives a new fd connected to the controlling terminal of the process.

modulecmd uses stdin, for some reason. Running strace on it, we see it writes the header line to the original fd 2, then (after some unrelated fd juggling that doesn't touch fd 0) duplicates fd 0 (stdin) to fd 2, and prints the description there.

...
write(2, "\n----------- Module Specific Hel"..., 70) = 70
...
[unrelated shuffling of other fds]
...
dup(0)                                  = 2
write(2, "\tThis module does absolutely not"..., 37) = 37
write(2, "\r\n", 2)                     = 2
write(2, "\tIt's meant simply as a place ho"..., 44) = 44
...

So you could redirect that part of the message by redirecting stdin (fd 0) to some file, e.g. 0>somefile (or to /dev/null to suppress it), in addition to any redirections of stdout and stderr.

A redirection like < /dev/tty could also prevent the output by giving the process an explicitly read-only fd. (The program would get an error for the write() call, though.) On Linux, you could even do < /dev/stdin with the same result, if the original stdin is connected to a terminal.

If some program used /dev/tty, capturing the output is harder. If available, something like setsid could be used to start the program without a controlling terminal, which would mean that opening /dev/tty would fail. (Well, that's what it does on Linux anyway.)

4
  • stdin is meant to be read from, it's generally not opened read+write, it is so sometimes when the same bidirectional channel is connected to both stdin and stdout, where both stdin and stdout then share the same open file description like for the case of processes running in a terminal, but that's rather the exception. Sep 5, 2021 at 13:33
  • < /dev/stdin would be a no-op on systems other than Linux / Cygwin where it would be more like a dup(0), so would not stop processes from writing to fd 0. But on Linux / cygwin, that means reopening the file pointed to by stdin anew, so would also have the side effect of rewinding to the beginning of the file for regular files or fail with an error if stdin is a socket. Sep 5, 2021 at 13:39
  • @StéphaneChazelas, I'm not sure processes running on a terminal is the exception, esp. if we're in the context of running something interactively from the command line, as in the question. Then again, I'm also not sure it would be necessary for them to point to the same open file description in the case of a terminal either, it should be possible to open the terminal twice, to get a read-only handle and a read-write handle, right? Of course then modulecmd here couldn't print that description, but I have absolutely no idea why it does what it does anyway.
    – ilkkachu
    Sep 5, 2021 at 15:12
  • Both </dev/tty and /dev/stdin are broken because they would not work when running via su or similar (in fact, as already mentioned, the latter may "work", but not do anything at all). Use a "useless" use of cat instead: cat | prog ... and prog won't be able to write to its stdin. As to setsid, it will detach the program from the terminal, making it unkillable with Control-C. But I think that there really is a way to prevent a program from opening /dev/tty, while still running it in foreground and attached to the tty. But this was already quite long and it's late ;-)
    – user313992
    Sep 5, 2021 at 20:32
0

I think the answer to the question is "No" for the following reason: You can only redirect output that existed before the command starts. That is: If the command opens a new output you cannot prevent it by redirecting.

You must log in to answer this question.

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