Skip to main content
updated example.
Source Link
Gairfowl
  • 501
  • 3
  • 6

This appears to work:

#!/usr/bin/env zsh
exec >&1 >>log.txt 2>&1
print -u1 stdout stuff
print -u2 stderr info

Testing:

> ./testexec
stdout stuff
stderr info
> cat log.txt
stdout stuff
stderr info

Change >>log.txt to >log.txt if you want to overwrite the file each time rather than appending to it. This also worked with >>$log when the log variable was set to a filename. The multios syntax is described in this answer, and there's a bit more info here.

This does require that multios be enabled - as you noted, that is the default. set -o (nb: set, not setopt) can be used to display the status of all of the options; setopt without parameters only lists options that have been changed from the default.

Some notes on the pieces:

  • exec ... - the exec builtin will replace the current shell with a new process. When it's invoked like this without a command argument, the replacement is another instance of zsh, with the redirects set to the new values in the command line. The effect is almost identical to invoking a command with those redirects on the command line, e.g.   
    ./testexec{print abc;print -u2 def} >&1 >>log>log.txt 2>&1.
  • >&1 - redirect stdout to stdout. Yes, it's a bit redundant - this is a signal to multios that we want to continue to send stdout to its current destination (which is probably the terminal) in addition to the following redirects.
  • >>log.txt - add a redirect of stdout to the file log.txt in append mode. This is a multios-specific behavior; now the standard output is being sent to two places, via a mechanism in zsh that looks a lot like tee.
  • 2>&1 - send stderr to the same place as stdout. Thanks to the previous two redirects, stdout is going to two places, so this also sends stderr output to the file and (probably) the terminal.
  • print -u<n> - just for testing. The -u option sends the output to file descriptor <n>.

This appears to work:

#!/usr/bin/env zsh
exec >&1 >>log.txt 2>&1
print -u1 stdout stuff
print -u2 stderr info

Testing:

> ./testexec
stdout stuff
stderr info
> cat log.txt
stdout stuff
stderr info

Change >>log.txt to >log.txt if you want to overwrite the file each time rather than appending to it. This also worked with >>$log when the log variable was set to a filename. The multios syntax is described in this answer, and there's a bit more info here.

This does require that multios be enabled - as you noted, that is the default. set -o (nb: set, not setopt) can be used to display the status of all of the options; setopt without parameters only lists options that have been changed from the default.

Some notes on the pieces:

  • exec ... - the exec builtin will replace the current shell with a new process. When it's invoked like this without a command argument, the replacement is another instance of zsh, with the redirects set to the new values in the command line. The effect is almost identical to invoking a command with those redirects, e.g.  ./testexec >&1 >>log.txt 2>&1.
  • >&1 - redirect stdout to stdout. Yes, it's a bit redundant - this is a signal to multios that we want to continue to send stdout to its current destination (which is probably the terminal) in addition to the following redirects.
  • >>log.txt - add a redirect of stdout to the file log.txt in append mode. This is a multios-specific behavior; now the standard output is being sent to two places, via a mechanism in zsh that looks a lot like tee.
  • 2>&1 - send stderr to the same place as stdout. Thanks to the previous two redirects, stdout is going to two places, so this also sends stderr output to the file and (probably) the terminal.
  • print -u<n> - just for testing. The -u option sends the output to file descriptor <n>.

This appears to work:

#!/usr/bin/env zsh
exec >&1 >>log.txt 2>&1
print -u1 stdout stuff
print -u2 stderr info

Testing:

> ./testexec
stdout stuff
stderr info
> cat log.txt
stdout stuff
stderr info

Change >>log.txt to >log.txt if you want to overwrite the file each time rather than appending to it. This also worked with >>$log when the log variable was set to a filename. The multios syntax is described in this answer, and there's a bit more info here.

This does require that multios be enabled - as you noted, that is the default. set -o (nb: set, not setopt) can be used to display the status of all of the options; setopt without parameters only lists options that have been changed from the default.

Some notes on the pieces:

  • exec ... - the exec builtin will replace the current shell with a new process. When it's invoked like this without a command argument, the replacement is another instance of zsh, with the redirects set to the new values in the command line. The effect is almost identical to invoking a command with those redirects on the command line, e.g. 
    {print abc;print -u2 def} >&1 >log.txt 2>&1.
  • >&1 - redirect stdout to stdout. Yes, it's a bit redundant - this is a signal to multios that we want to continue to send stdout to its current destination (which is probably the terminal) in addition to the following redirects.
  • >>log.txt - add a redirect of stdout to the file log.txt in append mode. This is a multios-specific behavior; now the standard output is being sent to two places, via a mechanism in zsh that looks a lot like tee.
  • 2>&1 - send stderr to the same place as stdout. Thanks to the previous two redirects, stdout is going to two places, so this also sends stderr output to the file and (probably) the terminal.
  • print -u<n> - just for testing. The -u option sends the output to file descriptor <n>.
added explanation.
Source Link
Gairfowl
  • 501
  • 3
  • 6

This appears to work:

#!/usr/bin/env zsh
exec >&1 >>log.txt 2>&1
print -u1 stdout stuff
print -u2 stderr info

Testing:

> ./testexec
stdout stuff
stderr info
> cat log.txt
stdout stuff
stderr info

Change >>log.txt to >log.txt if you want to overwrite the file each time rather than appending to it. This also worked with >>$log when the log variable was set to a filename. The multios syntax is described in this answer, and there's a bit more info here.

This does require that multios be enabled - as you noted, that is the default. set -o (nb: set, not setopt) can be used to display the status of all of the options; setopt without parameters only lists options that have been changed from the default.

Some notes on the pieces:

  • exec ... - the exec builtin will replace the current shell with a new process. When it's invoked like this without a command argument, the replacement is another instance of zsh, with the redirects set to the new values in the command line. The effect is almost identical to invoking a command with those redirects, e.g. ./testexec >&1 >>log.txt 2>&1.
  • >&1 - redirect stdout to stdout. Yes, it's a bit redundant - this is a signal to multios that we want to continue to send stdout to its current destination (which is probably the terminal) in addition to the following redirects.
  • >>log.txt - add a redirect of stdout to the file log.txt in append mode. This is a multios-specific behavior; now the standard output is being sent to two places, via a mechanism in zsh that looks a lot like tee.
  • 2>&1 - send stderr to the same place as stdout. Thanks to the previous two redirects, stdout is going to two places, so this also sends stderr output to the file and (probably) the terminal.
  • print -u<n> - just for testing. The -u option sends the output to file descriptor <n>.

This appears to work:

#!/usr/bin/env zsh
exec >&1 >>log.txt 2>&1
print -u1 stdout stuff
print -u2 stderr info

Testing:

> ./testexec
stdout stuff
stderr info
> cat log.txt
stdout stuff
stderr info

Change >>log.txt to >log.txt if you want to overwrite the file each time rather than appending to it. This also worked with >>$log when the log variable was set to a filename. The multios syntax is described in this answer, and there's a bit more info here.

This does require that multios be enabled - as you noted, that is the default. set -o (nb: set, not setopt) can be used to display the status of all of the options; setopt without parameters only lists options that have been changed from the default.

This appears to work:

#!/usr/bin/env zsh
exec >&1 >>log.txt 2>&1
print -u1 stdout stuff
print -u2 stderr info

Testing:

> ./testexec
stdout stuff
stderr info
> cat log.txt
stdout stuff
stderr info

Change >>log.txt to >log.txt if you want to overwrite the file each time rather than appending to it. This also worked with >>$log when the log variable was set to a filename. The multios syntax is described in this answer, and there's a bit more info here.

This does require that multios be enabled - as you noted, that is the default. set -o (nb: set, not setopt) can be used to display the status of all of the options; setopt without parameters only lists options that have been changed from the default.

Some notes on the pieces:

  • exec ... - the exec builtin will replace the current shell with a new process. When it's invoked like this without a command argument, the replacement is another instance of zsh, with the redirects set to the new values in the command line. The effect is almost identical to invoking a command with those redirects, e.g. ./testexec >&1 >>log.txt 2>&1.
  • >&1 - redirect stdout to stdout. Yes, it's a bit redundant - this is a signal to multios that we want to continue to send stdout to its current destination (which is probably the terminal) in addition to the following redirects.
  • >>log.txt - add a redirect of stdout to the file log.txt in append mode. This is a multios-specific behavior; now the standard output is being sent to two places, via a mechanism in zsh that looks a lot like tee.
  • 2>&1 - send stderr to the same place as stdout. Thanks to the previous two redirects, stdout is going to two places, so this also sends stderr output to the file and (probably) the terminal.
  • print -u<n> - just for testing. The -u option sends the output to file descriptor <n>.
Source Link
Gairfowl
  • 501
  • 3
  • 6

This appears to work:

#!/usr/bin/env zsh
exec >&1 >>log.txt 2>&1
print -u1 stdout stuff
print -u2 stderr info

Testing:

> ./testexec
stdout stuff
stderr info
> cat log.txt
stdout stuff
stderr info

Change >>log.txt to >log.txt if you want to overwrite the file each time rather than appending to it. This also worked with >>$log when the log variable was set to a filename. The multios syntax is described in this answer, and there's a bit more info here.

This does require that multios be enabled - as you noted, that is the default. set -o (nb: set, not setopt) can be used to display the status of all of the options; setopt without parameters only lists options that have been changed from the default.