I am trying to redirect all output from bash (prompt, user input, results) to a file


/bin/bash > file.txt 2>&1

I thought that would work, but I'm not getting the prompt. Can anyone tell me what I'm doing wrong?

migrated from stackoverflow.com Sep 15 '11 at 22:15

This question came from our site for professional and enthusiast programmers.


Bash outputs the prompt only in interactive mode. I.e. it is normally output to the terminal (/dev/tty on linux). That is neither /dev/stdout or /dev/stdin :)

Now, I'm not sure but I can imagine that bash will allow limited interactive mode when there isn't a fully functional tty. In that case I'd expect the prompt to be written to stdout. I haven't tested that.

Nice Proof Of Concept:

(for a in some set of words; do echo $a > /dev/tty; done) 2>&1 > /dev/null

will just output 1..10 as if there wasn't redirection. Like the prompt, output is directly sent to the terminal (which will fail if there isn't one)

HINT: if you wanted everything to be collected look at

  • Added hints on how to potentially get more bash output into a pipe – sehe Sep 15 '11 at 14:37
  • seq is a highly nonstandard external command, and shouldn't be used in this manner. If you're using bash, do something like for x in {1..10}, or for ((x=1; x<=10; x++)) instead. – Chris Down Sep 15 '11 at 23:25
  • @Chris: good point, thanks for the heads up – sehe Sep 15 '11 at 23:30

To trick bash into thinking it's in interactive mode (although stdout is not being sent to a terminal) you may use the already mentioned script command.

exec 1> >(tee bashlog.txt) 2>&1
script -q /dev/null /bin/bash -l

# alternative without script command
# bash: no job control in this shell
exec 1> >(tee bashlog.txt) 2>&1
/bin/bash -il

The prompt is written to stderr as truss (on Solaris here) shows:

$ truss -ft write -p 10501
10501:  write(2, " d", 1)               = 1
10501:  write(2, " a", 1)               = 1
10501:  write(2, " t", 1)               = 1
10501:  write(2, " e", 1)               = 1
10501:  write(2, "\n", 1)               = 1
10521:  write(1, " S a t u r d a y ,   S e".., 46)  = 46
10501:      Received signal #18, SIGCLD [caught]
10501:        siginfo: SIGCLD CLD_EXITED pid=10521 status=0x0000
10501:  write(2, " $  ", 2)             = 2

The simplest way to do it would be

bash -i >/tmp/logfile 2>&1

Bash will write everything to /tmp/logfile and keep executing commands as you type them, but nothing will be displayed in the terminal. You can make it exit just as you exit your terminal session - by pressing Ctrl+D or typing exit.

Notice that if you run the same thing without stderr redirection, you will only have the greeting message logged to the file, all the rest will work in your current terminal. So the answer to your question about stream to which bash outputs its prompt (and all the following commands) seems to be: stderr.

Oh yes, and the -i parameter simply forces bash to run in interactive mode. Don't listen to those people - you don't need any magic tricks to do that ;)

  • +1 for use of <sub> to format. I just learned something new today. :D – Chris K Jan 13 '14 at 20:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy