I would like to split stdout and stderr and be able to see them side-by-side during program execution.
All solutions I knows require redirection of one or both streams to file.
My solutions:
Redirect stdout and stderr to different files, and then tail -f both files in separate terminal windows or inside tmux/screen. This requires 3 terminals - 1 for command invocation, and two for preview.
Redirect only stderr to files, and the taif -f the file in separate terminal. This requires 2 terminals - 1 for command invocation and stdout, and one for stderr preview.
Both solutions are inconvenient, because you have to run multiple commands and switch between terminals.
Are there any better solutions for this problem? Is there a way to avoid redirection to file?
so because OP asked specifically for side by side, one option: tmux!
(tmux is a little heavy but it does split panes pretty well I guess so example:)
$ tmux
Split your panes:
left-right:
^b + %
(^b means ctrl+b)
top-bottom:
^b + "
Focus your error pane:
^b + ↑↓→← + enter
$ tty, copy your error pane's device file
Re Focus your output pane:
^b + ↑↓→← + enter
$ your-command 2>/dev/pts/N
where /dev/pts/N is the value you coped from the other pane
Neat! :camera-flash:
If it is the file creation you want to avoid, you can do this...
Start a new Terminal, and in there, type tty to find that terminal's device special file, e.g /dev/ttys002
Then in your original Terminal, run your command like this:
yourProgram 2> /dev/ttys002
I used this as a test program:
#!/bin/bash
for i in {0..30}; do
echo hi
echo hi to stderr >&2
done
Related
I'm working on a script, that requires you press control + d when you complete your entries. I'd like to send this command so I can just script my work rather than having to redo my work.
You're probably talking about the "end of transmission" delimiter which is used to indicate the end of user input. If that's the case then you can always pipe data into your script. That is, instead of this:
$ test_script.sh
My input!
^D
You'd write that data to a file:
$ cat > input
My input!
^D
Then pipe that into the script:
$ test_script.sh < input
No ^D is required because once that file is fully read the script is signalled accordingly. The < shell operator switches STDIN to read from a file instead of the terminal. Likewise, > can be used to capture the output of a program and save it to a file, as done in the second step here, though you can use any tool you'd like to create or edit that input file.
This works with pretty much any scripting language, from Python, Perl, Ruby to Node.js as well as bash and other shells.
From this question: bash - automatically capture output of last executed command into a variable I used this command:
PROMPT_COMMAND='LAST="`cat /tmp/x`"; exec >/dev/tty; exec > >(tee /tmp/x)'
It works, but when I use Vim I get this:
# vim
Vim: Warning: Output is not to a terminal
Then Vim opens. But it takes a while. Is there a way to get rid of this message and the slowdown?
Also when I list dir and I echo $LAST it removes the return lines (\n). Is there a way to keep the return lines (\n)?
I think what you ask for is hard do achieve. Vim tests if the output is a terminal. The command you've provided redirects the output to the tee command. tee saves its input (which also menans: command's output) to the file and outputs it to the terminal. But vim knows nothing about it. It only knows its output is not a terminal. So it outputs warning. And from the vim's source code:
[...]
if (scriptin[0] == NULL)
ui_delay(2000L, TRUE);
TIME_MSG("Warning delay");
which means this redirection will always get you 2 seconds delay.
Also, for example, man vim command will not work with such redirections, because terminal output has some attributest (e.g. width and height) which generic file hasn't. So... it won't work.
I have a script using for a building a program that I redirect to sed to highlight errors and such during the build.
This works great, but the problem is at the end of this build script it starts an application which usually writes to the terminal, but stdout and stderr redirection doesn't seem to capture it. I'm not exactly sure how this output gets printed and it's kind of complicated to figure out.
buildAndStartApp # everything outputs correctly
buildAndStartApp 2>&1 | colorize # Catches build output, but not server output
Is there any way to capture all terminal output? The "script" command catches everything, but I would like the output to still print to my terminal rather than redirecting to a file.
I found out script has a -c option which runs a command and all of the output is printed to stdout as well as to a file.
My command ended up being:
script -c "buildAndStartApp" /dev/null | colorize
First, when you use script, the output does still go to the terminal (as well as redirecting to the file). You could do something like this in a second window to see the colorized output live:
tail -f typescript | colorize
Second, if the output of a command is going to the terminal even though you have both stdout and stderr redirected, it's possible that the command is writing directly to /dev/tty, in which case something like script that uses a pseudo-terminal is the only thing that will work.
I'm using Bash on Ubuntu, and sometimes when I run a command, the output overfills the terminal, even when I scroll up to the top. How can I access the part of the output that's hidden because of the overfill?
You can try any of the following (Using the ls command as an example for where the commands would go):
Option A: Redirect the output to a file with > and then examine the file later with less or a text editor like vim or gedit.
$ ls > outfile
$ less outfile
$ vim outfile
$ gedit outfile
$ emacs outfile
To write the command's output to both stdout and stderr to your outfile, add a 2>&1 at the end, like so:
$ ls > outfile 2>&1
Option B: pipe the output of your command directly to less
$ ls | less
Note: if you view the output with less with either of the above options, use:
Ctrl+F to go down a page,
Ctrl+B to go up a page ,
Ctrl+D for down 1/2 a page,
Ctrl+U for up 1/2 a page
Arrow keys to move up / down line by line.
Press q to exit from less anytime.
You can pipe the output to less :
command | less
That's actually not bash doing that, it's the terminal program.
You have a couple of options. Perhaps the easiest is just piping your command through less, which allows you to scroll back and forth:
command_with_much_output | less
Secondly, you can configure your terminal program. Assuming you're using the default one, you can open up the Edit menu and select Profile preferences:
Then choose the Scrolling tab and you can change the scrollback buffer size:
Or you can increase the number of lines kept to scrollback in profile's properties (assuming you are using gnome-terminal).
You can try Redirecting the output to a text file .
command > file
There are plenty of threads here discussing how to do this for scripts or for the cmdline (mostly involving pipes, redirections, tee).
What I didn't find is a solution which can be set up once and then just works globally, without manipulating single scripts or adding something to every command line.
What I want to achieve is something like described in the top answer of
How do I write stderr to a file while using "tee" with a pipe?
Isn't it possible to configure the bash session so that all stderr output is logged to a file, while still writing it to console? Something I could add to .bashrc and thus automatically set up every time I login?
Software: Bash 4.2.24(1)-release (x86_64-pc-linux-gnu), xterm, Ubuntu 12.04
Try this variation on #0xC0000022L's previous solution (put it in your .bash_profile):
exec 2> >( tee log.file > /dev/tty )
A couple of caveats:
The prompt and anything you type at the command line are printed to stderr, and so will be logged in your file.
There could be an issue with the newline that terminates a command not being displayed in your terminal; I observe it on my Linux host, but not on my Mac OS X laptop. Perhaps someone else can explain and/or fix the issue. For example, if I type "echo stdout", I see the following:
$ echo stdoutstdout
$