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 quotesgrep -o '[^"]*[^"]'
- select text within the double quoteswhile read -r line
- store each line into$line
anddo
some action (help read
)printf "%b" $line
- print line by expanding backslash escape sequencestr "\r\n" "\275\276"
- temporarily replace\r\n
into\275\276
tr -d "[:cntrl:]"
- remove all control characterstr "\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
"Bad Interpreter" Error Message When Trying to Run Awk Executable
Can Someone Explain the Shell Shock Bash Code
How to Print the Nth (5Th) Line of Every File Preceded by the Filename Using Any Linux Tool
How to Make My .Bat File Run Linux Command to Remote Linux
Stack Smashing Code Not Working on Linux Kernel 2.6.38.7... Please Help
Merge Two Files Using Awk in Linux
Segmentation Fault with a Variable in Section .Data
How to Run a SQL Script in Tsql
Linux Command Ambiguous Redirect
How to Run Multiple Programs in a Sequence
How to Escape the Bang (!) Character in Linux Bash Shell
Bash - Calculate the Average of Numbers Inputted
Split File into Multiple File Using Awk, But in Date Format
Shell Script to Delete Files When Disk Is Full
Find Command Find Directories That Were Created After a Certain Date Under Linux/Cygwin