htop output to human readable file - formatting

I've tried piping htop to a text file (e.g. htop > text.txt) but it gives me text garbled by formatting strings (see below). Is there a way to get nicer, human readable output?
^[7^[[?47h^[[1;30r^[[m^[[4l^[[?1h^[=^[[m^[[?1000h^[[m^[[m^[[H^[[2J^[[1B ^[[36m1 ^[[m^[[1m[^[[m^[[32m||||||||||^[[31m||||||||||^[[30m^[[1m \
22.2%^[[m]^[[m ^[[36mTasks: ^[[1m159^[[m^[[36m total, ^[[32m^[[1m5^[[m^[[36m running^[[3;3H2 ^[[m^[[1m[^[[30m \
0.0%^[[m]^[[m ^[[36mLoad average: ^[[30m^[[1m1.11 ^[[m^[[m1.28 ^[[1m1.31 ^[[4;3H^[[m^[[36m3 ^[[m^[[1m[^[[m^[[32m||||||||||^[[30m^[[1m \
11.1%^[[m]^[[m ^[[36mUptime: ^[[1m9 days, 22:04:51^[[5;3H^[[m^[[36m4 ^[[m^[[1m[^[[30m 0.0\
%^[[m]^[[6;3H^[[m^[[36m5 ^[[m^[[1m[^[[m^[[31m||||||||||^[[30m^[[1m 11.1%^[[m]^[[7;3H^[[m^[[36m6 ^[[m^[[1m[^[[30m \

htop author here.
No, there's no "nice" way to get the output of htop piped into a file. It is an interactive application and uses terminal redraw routines to produce its interface (therefore, piping it makes as much sense as, for example, piping vim into a text file -- you'll get similar results).
To get the information about your processes in a text format, use "ps". For example, ps auxf > file.txt gives you lots of easy to parse information (or ps aux if you do not wish tree-formatting -- see man ps for more options).

htop outputs ANSI escape code to use colors and move the cursor around the terminal. There is a great command line program aha that can be used to convert ANSI into HTML.
Ubuntu/Debian installation
apt-get install aha
Save htop output as HTML file
echo q | htop | aha --black --line-fix > htop.html

I have had the same need, and ended up using top instead of htop a is provides a batch mode via the -b flag.
-b : Batch mode operation
Starts top in 'Batch mode', which could be useful for sending output from top to other programs or to a file. In this mode, top will not accept input and runs until the iterations limit you've set with the '-n' command-line option or until killed.
So for example:
top -b -n 1
Hope this helps even if this is not using htop.

This command outputs plain text. (It requires installing aha and html2text.)
echo q | htop -C | aha --line-fix | html2text -width 999 |
grep -v "F1Help\|xml version=" > file.txt

You can also use script prior to running htop in a mode that will redirect timings to a file for later playback. In the realm of 'yet another work around' and 'good for show and tell'.
script -t -a /var/tmp/script.htop.out 2> /var/tmp/script.htop.out.timings
htop
Then to playback
scriptreplay /var/tmp/script.htop.out.timings /var/tmp/script.htop.out

Install recode first, then encode it to utf-8:
$htop | recode utf-8 > test.txt
Then cat the file and you should be good.

Based on the previous answers, I suggest use python to do some post-processing. The codes are as follows:
First, we get the text from htop:
echo q | htop -C > a.txt
Then, we use python to make it human-readable:
import re
htop = open("a.txt").read()
print(re.sub(r'\x1B(?:[#-Z\\-_]|\[[0-?]*[ -/]*[#-~])', "", re.sub(r"\x1b\[\d\d;\dH|\x1b\[\d;3H", "\n", '\n'.join(htop)))[9:])
The results are as follows:
1 [ 0.0%] Tasks: 11, 38 thr; 1 running
2 [ 0.0%] Load average: 0.38 0.26 0.11
3 [ 0.0%] Uptime: 01:19:50
4 [ 0.0%]
Mem[|#**** 700M/25.5G]
Swp[ 0K/0K]
PID USER PRI NI VIRT RES SHR S CPU% MEM% TIME+ Command
51 root 20 0 359M 62880 33428 S 0.0 0.2 0:00.00 /tools/node/bin
52 root20 0 359M 62880 33428 S 0.0 0.2 0:00.21 /tools/node/bin
53 root20 0 359M 62880 33428 S 0.0 0.2 0:00.19 /tools/node/bin
54 root20 0 359M 62880 33428 S 0.0 0.2 0:00.16 /tools/node/bin
55 root20 0 359M 62880 33428 S 0.0 0.2 0:00.15 /tools/node/bin
56 root20 0 359M 62880 33428 S 0.0 0.2 0:00.00 /tools/node/bin
57 root20 0 359M 62880 33428 S 0.0 0.2 0:00.05 /tools/node/bin
58 root20 0 359M 62880 33428 S 0.0 0.2 0:00.04 /tools/node/bin
59 root20 0 359M 62880 33428 S 0.0 0.2 0:00.05 /tools/node/bin
60 root20 0 359M 62880 33428 S 0.0 0.2 0:00.04 /tools/node/bin
1 root20 0 359M 62880 33428 S 0.0 0.2 0:08.76 /tools/node/bin
16 root20 0 35892 4768 3660 S 0.0 0.0 0:00.62 tail -n +0 -F /
75 root20 0 190M 61096 13512 S 0.0 0.2 0:00.00 /usr/bin/python
76 root20 0 190M 61096 13512 S 0.0 0.2 0:00.56 /usr/bin/python
F1Help F2Setup F3SearchF4FilterF5Tree F6SortByF7Nice -F8Nice +F9Kill F10Quit

This may sound really noobish, however, if you have multiple monitors you could have htop running while "record my desktop" is capturing that area. Its more of a video and may not help with searching and sorting but it would look nice and pretty.

Related

What is the most minimalistic way to run a program inside an OS?

Generally, when I start a program from bash, it forks bash and inherits many things from it, like stdin, stdout. Is there some other way to run a program, with no such setup? Maybe it explicitly opens fd 1, writes something and closes it?
I came across nohup and disown. But both of those detaches a running process from bash, but initially still the process inherits from bash. Maybe is there a way to start a process that inherits from nothing?
I am asking this just out of curiosity, and have no practical purposes. When a program is ran in a microcontroller, it is just our program that is running with no additional setup (if setup is required, user have to prepend it). Similarly, is there a way even in the presence of an operating system, to run just what is programmed, without any setups?
I assume you are using Linux.
Printing top -u root you see for eg on my system (Ubuntu 20.04 x86_64):
PID PPID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 0 root 20 0 170380 11368 6500 S 0.0 0.0 0:23.52 systemd
2 0 root 20 0 0 0 0 S 0.0 0.0 0:00.61 kthreadd
3 2 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_gp
4 2 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_par_gp
5 2 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 netns
10 2 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 mm_percpu_wq
11 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_tasks_rude_
12 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_tasks_trace
13 2 root 20 0 0 0 0 S 0.0 0.0 0:04.48 ksoftirqd/0
14 2 root 20 0 0 0 0 I 0.0 0.0 1:28.82 rcu_sched
You see that all processes inherit ultimately from PPID (parent process ID) zero.
This process is not a process, it represents the Linux scheduler. Then systemd (PID 1) is launched by the kernel and every other process in the system is launched by systemd.
At a user level top -u madfred
3371 1 madfred 20 0 19928 7664 6136 S 0.0 0.0 0:11.62 systemd
3372 3371 madfred 20 0 170404 2460 0 S 0.0 0.0 0:00.00 (sd-pam)
3379 3371 madfred 39 19 659828 16348 12500 S 0.0 0.0 0:02.38 tracker-miner-f
3402 3371 madfred 20 0 8664 5112 3412 S 0.0 0.0 0:00.94 dbus-daemon
3407 3371 madfred 20 0 239712 6740 6064 S 0.0 0.0 0:00.03 gvfsd
There is one user systemd that is launched by the root systemd and runs as the user. This user systemd is in charge of launching every process for that user.
That is necessary for assuring all the guarantees that the Linux OS provides as security, memory protection, file resources etc.
What you want would be to replace the kernel with something else, which is very possible. Check for example:
https://wiki.osdev.org/Bare_bones
https://github.com/contiki-ng/contiki-ng
It is pretty easy to replace systemd (or the old /sbin/init) with your own custom initializer. Check this answer:
Writing my own init executable

How come apply on multiple columns in dataframe does not work?

I am trying to remove '$' sign and convert value to a float for multiple columns in a dataframe.
I have a dataframe that looks something like this:
policy_status sum_assured premium riders premium_plus
0 A 1252000 $ 1500 $ 1.0 1100 $
1 A 1072000 $ 2200 $ 2.0 1600 $
2 A 1274000 $ 1700 $ 2.0 1300 $
3 A 1720000 $ 2900 $ 1.0 1400 $
4 A 1360000 $ 1700 $ 3.0 1400 $
I have this function:
def transform_amount(x):
x=x.replace('$','')
x=float(x)
return x
when I do this:
policy[['sum_assured','premium','premium_plus']]=policy[['sum_assured','premium','premium_plus']].apply(transform_amount)
the following error occured:
TypeError: ("cannot convert the series to <class 'float'>", 'occurred at index sum_assured')
Does anyone know why?
If need working elementwise use DataFrame.applymap:
cols = ['sum_assured','policy_premium','rider_premium']
policy[cols]=policy[cols]].applymap(transform_amount)
Better is use DataFrame.replace with regex=True, but first escape $ because special regex value and convert columns to floats:
cols = ['sum_assured','premium','premium_plus']
policy[cols]=policy[cols].replace('\$','', regex=True).astype(float)
print (policy)
policy_status sum_assured premium riders premium_plus
0 A 1252000.0 1500.0 1.0 1100.0
1 A 1072000.0 2200.0 2.0 1600.0
2 A 1274000.0 1700.0 2.0 1300.0
3 A 1720000.0 2900.0 1.0 1400.0
4 A 1360000.0 1700.0 3.0 1400.0

Export image with GDAL. Poor quality

I use the following command to export a jpg file:
gdaldem color-relief C:\input.tif C:\colors.txt C:\output.jpg
The file colors.txt:
-0.99 255 38 0
-0.5 255 81 0
-0.3 255 119 0
-0.2 255 153 0
-0.1 255 187 0
-0 255 221 0
0.1 255 255 0
0.2 206 224 0
0.3 164 196 0
0.4 122 171 0
0.5 85 145 0
0.6 48 120 0
1 0 97 0
The problem is that the file looks different when I display it in the standard Windows software to display images or when I show it in arcmap.
This is how it looks good and is shown in arcmap:
ARCMAP
This is how it is displayed in the Windows program:
WINDOWS
Does anyone have any idea how to display this in Windows software as it appears in arcmap software?
Thanks

Too many rcuob and rcuos are shown

On my Linux server, Too many rcuob and rcuos process are shown.
Execute a following command.
ps auxwwf | grep rcu
And shown below.
root 9 0.0 0.0 0 0 ? S 5月30 0:00 \_ [rcuob/0]
root 10 0.0 0.0 0 0 ? S 5月30 0:00 \_ [rcuob/1]
:
:
root 151 0.0 0.0 0 0 ? S 5月30 0:00 \_ [rcuob/142]
root 152 0.0 0.0 0 0 ? S 5月30 0:00 \_ [rcuob/143]
and
root 154 0.0 0.0 0 0 ? S 5月30 0:11 \_ [rcuos/0]
root 155 0.0 0.0 0 0 ? S 5月30 0:04 \_ [rcuos/1]
:
:
root 296 0.0 0.0 0 0 ? S 5月30 0:00 \_ [rcuos/142]
root 297 0.0 0.0 0 0 ? S 5月30 0:00 \_ [rcuos/143]
The server's CPU is "Intel(R) Xeon(R) CPU E5-2630 v3 # 2.40GHz"
Total Memory is "32GB"
and OS is"CentOS Linux release 7.2.1511 (Core)"
I do not know what these are, and if they are the problem, please let me know the procedure to fix it.
I noticed the same behaviour on RHEL7.2 3.10.0-327.el7.
https://access.redhat.com/solutions/1404313 has the title More "rcuob" and "rcuos" kernel threads running than there are CPUs online, and describes how the RCU threads started did not match the number of online CPUs, but the number of possible CPUs. It explains a fix has been released with an errata RHSA-2016-2574, kernel 3.10.0-514.el7. I imagine CentOS will also have a fix.
To view the number of online CPUs and the number of possible CPUs:
> cd /sys/devices/system/cpu ; grep '' {online,offline,possible}
online:0-55
offline:56-191
possible:0-191
Count the number of rcuob and rcuos kernel threads:
> ps aux | awk '/\[(ksoftirqd|migration|watchdog|rcuo)/{print $11}' | sed 's/[0-9]//g' | sort | uniq -c
56 [ksoftirqd/]
56 [migration/]
192 [rcuob/]
192 [rcuos/]
56 [watchdog/]

AWK print next line of match between matches

Let's presume I have file test.txt with following data:
.0
41
0.0
42
0.0
43
0.0
44
0.0
45
0.0
46
0.0
START
90
34
17
34
10
100
20
2056
30
0.0
10
53
20
2345
30
0.0
10
45
20
875
30
0.0
END
0.0
48
0.0
49
0.0
140
0.0
With AWK how would I print the lines after 10 and 20 between START and END.
So the output would be.
100
2056
53
2345
45
875
I was able to get the lines with 10 and 20 with
awk '/START/,/END/ {if($0==10 || $0==20) print $0}' test.txt
but how would I get the next lines?
I actually got what I wanted with
awk '/^START/,/^END/ {if($0==10 || $0==20) {getline; print} }' test.txt
Range in awk works fine, but is less flexible than using flags.
awk '/^START/ {f=1} /^END/ {f=0} f && /^(1|2)0$/ {getline;print}' file
100
2056
53
2345
45
875
Don't use ranges as they make trivial things slightly briefer but require a complete rewrite or duplicate conditions when things get even slightly more complicated.
Don't use getline unless it's an appropriate application and you have read and fully understand http://awk.info/?tip/getline.
Just let awk read your lines as designed:
$ cat tst.awk
/START/ { inBlock=1 }
/END/ { inBlock=0 }
foundTgt { print; foundTgt=0 }
inBlock && /^[12]0$/ { foundTgt=1 }
$ awk -f tst.awk file
100
2056
53
2345
45
875
Feel free to use single-character variable names and cram it all onto one line if you find that useful:
awk '/START/{b=1} /END/{b=0} f{print;f=0} b&&/^[12]0$/{f=1}' file