extract syscall names from strace output - linux

I use the following command to extract syscall names from strace output:
strace ls 3>&1 1>&2 2>&3 3>&- | grep -P -o '^[a-z]*(?=\()'
but this command also includes the ls output in the output.
how can I prevent that?

There are two options to strace that will help you get what you want:
-c will output a table of all system calls run by the command, together with the number of times they were called and CPU usage.
$ strace -c ls
Desktop Documents Downloads Music Pictures Public Templates Videos
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
31.07 0.000653 20 32 mmap
9.94 0.000209 20 10 mprotect
9.80 0.000206 12 16 read
8.28 0.000174 15 11 close
7.61 0.000160 16 10 fstat
6.90 0.000145 16 9 openat
2.47 0.000052 17 3 3 ioctl
...
The -o option will send strace's output to a file, so it won't get mixed in with your process's output.
The following will run the ls command, diverting its output to /dev/null, and will send strace's output to an awk script to extract the last column:
$ strace -o >(awk '$1 ~ /^-----/ { toprint = !toprint; next } { if (toprint) print $NF }') \
-c ls >/dev/null 2>/dev/null
mmap
mprotect
read
close
fstat
openat
ioctl
...

Finally I found a solution with the help of this link: http://mywiki.wooledge.org/BashFAQ/047
strace ls 2>&1 >/dev/null | grep -P -o '^[a-z]*(?=\()'
and a useful variant to count the syscalls:
strace ls 2>&1 >/dev/null | grep -P -o '^[a-z]*(?=\()' | sort | uniq -c | sort -nr
And a better solution using Mark Plotnick's answer:
strace -o >(grep -P -o '^[a-z]*(?=\()' | sort | uniq -c | sort -nr) ls &>/dev/null

Related

linux shell script stops after first line

I try to execute etherwake based on a MQTT topic.
The output of mosquitto_sub stops if I pipe it in a while statement.
works:
# mosquitto_sub -L mqtt://... | grep -o -E '([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}'
00:00:00:00:de:ad
00:00:00:00:be:ef
00:00:00:00:ca:fe
(goes on and on)
does not work:
mosquitto_sub -L mqtt://... \
| grep -o -E '([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}' \
| hexdump
Output stops after a single line:
0000000 1234 5678 9abc def0 abcd cafe 3762 3a65
The big picture is this one:
mosquitto_sub -L mqtt://... \
| grep -o -E '([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}' \
| while read macaddr; do
echo "send WOL to " $macaddr;
/usr/bin/etherwake -D -b "$macaddr" 2>&1;
done
Usually I am fine with the Linux shell but this time it simply gets stuck after the first line.
My guess is there is some problem with stdin or stdout (is not read or full etc.) in some kind. But I am out ideas.
By the way its an OpenWRT shell so an ash and no bash.
The problem is indeed the "buffering" of grep when used with pipes.
Usually the '--line-buffered' switch should be used to force grep to process the data line by line instead of buffer the data.
Because grep on OpenWRT (busybox) does not have this switch 'awk' is used:
mosquitto_sub -L mqtt://... \
| awk '/([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}/{ print $0 }' \
| hexdump
If there is no busybox version of grep used the solution would be like:
mosquitto_sub -L mqtt://... \
| grep -o --line-buffered -E '([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}' \
| hexdump
Thank you all a lot for your help.

wc -c and wc -m give the same output all the time?

I am having the following doubt. wc -m and wc -c are always giving same output. I tried with floating point numbers also but the output is same for both the commands.
cat test | wc -m
541
cat test | wc -c
541
ASCII character takes byte. But UTF-8 local charaters takes 2 bytes.
echo -n "ŻÓŹŁŃĘ"|wc -m
6
echo -n "ŻÓŹŁŃĘ"|wc -c
12
P.S. You can wc -m test to save cat.

Junk characters being printed with tee command

Script I'm utilizing is below:
#!/bin/bash
lla=$(top -n 1 | grep "load average" | awk '{print $13,$14,$15}')
mem_usage=$(free | grep Mem | awk '{print $3/$2 * 100.0}')
now=`date`
cur_time=$(echo $now | awk '{print $4}')
for i in {1..60}
do
echo "System Performance Statistics at: "$cur_time | tee -a hp.txt
echo "Linux Load Average: "$lla | tee -a hp.txt
echo "Memory Usage: "$mem_usage | tee -a hp.txt
echo "" | tee -a hp.txt
sleep 3
done
Results:
System Performance Statistics at: 19:00:29
Linux Load Average: 0.13, 0.11, 0.14^[(B^[[m^[[39;49m^[[K
Memory Usage: 82.7672
Standard out isn't showing any garbage characters at all. What do I need to change?
Added -b to top command and it works.
From man top:
-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.

how to capture the output of "sort -c" in linux

I am trying to capture the output of "sort -c" in linux. I tried redirecting it to a file, used tee command but both did not helped. Any suggestions ?
For example:
roor>cat db | sort -c
sort: -:319: disorder: 1842251880: aa bb bc dd ee
Following failed to give me output
roor>cat db | sort -c > fileName
roor>cat db | sort -c |tee fileName
Sample file:
>cat file
111 aa as sdasd
222 sadf dzfasf af
333 sada gvsdgf h hgfhfghfg
444 asdfafasfa gsdgsdg sgsg
222 asdasd fasdfaf asdasdasd
root>cat file |sort -c
sort: -:5: disorder: 222 asdasd fasdfaf asdasdasd
8>sort -c db 2> fileName
sort: extra operand `2' not allowed with -c
0>sort -c < file 2> result1.txt
sort: open failed: 2: No such file or directory
ANY ALTERNATE TO SORT -C would ALSO WORK FOR ME!!
If sort -c is producing an error, it sends that error to "standard error" (stderr), not to "standard output" (stdout).
In shell, you need to use special redirects to capture standard error.
sort -c inputfile > /path/to/stdout.txt 2> /path/to/stderr.txt
These two output streams are called "file descriptors", and you can alternately redirect one of them to the other:
sort -c inputfile > /path/to/combined.txt 2>&1
You can read more about how these work at tldp.org, in the Bash reference manual, the bash-hackers wiki and the Bash FAQ. Happy reading! :-D
other good alternative for '2>' is STDERR pipe
|&
cat db | sort -c -h |& tee >fileName
Some time it is very suitable when present STDIN, for example:
TIMEFORMAT=%R;for i in `seq 1 20` ; do time kubectl get pods -l app=pod >/dev/null ; done |& sort -u -h
or
TIMEFORMAT=%R;for i in `seq 1 20` ; do time kubectl get pods >>log1 ; done |& sort -u -h
sort -c has no output as you might expect:
[root#home:~] cat /etc/services | sort -c
sort: -:2: disorder: #
As described by the manpage, the -c argument simply checks whether a given file or input is sorted or not.
If you're trying to catch the message from the command, try redirecting the error stream (2), not the standard output (1):
cat file | sort -c 2>result.txt
sort -conly checks if the input is sorted. It does not performs any sorting.
See: man sort
Remove -c to sort the lines.
PS: It gives the "disorder" error because the file of yours isn't already sorted. On line 5, "222" appears after "444" on the previous line.
EDIT: I think I misunderstood.
To redirect the error to a file you must use 2>.
So, the command would become: roor>cat db | sort -c 2> fileName
EDIT2: You can simply use: sort -c db 2> fileName

Finding process count in Linux via command line

I was looking for the best way to find the number of running processes with the same name via the command line in Linux. For example if I wanted to find the number of bash processes running and get "5". Currently I have a script that does a 'pidof ' and then does a count on the tokenized string. This works fine but I was wondering if there was a better way that can be done entirely via the command line. Thanks in advance for your help.
On systems that have pgrep available, the -c option returns a count of the number of processes that match the given name
pgrep -c command_name
Note that this is a grep-style match, not an exact match, so e.g. pgrep sh will also match bash processes. If you want an exact match, also use the -x option.
If pgrep is not available, you can use ps and wc.
ps -C command_name --no-headers | wc -l
The -C option to ps takes command_name as an argument, and the program prints a table of information about processes whose executable name matches the given command name. This is an exact match, not grep-style. The --no-headers option suppresses the headers of the table, which are normally printed as the first line. With --no-headers, you get one line per process matched. Then wc -l counts and prints the number of lines in its input.
result=`ps -Al | grep command-name | wc -l`
echo $result
ps -Al | grep -c bash
You can try :
ps -ef | grep -cw [p]rocess_name
OR
ps aux | grep -cw [p]rocess_name
For e.g.,:
ps -ef | grep -cw [i]nit
Some of the above didn't work for me, but they helped me on my way to this.
ps aux | grep [j]ava -c
For newbies to Linux:
ps aux prints all the currently running processes, grep searches for all processes that match the word java, the [] brackets remove the process you just ran so it wont include that as a running process and finally the -c option stands for count.
List all process names, sort and count
ps --no-headers -A -o comm | sort | uniq -c
You also can list process attached to a tty
ps --no-headers a -o comm | sort | uniq -c
You may filter with:
ps --no-headers -A -o comm | awk '{ list[$1] ++ } END { for (i in list) { if (list[i] > 10) printf ("%20s: %s\n", i, list[i]) } }'
Following bash script can be run as a cron job and you can possibly get email if any process forks itself too much.
for i in `ps -A -o comm= --sort=+comm | uniq`;
do
if (( `ps -C $i --no-headers | wc -l` > 10 )); then
echo `hostname` $i `ps -C $i --no-headers | wc -l` ;
fi
done
Replace 10 with your number of concern.
TODO: "10" could be passed as command line parameter as well. Also, few system processes can be put into exception list.
You can use ps(will show snapshot of processes) with wc(will count number of words, wc -l option will count lines i.e. newline characters).
Which is very easy and simple to remember.
ps -e | grep processName | wc -l
This simple command will print number of processes running on current server.
If you want to find the number of process running on current server for current user then use -U option of ps.
ps -U root | grep processName | wc -l
change root with username.
But as mentioned in lot of other answers you can also use ps -e | grep -c process_name which is more elegant way.
ps aux | wc -l
This command shows number of processes running on the system by all the users.
For a specific user you can use the following command:
ps -u <username> | wc -l
replace with the actual username before running :)
ps -awef | grep CAP | wc -l
Here "CAP" is the word which is in the my Process_Names.
This command output = Number of Processes + 1
This is why When we are running this command , our system read thats "ps -awef | grep CAP | wc -l " is also a process.
So yes our real answer is (Number of Processes) = Command Output - 1
Note : These processes are only those processes who include the name of "CAP"

Resources