Print the Output of Strace Command in a Text File

Print custom text into strace. Strace comments

write() to an out-of-range file descriptor shows up well in strace output, and should be much faster - the range check happens early, and it doesn't need to look at the data at all. (You need to pass the length of the data to be written, rather than just a 0-terminated string, but gcc will normally optimise strlen() of a constant string to a constant.)

$ cat hw.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#define STRACE_TRACE(str) write(-1, str, strlen(str))

int main(void)
{
STRACE_TRACE("before");
printf("Hello world\n");
STRACE_TRACE("after");
return 0;
}
$ gcc -Wall -o hw hw.c
$ strace ./hw
...
write(-1, "before"..., 6) = -1 EBADF (Bad file descriptor)
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 150), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77da000
write(1, "Hello world\n"..., 12Hello world
) = 12
write(-1, "after"..., 5) = -1 EBADF (Bad file descriptor)
exit_group(0) = ?
$

trying to understand strace output

strace prints to stderr, not stdout. You need should redirect with 2> echo1.txt in order to redirect stderr to a file, or just use strace -o echo1.txt to explicitly write the strace output into that file.

How to parse strace in shell into plain text?

The problem why read doesn't work, because shell is already escaping the characters, so the string is doubled escaped, therefore \r\n is printed as rn.

To ignore escaping of characters by shell, you can use read -r which allow backslashes to escape any characters (so they're treated literally). Here is example:

while read -r line; do printf "%b\n" "$line"; done < strace.log | strings

Since it's a binary data, above example also includes strings command to display only printable strings.

Strace also support printing all strings in hex when -x is specified, but it'll work the same.


Here is the version to parse strace output in real-time:

while read -r line;
do printf "%b\n" "$line" | strings
done < <(sudo strace -e recvfrom,sendto -s 1000 -fp $(pgrep -n php) 2>/dev/stdout)

Further more strings, can be replaced by more specific filter using grep, to get only what is inside double quotes:

grep -o '".\+[^"]"' | grep -o '[^"]\+[^"]'

however this may still print binary formats.

To avoid that, lets simplify the whole process, so lets define the following formatter alias:

alias format-strace='grep --line-buffered -o '\''".\+[^"]"'\'' | grep --line-buffered -o '\''[^"]*[^"]'\'' | while read -r line; do printf "%b" $line; done | tr "\r\n" "\275\276" | tr -d "[:cntrl:]" | tr "\275\276" "\r\n"'

where:

  • grep -o '".\+[^"]"' - select double-quoted string with quotes
  • grep -o '[^"]*[^"]' - select text within the double quotes
  • while read -r line - store each line into $line and do some action (help read)
  • printf "%b" $line - print line by expanding backslash escape sequences
  • tr "\r\n" "\275\276" - temporarily replace \r\n into \275\276
  • tr -d "[:cntrl:]" - remove all control characters
  • tr "\275\276" "\r\n" - restore new line endings

then the complete example to trace some command (e.g. php) can look like:

strace -e trace=read,write,recvfrom,sendto -s 1000 -fp $(pgrep -n php) 2>&1 | format-strace

Check for similar example: How to view the output of a running process in another bash session? at Unix.SE

How to decode this information from strace output

My understanding of your problem is you try to compare what auditd sends to what your program sends by comparing strace output, and you have issues to convert the string provided by strace into a Go []byte datatype.

The strace output follows the GNU C representation of string literal, whose characters can be escaped as follows:

\\ Backslash character. 
\? Question mark character.
\' Single quotation mark.
\" Double quotation mark.
\a Audible alert.
\b Backspace character.
\e <ESC> character. (This is a GNU extension.)
\f Form feed.
\n Newline character.
\r Carriage return.
\t Horizontal tab.
\v Vertical tab.
\o, \oo, \ooo Octal number.
\xh, \xhh, \xhhh, ... Hexadecimal number.

Note that the number of octal or hex digits can be variable. In Go, characters can also be escaped but the rules are different - see http://golang.org/ref/spec#Rune_literals

In particular, the octal values are systematically on 3 digits to avoid any ambiguity. To declare a []byte with such a sequence of characters, you will have to write something like this:

// In strace, it was "\21\0\0\0\350\3\5\0\1\0\0\0\0\0\0\0\t"
wb := []byte("\021\000\000\000\350\003\005\000\001\000\000\000\000\000\000\000\t")

Note that the -x option in strace will use fixed-length hex encoding for non-printable characters, which makes the direct usage of these strings easier in a Go program. The -xx option will output hex encoded bytes even for printable characters, which makes it even easier IMO.

Anyway, it is not necessarily a good style (or even a good idea) to use literal strings to initialize []byte. Strings are for UTF-8 characters, not for binary data.

strace tmux output redirected to a file

Oh I got it. Strace doesn't print to stdout. It prints to stderr.

strace tmux 2> /tmp/blah works.



Related Topics



Leave a reply



Submit