Как я могу получить dtrace для запуска команды трассировки с некорневыми привилегиями?
OS X не хватает linux strace
, но это dtrace
который должен быть намного лучше.
однако я упускаю возможность выполнять простую трассировку по отдельным командам. Например, на linux я могу написать strace -f gcc hello.c
чтобы caputre все системные вызовы, который дает мне список все имена файлов, необходимые компилятору для компиляции моей программы (отлично memoize скрипт построен на этом трюке)
я хочу, чтобы порт memoize на мак, так что мне нужен какой-то strace
. На самом деле мне нужен список файлов gcc
читает и пишет, так что мне нужно больше truss
. Конечно, я могу сказать dtruss -f gcc hello.c
и получить несколько ту же функциональность, но тогда компилятор запускается с корневыми привилегиями, что, очевидно, нежелательно (помимо огромного риска безопасности, одна проблема заключается в том, что a.out
файл теперь принадлежит root :-)
затем я попробовал dtruss -f sudo -u myusername gcc hello.c
, но это чувствует себя немного неправильно, и не работает в любом случае (я не получаю за все это время, не знаю почему)
вся эта длинная история пытается мотивировать мой первоначальный вопрос:как сделать dtrace
чтобы запустить мою команду с обычными правами пользователя, так же, как strace
делает в linux ?
Edit: кажется, что я не единственный, кому интересно, как это сделать: вопрос #1204256 почти такой же, как у меня (и имеет тот же неоптимальный ответ sudo :-)
8 ответов:
Не ответ на ваш вопрос, но что-то знать. OpenSolaris решил эту проблему (частично) с помощью "привилегий" - см. на этой странице. Даже в OpenSolaris было бы невозможно разрешить пользователю без каких-либо дополнительных привилегий выполнять свой собственный процесс. Причина в том, как работает dtrace-он позволяет зонды на ядра. Таким образом, позволяя непривилегированному пользователю зондировать ядро, пользователь может делать много нежелательных вещей, например, нюхать passwd другого пользователя включение зондов в драйвере клавиатуры!
самый простой способ-использовать sudo:
sudo dtruss -f sudo -u $USER whoami
другим решением было бы сначала запустить отладчик и отслеживать новые конкретные процессы. Е. Г.
sudo dtruss -fn whoami
затем в другом терминале просто запустите:
whoami
просто.
более сложные аргументы вы можете найти в руководстве:
man dtruss
в качестве альтернативы вы можете прикрепить dtruss к запущенному пользовательскому процессу, например Mac:
sudo dtruss -fp PID
или аналогичный на Linux / Unix с помощью strace:
sudo strace -fp PID
еще один хитрый трюк может заключаться в том, чтобы выполнить команду и сразу после этого подключиться к процессу. Вот несколько примеров:
sudo true; (./Pages &); sudo dtruss -fp `pgrep -n -x Pages` sudo true; (sleep 1 &); sudo dtruss -fp `pgrep -n -x sleep` sudo true; (tail -f /var/log/system.log &); sudo dtruss -fp `pgrep -n -x tail`
Примечание:
первый sudo предназначен только для кэширования пароля при первом запуске,
этот трюк не работает для быстрых командных строк, таких как
ls, date
а это занимает некоторое время, пока отладчик не присоединится к процессу,вы должны ввести свою команду в двух местах,
вы можете игнорировать
&
чтобы запустить процесс в фоновом режиме, если он уже делает это,после окончания отладки, вам придется вручную убить фоновый процесс (например,
killall -v tail
)
Я не знаю, можете ли вы заставить dtruss быть таким же неинвазивным, как strace.
вариант "sudo [to root] dtruss sudo [back to nonroot] cmd", который, кажется, работает лучше в некоторых быстрых тестах для меня:
sudo dtruss -f su -l `whoami` cd `pwd` && cmd....
внешний sudo, конечно, так dtruss работает как root.
внутренний su возвращается ко мне, и с-l он воссоздает окружающую среду должным образом, и в этот момент нам нужно вернуться к тому, с чего мы начали.
Я думаю, что "su-L user" лучше чем "пользователь sudo-u", если вы хотите, чтобы среда была тем, что обычно получает этот пользователь. Это будет их среда входа в систему; я не знаю, есть ли хороший способ позволить среде наследовать через два изменения пользователя.
в вашем вопросе одна дополнительная жалоба, которую вы имели о обходном пути "sudo dtruss sudo", кроме уродства, заключалась в том, что "я не получаю файл.out все это время, не знаю, почему". Я тоже не знаю почему, но в моем маленьком тестовом сценарии " sudo вариант " dtruss sudo "также не удалось записать в тестовый выходной файл, а вариант" sudo dtruss su " выше создал выходной файл.
похоже, что OS X не поддерживает использование dtrace для репликации всех функций strace, которые вам нужны. Тем не менее, я бы предложил попробовать создать оболочку вокруг подходящих системных вызовов. Это выглядит как DYLD_INSERT_LIBRARIES это переменная окружения, которую вы хотите немного взломать. Это в основном то же самое, что
LD_PRELOAD
для Linux.гораздо более простой способ выполнения переопределений библиотечных функций-это использование Переменная окружения DYLD_INSERT_LIBRARIES (аналогично LD_PRELOAD на Linux.) Концепция проста: во время загрузки динамический линкер (dyld) загружает любые динамические библиотеки, указанные в DYLD_INSERT_LIBRARIES перед любыми библиотеками исполняемый файл должен быть загружен. Название функции такой же, как и в библиотечной функции, он заменит любые вызовы оригинал.
исходная функция также загружается и может быть получена с помощью функция dlsym(RTLD_NEXT, "имя_функции"); функция. Это позволяет простой способ упаковки существующие библиотечные функции.
по словам пример by Тома Робинсона возможно, Вам потребуется установить
DYLD_FORCE_FLAT_NAMESPACE=1
тоже.копия исходного примера (
lib_overrides.c
), который переопределяет толькоfopen
:#include <stdio.h> #include <unistd.h> #include <dlfcn.h> // for caching the original fopen implementation FILE * (*original_fopen) (const char *, const char *) = NULL; // our fopen override implmentation FILE * fopen(const char * filename, const char * mode) { // if we haven’t already, retrieve the original fopen implementation if (!original_fopen) original_fopen = dlsym(RTLD_NEXT, "fopen"); // do our own processing; in this case just print the parameters printf("== fopen: {%s,%s} ==\n", filename, mode); // call the original fopen with the same arugments FILE* f = original_fopen(filename, mode); // return the result return f; }
использование:
$ gcc -Wall -o lib_overrides.dylib -dynamiclib lib_overrides.c $ DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=lib_overrides.dylib command-to-test
отказ от ответственности: это происходит от @kenorb в ответ. Однако у него есть некоторые преимущества: PID более специфичен, чем execname. И мы можем заставить недолговечный процесс ждать DTrace, прежде чем он начнется.
это немного расовая обусловленность, но...
допустим, мы хотим проследить
cat /etc/hosts
:sudo true && \ (sleep 1; cat /etc/hosts) &; \ sudo dtrace -n 'syscall:::entry /pid == / {@[probefunc] = count();}' $!; \ kill $!
мы используем:
sudo true
чтобы убедиться, что мы очищаем запрос пароля sudo перед запуском чего-либо чувствительный ко времени.мы начинаем фоновый процесс ("подождите 1 сек, а затем сделать что-то интересное"). Тем временем, мы начинаем DTrace. Мы захватили PID фонового процесса в
$!
, Так что мы можем передать, что для потребителя в качестве аргументов.The
kill $!
работает после закрытия DTrace. Это не нужно для нашегоcat
пример (процесс закрывается сам по себе), но это помогает нам закончить длительные фоновые процессы, такие какping
. Передает-p $!
для DTrace является предпочтительным способом сделать это, но на macOS, по-видимому, требуется исполняемый файл с подписью кода.
другое, что вы можете сделать, это запустить команду в отдельной оболочке и вынюхать эту оболочку. Смотрите мой ответ.
Я не знаю, как запустить то, что вы хотите, как обычный пользователь, так как кажется, что dtruss, который использует dtrace, требует привилегий su.
однако, я считаю, что команда, которую вы искали вместо
dtruss -f sudo -u myusername gcc hello.c
и
sudo dtruss -f gcc hello.c
после ввода пароля, dtruss будет работать dtrace будет sudo привилегии, и вы получите трассировку, а также файл.out.
Извините, я не мог быть дальше помощь.
Извините, я не могу помочь! Я бы набрал bash$
d program under test
чтобы безопасно запустить dtruss в отдельном корневом окне, но кажется, что MacOSX SIP или что-то еще теперь калечитdtruss -p
иopensnoop -p
таким же тупым способом "все или ничего", как старый корень Un*X. Таким образом, этот скрипт больше не работает:d () { case "$*" in [0-9] | [0-9][0-9] | [0-9][0-9][0-9] | [0-9][0-9][0-9][0-9] | [0-9][0-9][0-9][0-9][0-9]) dtruss -f -p "$*" ;; *) bash -c 'echo -en "\t <<< press return in this window to run after launching trace in root window like this >>> \t # d $$" >/dev/tty; (read -u3 3</dev/tty); exec "" "$@"' "$@" ;; esac }
несколько десятилетий назад у нас были компьютеры компании Apple для толкания данных и джинсы levi'S для вождения трактора - теперь идеократии царит (пух-собирать колоски, заткни мне рот ...) оба мода ответственностью.