Как разобрать strace в оболочке в обычный текст?

У меня есть журнал трассировки, сгенерированный strace команда как при запуске PHP:

sudo strace -e sendto -fp $(pgrep -n php) -o strace.log

И вывод выглядит так:

11208 sendto(4, "set 29170397297_-cache-schema 85 0 127240\r\n\257\202\v\0?\0\0\0\2\27\10stdClass\24\7\21\3cid\21\6schema\21\4d\37ata\25\n\247\21\5block\24\6\21\6fields\24\f\21\3bid\24\2\5\21\4type 0\37erial\21\10not null\5\21\6module\24\4\16\7\21\7va\37rchar\21\6length\6@\16\t\5\21\7default\r\21\5de\2lta@\5\16\v\16\f\6 \35\7\16\r\21\0010\21\5t \207C \ 30 @ 6 \ 2 \ 16 \ г \ гп \4tatus@0\4\21\3INT /\7\6\0\21\4size \222\finy\21\6weight\24\3 ;\0\22\300 \6\6region@8\340\5P\5custom \27\300,\17\16\23\16\24\21\n видимость \ 340 \ t \ 34 \ 7 \ 5 страниц \ 24 \ 2 \ 205 \ 3 \ 4tex @ \ 206 \ 261 \ 1it \ 365 \ 0 \ 5 \ 240 \0\377 y \ 10 \ r \ 21 \ ftransl! N \ 2ble% \ 1ca! a \ 340 \ 3Q \ 0 \ 1 n\31\vprimary key\24\1\6\0\16\6\21\vunique@\21\ts\24\1\21\3tmd\24\3 \31\0\20 2\v\n\6\2\16\16\21\7index \210\10\1\21\4list\24\5\240\36\0\21 \36\10\26\6\3\16\25\6\4\16\n \1\6\4\21\4name \7\0\na\317\2_ro \ 252 \ 0 \ 5! $ \ 0 \ n \ 3 \ 341 \ 2 \ 23 \ 0 \ 16 \ 340 \ 0 \ 16A \ 214 \ 2 \ 21 \ 3r! \ 354 @ \ v \ 22 \ 21 \ 10 без подписи \ 5 @ \ 332 \ 0 \ 36 \213\0\n \213\0\16 l\6%\16!\24\1\16% \ 271 \ 0% @ р \5\16#\ $ 16 \ 21 \ F \ 200л \241b@ п \ 2 \ 4 \ 16 \ 6 M\2\10\16&@E\4\21\4bod\201_\5\32\16\t\4\16\23B\\\2g\16\34 \30\3info .\0\7a\255\0\200@q!L\5\6forma\201\332B/!d\2\4\16\37 y\0* y \ 0 \ 225a; \ 240 \ 201 \ 2 '\ 21 \ van \ 0_ \207 \ 200 \ 2 \ 5 \ 16 \ 1 \ 340 \ 0U = @ U \ 1 \ 16 \ 3 @ \ 222 \ 212 \ 2lob @ O \ n \ 23 \ 16) \ 21 \ 6expire @ \ 30 \ 342 \ 0 \ 26 \ 7 \ 21 \ 7create \ 241 \ 17 < \25\0\n\203\1\"\177\0d Y \ 0 \ 22 \ 305 \ 5 \ 5small \ 240! A \ 32 \ 0. \230\0.\240\240\0\1\240\240\3,\21\vb S\2kpo\"\313\2s\24\6!\220\2\t\21\2\241q\0\10 ?\4\21\tno \213\6ort\5\21\fm\";\3ine_A\313 \ 232 \ 241 \ 3 \ 2 \5\16#\ 340 \ 4 \ 16! \ 345 \ 340 \ 0u \223\340\0'AC\4sourc\202\202\340\3\27\0\v\200\27\0_C\326\340\0074\1\16\21 _\240\363\2\1\16\25\340\3\16\ г \ 0 \ 21 \ vmultipliers \31\0- \223\1\21\t\341\0\30B-\0\1!\10\0003a\253\0005\ v \ 0005ac \ 327Dz \ "\ 364 \ 20 \ 0 \ 10 \ 6 \ 0 @ \ 333 \ r \ 0165 \ 16 \ 36 \ 0163 \ 21 \ nidenti $ x \ nr \ 0166 \ 21 \ vadmin_ce \ 10 \ 21 \ 5label \ 21 \ f \ 244H \ 6 крюк \ 21 \ 23 \ 240 \ r \ 0_ \ 340 \ 1 \ 375 \ fs \ 21 \ 3api \ 24 \ 4 \ 21 \ 5own F \ 0062 \ 16C \ 16B \ 21 \ 17 H \ 5imum_v \ 260 $ \ 25 \ 7 \ 6 \ 1 \ 21 \ 17curr m \ 340 \ 1 \ 22! \ 242 \ 0002 \ "\ 305 \ 0022 \ 21 \ 20 \ 340 \ 1N \ 5_groupa \ 247 \ 2 \ 6 \ 0163 \352\0\10 \352\2\0164\5 \325C%\341\0P\341\5\220\1\0162aQA\26\4\16:\5\21\17\201\321\1 c\"$\5back\21#\340\7b\0_\200!\340\3\311\1\16\7 C \ 340 \ 0a! \ 312 \ 1 \ no \ 300 # \ 240! & }\241\237\0\0\242e\341\4n\5\16;\24\10\16< \7\2=\21\35\340\1m\0 \ 320 \ 0 \ 342 \ 3XAz \ v \ 16> \ 16G \ 16? \ 16 @ \ 16A \ 21 \ 30 \ 341 \ tT \ 201 \ 5 \ 1 \ 21 \ 22 \ 200 \ 243 \ 0 B0 \ 6 строка #o\4toolsbD\1\16C \260\0D!D\4C\16L\16E!P\0F \3\201T\16G\21\21ckeditor_set%\266\0gE\323\0\5%Q\0# 4@\345!)\"W #\372\1\21\10\340\0!\0\1 \31\0\32\240\334\4#\16\n\21\10\300D \r\20O\21\25\300\r\6_input_\244+\340\16V\1\16+ \31\340\4h X\0\2!;\0# \245\0+ \247\0Q T\7R\21\26comme#/\0_%\266\2cko W\3pane;\4\5\24\10\21\7@\v\0_\243\257\301\231\1\21\4F\35!\340\1\22F\323\0021\21\10\"\311'B\0e@\223A\254&f`\346\"~\6\vcollap&q%\227\340\6\35\2\0\21\ т \ 240 \ 35 \ 344 \ 1а \3009\0\0#\212\300 \0001\200L$\247\1enFl\344\0\216\300,\0\1G\5\3view\340\0002\300\177 \372\0\1 K\0T!"..., 8196, MSG_NOSIGNAL|MSG_MORE, NULL, 0) = 8196

Похоже, они представлены обычными C-кодами.

Я пытался расшифровать их в оболочке printf лайк:

while read line; do printf "%s" "$line"; done < <(cat strace.log | head -n2)

но это не удалось (похоже, это не имеет никакого смысла):

11208 sendto(4, "set 29170397297_-cache-schema 85 0 127240rn257202v0?00022710stdClass247213cid216schema214d37ata25n247215block246216fields24f213bid2425214type 037erial2110not null5216module244167217va37rchar216length6@16t5217defaultr215de2lta@516v16f6 35716r210010215t 207C 30 @ 6216rr n4tatus @ 04213int /760214size 222finy216weight243 ;022300 66region@83405P5custom 27300,171623162421nvisibility340t3475страниц242 20534tex @ 206 2611it 36505240 0377 y10r21ftransl! N2ble% 1ca! a3403Q01 n31vprimary key2416016621vunique@21ts241213tmd243 31020 2vn621616217index 210101214list24524036021 3610266316256416n 164214name 70na3172_ro 25205! $ 0n 3341223016340016A2142213r! 354 @ v222110unsigned5 @ 332036 2130n 213016 l6%16!24116% 2710% @ P516 # 16 $ 21f200l241b @ n24166 M21016&@E4214bod201_53216t41623B\2g1634 303info .07a2550200@q!L56forma201332B/!d241637 y0* y0 225a; 2402012'21van0_ 207 200251613400U = @ U1163 @ 222 2122lob @ On2316) 216expire @ 303420267217create24117 < 250n2031"1770d Y022 30555small240! A320.`2300.240240012402403,21vb S2kpo"3132s246!2202t212241q010...

Есть ли лучший способ разобрать вывод strace команда, чтобы увидеть простые строки переданы recvfrom / sendto?

В идеале можно печатать печатные символы, включая новые строки (\r\n), но обрезанные NULL и другие непечатаемые символы?

1 ответ

Решение

Проблема почему read не работает, потому что оболочка уже экранирует символы, поэтому строка удваивается, поэтому \r\n печатается как rn,

Чтобы игнорировать экранирование символов оболочкой, вы можете использовать read -r которые позволяют обратным слешам экранировать любые символы (поэтому они трактуются буквально). Вот пример:

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

Поскольку это двоичные данные, приведенный выше пример также включает strings Команда для отображения только печатаемых строк.

Strace также поддерживает печать всех строк в шестнадцатеричном формате, когда -x указан, но он будет работать так же.


Вот версия для разбора strace вывод в режиме реального времени:

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)

Дальше больше strings, может быть заменен более конкретным фильтром, используя grep, чтобы получить только то, что находится внутри двойных кавычек:

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

однако это может все еще печатать двоичные форматы.

Чтобы избежать этого, давайте упростим весь процесс, поэтому давайте определим следующий псевдоним форматера:

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"'

где:

  • grep -o '".\+[^"]"' - выберите строку в двойных кавычках с кавычками
  • grep -o '[^"]*[^"]' - выделите текст в двойных кавычках
  • while read -r line - сохранить каждую строку в $line а также do какое-то действие (help read)
  • printf "%b" $line - вывести строку, расширив escape-последовательности обратной косой черты
  • tr "\r\n" "\275\276" - временно заменить \r\n в \275\276
  • tr -d "[:cntrl:]" - удалить все управляющие символы
  • tr "\275\276" "\r\n" - восстановить новые окончания строк

тогда полный пример для отслеживания какой-либо команды (например, php) может выглядеть так:

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

Проверьте аналогичный пример: как просмотреть результаты запущенного процесса в другом сеансе bash? на Unix.SE

Другие вопросы по тегам