5

This is the un-redirected output (if you don't know what module is, it doesn't matter much):

$ module help null

----------- Module Specific Help for 'null' -----------------------

        This module does absolutely nothing.
        It's meant simply as a place holder in your
        dot file initialization.

        Version 3.2.6

Suppose I'd like to redirect that to a file....

$ module help null > aaa.txt 

----------- Module Specific Help for 'null' -----------------------

        This module does absolutely nothing.
        It's meant simply as a place holder in your
        dot file initialization.

        Version 3.2.6

$ cat aaa.txt
$

Well, it must be on the stderr

$ module help null 2> aaa.txt 
        This module does absolutely nothing.
        It's meant simply as a place holder in your
        dot file initialization.

        Version 3.2.6

$ cat aaa.txt 

----------- Module Specific Help for 'null' -----------------------
$

Hey! It is resetting my redirect. This is really annoying, and I have two questions:

  1. How can I achieve what I want, namely redirecting everything into my file
  2. Why are they doing such a weird thing?

See also this related question.

EDIT: somebody asked in a comment, so some details. This is on AIX 5.3 at 64 bits. I have python 2.6.5 almost fully available. I have both gcc 4.1.1 and gcc 4.5.1 but not many libraries to link them against (the util-linux-ng library, which contains the script version mentioned in an answer fails to compile for the getopt part). I also have several version of IBM XL compiler xlc. The reason why I didn't specify in the first place is that I was hoping in some shell tricks, maybe with exec, not in an external program.

Community
  • 1
  • 1
Davide
  • 17,098
  • 11
  • 52
  • 68

3 Answers3

6

Try this:

script -q -c 'module help null' /dev/null > aaa.txt

This works in a shell script (non-interactively) using

$ script --version
script (util-linux-ng 2.16)

You may also be able to use expect.

Also see: Catching a direct redirect to /dev/tty.

Community
  • 1
  • 1
Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439
2

I'm answering the second question first: as a design choice, module is an eval and they took the (questionable) choice to use stderr/tty instead of stdout/stderr to keep their side of the design easier. See here.

My solution, since I couldn't use any of the other recommended tools (e.g. script, expect) is the following python mini-wrapper:

import pty, os

pid, fd = pty.fork()
if pid == 0: # In the child process execute another command
    os.execv('./my-progr', [''])
    print "Execv never returns :-)"
else:
    while True:
        try:
            print os.read(fd,65536),
        except OSError:
            break
Davide
  • 17,098
  • 11
  • 52
  • 68
0

Looks like module is writing to /dev/tty, which is always the console associated with the process. If so, then I don't think you can do anything about it. Typically, this is done to guarantee that the person sees the message (assuming that the program was invoked interactively).

Steve Emmerson
  • 7,702
  • 5
  • 33
  • 59
  • Well, the problem is the program is *not* invoked interactively. And `script` is a workaround that works, but (at least the version I have) works only interactively – Davide Oct 29 '10 at 21:49
  • My recommendation is then to get a version of script that does support -c. – Martin v. Löwis Oct 30 '10 at 00:36
  • Unfortunately it's not easy at all, on this platform (AIX). I'm trying but I guess it would be too much effort. Investigating expect too. – Davide Oct 30 '10 at 02:43
  • Then you should specify your limitations in your question. Can you compile C code, for example? Do you have Python available? – Martin v. Löwis Oct 30 '10 at 07:54