bash when inside screen, output is truncated if does not fit in a line - linux

Outside screen -
[j#firedesire rb]$ diff -bu root_es-US.pres root_es-MX.pres | sed -n "s/^-\([^=]*\)=.*/'\1'/p" | tr "\\n" ","
'IMG.HEAD.LOGO.URL','LNK.COPYRIGHT.URL','LNK.FOOTSECURITY.URL','LNK.HEADHELP.URL','LNK.HEADYAHOO.URL','LNK.PRIVACY.URL','LNK.TOS.URL','STR.HEAD.LOGO.HEIGHT','STR.HEAD.LOGO.WIDTH','REG.TOS.MAIL.URL','UPGRADE.STR.AGREE.STATEMENT',[j#firedesire rb]$
Inside screen -
[j#firedesire rb]$ diff -bu root_es-US.pres root_es-MX.pres | sed -n "s/^-\([^=]*\)=.*/'\1'/p" | tr "\\n" ","
'IMG.HEAD.LOGO.URL','LNK.COPYRIGHT.URL','LNK.FOOTSECURITY.URL','LNK.HEADHELP.URL','LNK.HEADYAHOO.URL','LNK.PRIVACY.URL','LNK.TOS.URL','STR.HEAD.LOGO.HEIGHT','STR.HEAD.LOGO.WIDTH','REG.TOS.MAIL.URL','UPGR
It gets cut off at 'UPGR where line ends. What could be causing this problem, how can I fix this ?

Your output is wider than your screen
You can force the output to wrap by piping it through less -+S, you'll have to use your arrow keys to view all of the output.
There's an option in screen to toggle wrapping on or off; you may have luck with that as well: https://www.gnu.org/software/screen/manual/html_node/Wrap.html

Another method besides less is to pipe it through cat:
ps aux | cat
top | cat
That won't pause at every screenful, like less or more would do, but when programs would otherwise halt until it receives user input, when they detect that their output is being piped to another process, they just dump out the results and keep going.
I use this a lot with external diff programs attached to my git or svn flags: git diff | cat keeps feeding my diff program all the extra files after the first one, while git diff by itself doesn't.

Related

How to overwrite previous output in bash

I have a bash script, that outputs top most CPU intensive processes every second to the terminal.
tmp=$(ps -e -eo pid,cmd,%mem,%cpu,user --sort=-%cpu | head -n 11)
printf "\n%s\n" "$tmp[pid]"
I know that I can move my cursor to the predeclared position, but that fails every time terminal is not cleared.
I could also just go to the beginning of the line and write over it, but that again makes a problem when current output is shorter that the previous and when the number of lines is not the same as it was at the previous output.
Is there a way to completely erase the previous output and write from there?
Yes, you can clear a part of the screen before each iteration (see https://unix.stackexchange.com/questions/297502/clear-half-of-the-screen-from-the-command-line), but the function watch does it for you. Try:
watch -n 1 "ps -e -eo pid,cmd,%mem,%cpu,user --sort=-%cpu | head -n 11"

Unix/Linux and MQ scripts explaination

echo "DISPLAY QL($Queue) CURDEPTH" \
| runmqsc Queue_Managr \
| grep 'CURDEPTH(' \
| sed 's/.*CURDEPTH//' \
| tr -d '()'.
Can anyone suggest how this script works? Actually this command displays the current depth value for a particular Q_Manager for a particular queue.
I understand "DISPLAY QL($Queue) CURDEPTH" | runmqsc Queue_Managr" - this command displays the queue name and curdepth{value}.
But I don't understand grep 'CURDEPTH(' | sed 's/.*CURDEPTH//' | tr -d '(). How does this command work?
It's a pipeline. It contains five stages, separated by the pipe character |. The output of one stage is used as the input to the next stage.
echo "DISPLAY blatti blatti" - this just outputs some text.
runmqsc Queue_Managr - Uses the text as input to the runmqsc-command, which does some MQ magic and outputs data.
grep 'CURDEPTH(' - Grep is a standard unix utility. It filters its input. In this case, only lines containing the text CURDEPTH( is allowed through to the next stage.
sed 's/.*CURDEPTH//' - Sed is another standard utility. It's short for "stream editor", and allows you edit the input as it passes through. In this case, the expression 's/.*CURDEPTH//' means to delete everything from the start of each line, up to and including the text CURDEPTH. (remember, only lines containing that text was passed through from the previous stage).
tr -d '()' - Finally, another standard utility, tr, which also allows editing the text that flows through from input to output. -d '()' means delete the characters ( and ) from the text.
The output from the final stage is shown in the terminal (if you ran your script in a terminal).
It's a fairly common way of building scripts in a unix shell. Generate the input data somehow, push it to a command, and massage the output data through a couple of stages each doing its little bit.
Long dissertations can be (and probably have been) written about all of grep, sed and tr. Look them up if you're interested.
CURDEPTH(3) DEFBIND(OPEN)
Notice that there are 2 pairs of attribute-value in this output. We need to handle only the appropriate pair.
We might be tempted to use the "cut" command to do simple trimming of the first pair to get the value.
However, the output from runmqsc for queues that have very long names (such as 48 characters) shows CURDEPTH as the 2nd pair (as shown below). Thus, a simple use of "cut" is no longer possible:
CRTIME(09.08.08) CURDEPTH(3)
The use of the "sed" (stream editor) can help us to get the value. Notice that the parenthesis are included.
$ echo "DISPLAY QL($QNAME) CURDEPTH" | runmqsc $QMNAME | grep 'CURDEPTH(' | sed 's/.*CURDEPTH//'
(3)
Notice that the answer is: (3)
Finally, it is necessary to remove the open and close parenthesis. This can be done using "tr" as follows:
$ echo "DISPLAY QL($QNAME) CURDEPTH" | runmqsc $QMNAME | grep 'CURDEPTH(' | sed 's/.*CURDEPTH//' | tr -d '()'
3
Notice that the answer is: 3

Continuous grep, output at same spot on console

I use
tail -f file | grep pattern
all the time for continuous grep.
However, is there a way I can make grep output its pattern at the same spot, say at the top of the screen? so that the screen doesn't scroll all the time?
My case is something like this: tail -f log_file | grep Status -A 2 will show the current status and what changed it to that status. The problem is the screen scrolls and it becomes annoying. I'd rather have the output stuck on the first 3 lines in the screen.
Thank you!
you could use the watch command; which will always execute the same command, but the position on the screen will stay the same. The process might eat some more CPU or memory though:
watch "tail file | grep pattern"
by default watch executes that command every 2 seconds. You can adjust up to 0.1 seconds using:
watch -n 0.1
NOTE
As noted by #etanReisner: this is not exactly the same as tail -f: tail -f will change immediately if something is added to your logfile, the watch command will only notice that when it executes, ie every 2 (or 0.1 seconds).
Assuming you are using a vt100 compatible emulator...
This command will tail a file, pipe it into grep, read it a line at a time and then display it in reverse on the top line of the screen:
TOSL=$(tput sc;tput cup 0 0;tput rev;tput el)
FROMSL=$(tput sgr0; tput rc)
tail -f file | grep --line-buffered pattern | while read line
do
echo -n "$TOSL${line}$FROMSL"
done
It assumes your output appears a line at a time. If you want more than one line, you can read more than a line, but you have to decide how you want to buffer the output. You could also use the csr terminfo command to set up an entire separate scrolling region instead of just having one line.
Here is the scrolling region version with a ten line status area at the top:
TOSL=$(tput sc; tput csr 0 10; tput cup 10 0;tput rev;tput el)
FROMSL=$(tput sgr0; tput rc;tput csr 10 50;tput rc)
tail -f file | grep --line-buffered pattern | while read line
do
echo -n "$TOSL${line}
$FROMSL"
done
Note that it is not impossible that your display will be corrupted from time-to-time as it could be that the output from your main shell and your background task get mixed up.
Simply replace the newlines with carriage returns.
tail -f file | grep --line-buffered whatever | tr '\012' '\015'
The line buffering is to avoid jumpy output; see http://mywiki.wooledge.org/BashFAQ/009
This is quick and dirty. As noted in comments, this will leave the previous contents of the line underneath, so a shorter line will not completely overlay a longer line. You could add some control codes to address that, but then you might as well use Curses for the formatting too, like in rghome's answer.

search with in Data displayed as a result of tail Operation?

I am working on a Java EE application where its logs will be generated inside a Linux server .
I have used the command tail -f -n -10000 MyLog
It displayed last 1000 lines from that log file .
Now I pressed Ctrl + c in Putty to disconnect the logs updation ( as i am feared it may be updated with new requests and I will loose my data )
In the displayed result, how can I search for a particular keyword ?? (Used / String name to search but it's not working)
Pipe your output to PAGER.
tail -f -n LINE_CNT LOG_FILE | less
then you can use
/SEARCH_STRING
Two ways:
tail -n 10000 MyLog| grep -i "search phrase"
tail -f -n 10000 MyLog | less
The 2nd method will allow you to search with /. It will only search down but you can press g to go back to the top.
Edit: On testing it seems method 2 doesn't work all that well... if you hit the end of the file it will freeze till you ctrl+c the tail command.
You need to redirect the output from tail into a search utility (e.g. grep). You could do this in two steps: save the output to a file, then search in the file; or in one go: pipe the ouput to the search utility
To see what goes into the file (so you can hit Ctlr+c) you can use the tee command, which duplicates the output to the screen and to a file:
tail -f -n -10000 MyLog | tee <filename>
Then search within the file.
If you want to pipe the result into the search utility, you can use the same trick as above, but use your search program instead of tee
Controlling terminal output on the fly
While running any command in a terminal such as Putty you can use CTRL-S and CTRL-Q to stop and start output to the Putty terminal.
Excluding lines using grep
If you want to exclude lines that contain a specific pattern use grep -v the following would remove all line that contain the string INFO
tail -f logfile | grep -v INFO
Show lines that do not contain the words INFO or DEBUG
tail -f logfile | grep -v -E 'INFO|DEBUG'
Finally, the MOTHER AND FATHER of all tailing tools is xtail.pl
If you have perl on your host xtail.pl is a very nice tool to learn and in a nutshell you can use it to tail multiple files. Very handy.
You can just open it with less command
less logfile_name
when you open the file you can use this guide here
Tip: I suggest, first to use G to go to the end of the file and then to you use Backward Search

UNIX sort: Sorting something from the clipboard

The other day I saw a colleague of mine using sort to sort a number of lines he copied from a text file.
I've been trying to reproduce it myself and I cannot seem to find how.
The requirements are as follow:
Use sort from command line, plus whatever else you need to add to configure input
Paste the text to be sorted from the clipboard
Get the sorted result in the console
If you type sort - the command will accept input from stdin. Then you can just paste whatever you want into the console and type CTRL-D to sort it.
Easy, just type sort (or sort -) to run on stdin, paste your lines, and hit CTRL+D for end-of-transmission to sort.
Use xclip.
xclip -o | sort -
I did something like:
xclip -o | sort > /tmp/xclip_temp; xclip -i < /tmp/xclip_temp;cat /tmp/xclip_temp; rm /tmp/xclip_temp
It does:
Stores the sorted input from the clipboard in the /tmp/xclip_temp file;
Puts the sorted input from the file back to the clipboard;
Prints the sorted value on the console;
And finally deletes the temp file;
The reason I am using ; instead of | is because pipe works as a parallel process, so if I used just | I would be overwriting the value of xclip while it was still being read.
For your convenience, you can add a function in your ~/.bashrc file, like this:
sort_xclip()
{
xclip -o | sort > /tmp/xclip_temp; xclip -i < /tmp/xclip_temp; cat /tmp/xclip_temp; rm /tmp/xclip_temp;
}
So you can just type sort_xclip when you want to do it again.
PS: After you edit the ~/.bashrc, run source ~/.bashrc, then the terminal will loads the function you just created.

Resources