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
Related
Is it possible to have a bash script split the terminal window horizontally at one point, so that the left side details the overall progress of tasks, and the right side contains verbose output from the current task being run?
I've found some people referencing nohup and screen in contexts of splitting the terminal window, but I don't know how to get that going in a bash script sense, or if its even the right direction for my needs.
At the moment, I've got lots of long tasks with long output, so I'm sending the output of each to a cumulative log file, instead of dumping on the screen. Then, as an interim, manually opening a new terminal window to use watch tail LogFile* to keep an eye on what's going on.
It would be great if I could automate that process.
Update
Some leads.
This post and its comments were very helpful, to establish that you can launch a command in one window and send its output to another based on its pts value.
For example, ls > /dev/pts/7 will display output of ls in the terminal window at pts/7.
Still stumped about how to automate splitting the screen programatically, and using that, instead of a new window.
I got a working example going with Terminator.
Start the bash script below in a new Terminator window:
terminator --command="bash /path/to/script"
And once we're running in that, it's a bit of a hack solution, but to split the screen by command-line in the bash script, I ended up using xdotool to send keybindings to Terminator. Like so:
#!/bin/bash
# send keybinding that splits screen vertically
xdotool key Ctrl+Shift+E
# Terminator now sets focus to the right side (the new split) by default, so send keybinding that returns the focus to our left side
# sleep a tiny little bit first
sleep 0.01
xdotool key Alt+Left
# now to send output to the right side, let's work out "where" the ride side is
# use who to find the pts ids of all currently spanwed terminal windows
# use tail to find the last line from who (which we assume is the terminal window we just split)
# then grep to find just the number after pts/
## windowID=$(who | tail -n1 | grep -oP 'pts/\K[0-9]*')
# updated this to fix bug where who does not return pts values
# https://askubuntu.com/questions/1110203
windowID=$(ps -u $USER -o tty | awk 'NR>1 && $1 != "?" {a[$0]++};END{for(val in a) print val}' | tail -n1 | grep -oP 'pts/\K[0-9]*')
# now we can send output from commands to the right side split window by using its pseudo device id. for example:
ls -lah >> /dev/pts/$windowID
exit
I am trying to redirect outputs of systat -ifstat and systat -vmstat to a file and When I open that file, lot of special chars are added to a file like below
(B)0[?1049h[1;39r[m[4l[H[2J[1;21H/0 /1 /2 /3 /4 /5 /6 /7 /8 /9 /10
[68DLoad Average
[11DInterface[4;27HTraffic[4;49HPeak[4;69HTotal[2;21H[5;13H1/1 in[6C0.000 KB/s[5;46H0.000 KB/s[5;66H260.087 MB[6;18Hout 0.000 KB/s[6;46H0.000 KB/s[6;66H205.319
The command I am using to redirect to a file is below:
systat -ifstat 1 > text.txt
Can someone guide me to get rid of these special chars.Help is appreciated.
Keep in mind that systat(from the man page) display system statistics in a screen-oriented fashion using the curser screen display library, therefore in the try to get something like a screenshot, this partially works:
systat -ifstat | tee /tmp/output
to see the output like when using the command you will need to do cat /tmp/output, otherwise you will see all the shell escape characters.
You could also try script:
$ script
Script started, output file is typescript
$ systat -ifstat
next, you exit systat ctrl+c
$ exit
exit
Script done, output file is typescript
This will create a file named typescript but the output is not as clear as when using tee. (still, haven't found a way of how to render properly typescript within csh)
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 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
When I try to read bash history into vim, I get nothing.
:r !history
If I just execute the command, i.e.
:!history
instead of history I get a snapshot of my terminal as it looked before I started vim.
How can I read the output of "history" into vim? Reading the contents of .bash_history won't do as I save history with timestamps:
HISTTIMEFORMAT='%Y.%m.%d %R '
From a shell prompt:
history | vim -
The problem is that that history is only known by the bash shell that started vim. When you do :!history from within vim, you're starting a new bash shell that has its own history, which is empty, which is why you just see the screen as it looked when you started vim: it's outputting all the lines in its history, which is a grand total of zero. This actually is an oversimplification, but anyway you can't get a history of the commands that you typed just before starting vim this way.
If you want to get those lines of history without exiting vim, you can suspend vim by pressing CTRL-Z and then write the history to a file using history >history.tmp. Then type fg 1 to resume vim: this will tell bash to transfer focus back to its "job number 1", which will normally be vim. The job number is displayed after you hit CTRL-Z:
[1]+ Stopped vim
so if there's a number other than 1 in the brackets, then you should do fg for that number instead. Then (hopefully you know this) when you're back in vim just :tabedit history.tmp, for example, to open the saved history in a new tab.
You'll have timestamps in this output too, but since you're in vim you can easily filter them out with a :substitute command. Alternatively you can cut them out using HISTTIMESTAMP='' history rather than just history when writing to the file; this will still output the index of each entry. I guess you can filter that out on its way into the file too, by piping it through sed or cut or one of their crew. But it's really easy to do this from within vim (assuming you know the basics of regular expressions; if not, start with :help :substitute or maybe look for a regex tutorial).
Note that if you read in the lines from ~/.bash_history, you're only getting the history from bash shells which have completed, ie you typed exit and the terminal window closed. So any commands you typed just before starting vim won't be there. You can change the way this works but then you end up with commands from different sessions all jumbled up together in the history.
:r!echo "history" | bash -i 2>/dev/null | sed -e 's/\x1b\[.//g'
Explanation:
The history command only works on interactive shell.
The first part:
echo "history" | bash -i 2>/dev/null
Forces interactive shell (and removes lines which aren't output of history).
The second part:
sed -e 's/\x1b\[.//g'
Removes escape character the shell might output (happened on my system).
You may pre-write the history of current session:
history -w
Then in editor you can get last, say, 20 commands of history:
:r ! tail -20 ~/.bash_history
Try:
r !set -o history; HISTFILE=~/.bash_history; history -r; history 10
This will include the timestamps and will not include history that hasn't been saved to the history file.