Ni awọn ọna ṣiṣe bii Unix, ibaraẹnisọrọ eto pẹlu agbaye ita ati ẹrọ ṣiṣe waye nipasẹ eto iṣẹ kekere kan - awọn ipe eto. Eyi tumọ si pe fun awọn idi n ṣatunṣe aṣiṣe o le wulo lati ṣe amí lori awọn ipe eto ni ṣiṣe nipasẹ awọn ilana.
IwUlO kan ṣe iranlọwọ fun ọ lati ṣe atẹle “igbesi aye timotimo” ti awọn eto lori Lainos strace, eyiti o jẹ koko-ọrọ ti nkan yii. Awọn apẹẹrẹ ti lilo awọn ohun elo amí wa pẹlu itan kukuru kan strace ati apejuwe ti awọn oniru ti iru awọn eto.
Ni wiwo akọkọ laarin awọn eto ati ekuro OS ni Unix jẹ awọn ipe eto. awọn ipe eto, syscals), ibaraenisepo ti awọn eto pẹlu ita ita waye nipasẹ wọn nikan.
Ṣugbọn ni ẹya akọkọ ti gbangba ti Unix (Ẹya 6 Unix, 1975) ko si awọn ọna irọrun lati tọpa ihuwasi ti awọn ilana olumulo. Lati yanju ọran yii, Bell Labs yoo ṣe imudojuiwọn si ẹya atẹle (Ẹya 7 Unix, 1979) dabaa ipe eto titun kan - ptrace.
ptrace ti ni idagbasoke ni akọkọ fun awọn olutọpa ibaraenisepo, ṣugbọn ni opin awọn ọdun 80 (ni akoko ti iṣowo Itusilẹ eto V 4) lori ipilẹ yii, awọn olutọpa ti o ni idojukọ dín — awọn olutọpa ipe eto — han ati di lilo pupọ.
Ni igba akọkọ ti ẹya kanna ti strace ni a tẹjade nipasẹ Paul Cronenburg lori atokọ ifiweranṣẹ comp.sources.sun ni ọdun 1992 bi yiyan si ohun elo pipade trace lati Sun. Mejeeji ẹda oniye ati atilẹba jẹ ipinnu fun SunOS, ṣugbọn nipasẹ ọdun 1994 strace ti gbejade si System V, Solaris ati Lainos olokiki ti o pọ si.
Loni strace ṣe atilẹyin Linux nikan ati dale lori kanna ptrace, poju pẹlu ọpọlọpọ awọn amugbooro.
Modern (ati ki o gidigidi lọwọ) olutọju strace - Dmitry Levin. Ṣeun si i, ohun elo naa gba awọn ẹya ilọsiwaju gẹgẹbi abẹrẹ aṣiṣe sinu awọn ipe eto, atilẹyin fun ọpọlọpọ awọn faaji ati, pataki julọ, mascot. Awọn orisun laigba aṣẹ beere pe yiyan naa ṣubu lori ostrich nitori ifọkanbalẹ laarin ọrọ Russian “ostrich” ati ọrọ Gẹẹsi “strace”.
O tun ṣe pataki pe ipe eto ptrace ati awọn olutọpa ko wa ninu POSIX, laibikita itan-akọọlẹ gigun ati imuse ni Lainos, FreeBSD, OpenBSD ati Unix ibile.
Ẹrọ Strace ni kukuru: Piglet Trace
"O ko nireti lati loye eyi" (Dennis Ritchie, asọye ni Ẹya 6 koodu orisun Unix)
Lati igba ewe, Emi ko le duro awọn apoti dudu: Emi ko ṣere pẹlu awọn nkan isere, ṣugbọn gbiyanju lati ni oye eto wọn (awọn agbalagba lo ọrọ naa "fifọ," ṣugbọn ko gbagbọ awọn ahọn buburu). Boya eyi ni idi ti aṣa aiṣedeede ti Unix akọkọ ati egbe ṣiṣi-orisun igbalode ti sunmọ mi.
Fun awọn idi ti nkan yii, ko bọgbọnmu lati ṣajọ koodu orisun ti strace, eyiti o ti dagba ni awọn ọdun sẹhin. Ṣugbọn ko yẹ ki o jẹ awọn aṣiri ti o fi silẹ fun awọn onkawe. Nitorinaa, lati ṣafihan ipilẹ ti iṣiṣẹ ti iru awọn eto strace, Emi yoo pese koodu fun olutọpa kekere kan - Piglet Trace (ptr). Ko mọ bi o ṣe le ṣe ohunkohun pataki, ṣugbọn ohun akọkọ ni awọn ipe eto ti eto naa - o jade:
Piglet Trace ṣe idanimọ nipa awọn ọgọọgọrun ti awọn ipe eto Linux (wo. tabili) ati ki o ṣiṣẹ nikan lori x86-64 faaji. Eyi to fun awọn idi ẹkọ.
Jẹ ki a wo iṣẹ ti ẹda oniye wa. Ninu ọran ti Lainos, awọn olutọpa ati awọn olutọpa lo, gẹgẹbi a ti sọ loke, ipe eto ptrace. O ṣiṣẹ nipa gbigbe ni ariyanjiyan akọkọ awọn idamọ aṣẹ, eyiti a nilo nikan PTRACE_TRACEME, PTRACE_SYSCALL и PTRACE_GETREGS.
Olutọpa bẹrẹ ni aṣa Unix deede: fork(2) ifilọlẹ ọmọ ilana, eyi ti o ni Tan nlo exec(3) ṣe ifilọlẹ eto ti o wa labẹ ikẹkọ. Awọn arekereke nikan nibi ni ipenija ptrace(PTRACE_TRACEME) diẹ ẹ sii exec: Ilana ọmọ nireti ilana obi lati ṣe atẹle rẹ:
pid_t child_pid = fork();
switch (child_pid) {
case -1:
err(EXIT_FAILURE, "fork");
case 0:
/* Child here */
/* A traced mode has to be enabled. A parent will have to wait(2) for it
* to happen. */
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
/* Replace itself with a program to be run. */
execvp(argv[1], argv + 1);
err(EXIT_FAILURE, "exec");
}
Ilana obi yẹ ki o pe bayi wait(2) ninu ilana ọmọ, iyẹn ni, rii daju pe iyipada si ipo itọpa ti ṣẹlẹ:
/* Parent */
/* First we wait for the child to set the traced mode (see
* ptrace(PTRACE_TRACEME) above) */
if (waitpid(child_pid, NULL, 0) == -1)
err(EXIT_FAILURE, "traceme -> waitpid");
Ni aaye yii, awọn igbaradi ti pari ati pe o le tẹsiwaju taara si awọn ipe eto titele ni lupu ailopin.
Pe ptrace(PTRACE_SYSCALL) onigbọwọ wipe o tele wait obi yoo pari boya ṣaaju ṣiṣe ipe eto tabi lẹsẹkẹsẹ lẹhin ti o pari. Laarin awọn ipe meji o le ṣe awọn iṣe eyikeyi: rọpo ipe pẹlu omiiran miiran, yi awọn ariyanjiyan pada tabi iye ipadabọ.
A kan nilo lati pe aṣẹ naa lẹẹmeji ptrace(PTRACE_GETREGS)lati gba ipo iforukọsilẹ rax ṣaaju ipe (nọmba ipe eto) ati lẹsẹkẹsẹ lẹhin (iye ipadabọ).
Lootọ, iwọnyi:
/* A system call tracing loop, one interation per call. */
for (;;) {
/* A non-portable structure defined for ptrace/GDB/strace usage mostly.
* It allows to conveniently dump and access register state using
* ptrace. */
struct user_regs_struct registers;
/* Enter syscall: continue execution until the next system call
* beginning. Stop right before syscall.
*
* It's possible to change the system call number, system call
* arguments, return value or even avoid executing the system call
* completely. */
if (ptrace(PTRACE_SYSCALL, child_pid, NULL, NULL) == -1)
err(EXIT_FAILURE, "enter_syscall");
if (waitpid(child_pid, NULL, 0) == -1)
err(EXIT_FAILURE, "enter_syscall -> waitpid");
/* According to the x86-64 system call convention on Linux (see man 2
* syscall) the number identifying a syscall should be put into the rax
* general purpose register, with the rest of the arguments residing in
* other general purpose registers (rdi,rsi, rdx, r10, r8, r9). */
if (ptrace(PTRACE_GETREGS, child_pid, NULL, ®isters) == -1)
err(EXIT_FAILURE, "enter_syscall -> getregs");
/* Note how orig_rax is used here. That's because on x86-64 rax is used
* both for executing a syscall, and returning a value from it. To
* differentiate between the cases both rax and orig_rax are updated on
* syscall entry/exit, and only rax is updated on exit. */
print_syscall_enter(registers.orig_rax);
/* Exit syscall: execute of the syscall, and stop on system
* call exit.
*
* More system call tinkering possible: change the return value, record
* time it took to finish the system call, etc. */
if (ptrace(PTRACE_SYSCALL, child_pid, NULL, NULL) == -1)
err(EXIT_FAILURE, "exit_syscall");
if (waitpid(child_pid, NULL, 0) == -1)
err(EXIT_FAILURE, "exit_syscall -> waitpid");
/* Retrieve register state again as we want to inspect system call
* return value. */
if (ptrace(PTRACE_GETREGS, child_pid, NULL, ®isters) == -1) {
/* ESRCH is returned when a child terminates using a syscall and no
* return value is possible, e.g. as a result of exit(2). */
if (errno == ESRCH) {
fprintf(stderr, "nTracee terminatedn");
break;
}
err(EXIT_FAILURE, "exit_syscall -> getregs");
}
/* Done with this system call, let the next iteration handle the next
* one */
print_syscall_exit(registers.rax);
}
Iyẹn ni gbogbo olutọpa. Bayi o mọ ibiti o ti le bẹrẹ ibudo atẹle DTrace lori Linux.
Ipilẹ: nṣiṣẹ a eto nṣiṣẹ strace
Gẹgẹbi ọran lilo akọkọ strace, boya o tọ lati tọka ọna ti o rọrun julọ - ifilọlẹ ohun elo nṣiṣẹ strace.
Ni ibere ki o má ba lọ sinu atokọ ailopin ti awọn ipe ti eto aṣoju, a kọ kere eto ni ayika write:
int main(int argc, char *argv[])
{
char str[] = "write me to stdoutn";
/* write(2) is a simple wrapper around a syscall so it should be easy to
* find in the syscall trace. */
if (sizeof(str) != write(STDOUT_FILENO, str, sizeof(str))){
perror("write");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Jẹ ki a kọ eto naa ki o rii daju pe o ṣiṣẹ:
$ gcc examples/write-simple.c -o write-simple
$ ./write-simple
write me to stdout
Pupọ “ọrọ” ati kii ṣe ẹkọ pupọ. Awọn iṣoro meji wa nibi: iṣẹjade eto ti dapọ pẹlu iṣẹjade strace ati awọn ẹya opo ti awọn ipe eto ti ko ni anfani wa.
O le ya awọn eto ká boṣewa o wu san ati strace o wu aṣiṣe nipa lilo awọn -o yipada, eyi ti o àtúnjúwe awọn akojọ ti awọn ipe eto si ohun ariyanjiyan faili.
O wa lati koju iṣoro ti awọn ipe “afikun”. Jẹ ki a ro pe a nifẹ si awọn ipe nikan write. Bọtini -e faye gba o lati pato awọn ikosile nipa eyi ti awọn ipe eto yoo wa ni filtered. Aṣayan ipo olokiki julọ ni, nipa ti ara, trace=*, pẹlu eyiti o le fi awọn ipe nikan ti o nifẹ si wa.
Nigbati o ba lo nigbakanna -o и -e a yoo gba:
$ strace -e trace=write -owrite-simple.log ./write-simple
write me to stdout
$ cat write-simple.log
write(1, "write me to stdoutn", 20
) = 20
+++ exited with 0 +++
Nitorinaa, o rii, o rọrun pupọ lati ka.
O tun le yọ awọn ipe eto kuro, fun apẹẹrẹ awọn ti o ni ibatan si ipin iranti ati idasilẹ:
$ strace -e trace=!brk,mmap,mprotect,munmap -owrite-simple.log ./write-simple
write me to stdout
$ cat write-simple.log
execve("./write-simple", ["./write-simple"], 0x7ffe9972a498 /* 69 vars */) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=124066, ...}) = 0
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "177ELF21133>1260342"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=2030544, ...}) = 0
close(3) = 0
arch_prctl(ARCH_SET_FS, 0x7f00f0be74c0) = 0
write(1, "write me to stdoutn", 20) = 20
exit_group(0) = ?
+++ exited with 0 +++
Ṣe akiyesi ami iyanju ti o salọ ninu atokọ ti awọn ipe ti a yọkuro: eyi ni a beere nipasẹ ikarahun aṣẹ. ikarahun).
Ninu ẹya mi ti glibc, ipe eto kan fopin si ilana naa exit_group, kii ṣe aṣa _exit. Eyi ni iṣoro ti ṣiṣẹ pẹlu awọn ipe eto: wiwo pẹlu eyiti olupilẹṣẹ n ṣiṣẹ ko ni ibatan taara si awọn ipe eto. Pẹlupẹlu, o yipada nigbagbogbo da lori imuse ati pẹpẹ.
Awọn ipilẹ: didapọ mọ ilana lori fo
Ni ibẹrẹ, ipe eto ptrace lori eyiti o ti kọ strace, le ṣee lo nikan nigbati o nṣiṣẹ eto ni ipo pataki kan. Opin yii le ti dun ni oye ni awọn ọjọ ti Ẹya 6 Unix. Ni ode oni, eyi ko to: nigbakan o nilo lati ṣe iwadii awọn iṣoro ti eto iṣẹ kan. Apeere aṣoju jẹ ilana ti dina lori mimu tabi sisun. Nitorina igbalode strace le darapọ mọ awọn ilana lori fo.
$ ./write-sleep &
[1] 15329
write me
$ strace -p 15329
strace: Process 15329 attached
pause(
^Cstrace: Process 15329 detached
<detached ...>
Eto dina nipasẹ ipe pause. Jẹ ki a wo bi o ṣe ṣe si awọn ifihan agbara:
$ strace -o write-sleep.log -p 15329 &
strace: Process 15329 attached
$
$ kill -CONT 15329
$ cat write-sleep.log
pause() = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGCONT {si_signo=SIGCONT, si_code=SI_USER, si_pid=14989, si_uid=1001} ---
pause(
$
$ kill -TERM 15329
$ cat write-sleep.log
pause() = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGCONT {si_signo=SIGCONT, si_code=SI_USER, si_pid=14989, si_uid=1001} ---
pause() = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=14989, si_uid=1001} ---
+++ killed by SIGTERM +++
A ṣe ifilọlẹ eto tio tutunini ati darapọ mọ pẹlu lilo strace. Awọn nkan meji di mimọ: ipe eto idaduro foju awọn ifihan agbara laisi awọn oluṣakoso ati, ni iyanilenu, awọn atẹle strace kii ṣe awọn ipe eto nikan, ṣugbọn awọn ifihan agbara ti nwọle.
Apeere: Ipasẹ Awọn ilana Ọmọ
Ṣiṣẹ pẹlu awọn ilana nipasẹ ipe kan fork - ipilẹ gbogbo Unixes. Jẹ ki a wo bii strace ṣe n ṣiṣẹ pẹlu igi ilana nipa lilo apẹẹrẹ ti “ibisi” ti o rọrun. eto naa:
int main(int argc, char *argv[])
{
pid_t parent_pid = getpid();
pid_t child_pid = fork();
if (child_pid == 0) {
/* A child is born! */
child_pid = getpid();
/* In the end of the day printf is just a call to write(2). */
printf("child (self=%d)n", child_pid);
exit(EXIT_SUCCESS);
}
printf("parent (self=%d, child=%d)n", parent_pid, child_pid);
wait(NULL);
exit(EXIT_SUCCESS);
}
Asia ṣe iranlọwọ fun ọ lati tọpa gbogbo igi ilana naa -f, eyiti strace diigi eto awọn ipe ni ọmọ lakọkọ. Eyi ṣe afikun si laini iṣẹjade kọọkan pid ilana ti o mu ki eto jade:
Nipa ọna, kini ipe eto ti a lo lati ṣẹda ilana tuntun kan?
Apeere: Awọn ọna faili dipo awọn ọwọ
Mọ awọn apejuwe faili jẹ iwulo nitõtọ, ṣugbọn awọn orukọ ti awọn faili kan pato ti eto n wọle si le tun wa ni ọwọ.
Nigbamii ti o wa eto naa kọ ila si faili igba diẹ:
void do_write(int out_fd)
{
char str[] = "write me to a filen";
if (sizeof(str) != write(out_fd, str, sizeof(str))){
perror("write");
exit(EXIT_FAILURE);
}
}
int main(int argc, char *argv[])
{
char tmp_filename_template[] = "/tmp/output_fileXXXXXX";
int out_fd = mkstemp(tmp_filename_template);
if (out_fd == -1) {
perror("mkstemp");
exit(EXIT_FAILURE);
}
do_write(out_fd);
return EXIT_SUCCESS;
}
Lakoko ipe deede strace yoo ṣe afihan iye nọmba onitumọ ti o kọja si ipe eto naa:
$ strace -e trace=write -o write-tmp-file.log ./write-tmp-file
$ cat write-tmp-file.log
write(3, "write me to a filen", 20) = 20
+++ exited with 0 +++
Pẹlu asia -y IwUlO n ṣe afihan ọna si faili eyiti apejuwe ṣe badọgba:
$ strace -y -e trace=write -o write-tmp-file.log ./write-tmp-file
$ cat write-tmp-file.log
write(3</tmp/output_fileCf5MyW>, "write me to a filen", 20) = 20
+++ exited with 0 +++
Apeere: Titele Wiwọle Faili
Ẹya ti o wulo miiran: ṣafihan awọn ipe eto nikan ni nkan ṣe pẹlu faili kan pato. Itele eto naa fi ila kan si faili lainidii ti o kọja bi ariyanjiyan:
void do_write(int out_fd)
{
char str[] = "write me to a filen";
if (sizeof(str) != write(out_fd, str, sizeof(str))){
perror("write");
exit(EXIT_FAILURE);
}
}
int main(int argc, char *argv[])
{
/*
* Path will be provided by the first program argument.
* */
const char *path = argv[1];
/*
* Open an existing file for writing in append mode.
* */
int out_fd = open(path, O_APPEND | O_WRONLY);
if (out_fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
do_write(out_fd);
return EXIT_SUCCESS;
}
Nipa aiyipada strace ṣafihan ọpọlọpọ alaye ti ko wulo. Flag -P pẹlu ariyanjiyan fa strace lati tẹjade awọn ipe nikan si faili ti a sọ pato:
$ strace -y -P/tmp/test_file.log -o write-file.log ./write-file /tmp/test_file.log
$ cat write-file.log
openat(AT_FDCWD, "/tmp/test_file.log", O_WRONLY|O_APPEND) = 3</tmp/test_file.log>
write(3</tmp/test_file.log>, "write me to a filen", 20) = 20
+++ exited with 0 +++
Apeere: Awọn Eto Onitẹpọ
IwUlO strace tun le ṣe iranlọwọ nigbati o ba ṣiṣẹ pẹlu olona-asapo eto. Eto atẹle naa kọwe si iṣelọpọ boṣewa lati awọn ṣiṣan meji:
void *thread(void *arg)
{
(void) arg;
printf("Secondary thread: workingn");
sleep(1);
printf("Secondary thread: donen");
return NULL;
}
int main(int argc, char *argv[])
{
printf("Initial thread: launching a threadn");
pthread_t thr;
if (0 != pthread_create(&thr, NULL, thread, NULL)) {
fprintf(stderr, "Initial thread: failed to create a thread");
exit(EXIT_FAILURE);
}
printf("Initial thread: joining a threadn");
if (0 != pthread_join(thr, NULL)) {
fprintf(stderr, "Initial thread: failed to join a thread");
exit(EXIT_FAILURE);
};
printf("Initial thread: done");
exit(EXIT_SUCCESS);
}
Nipa ti, o gbọdọ ṣe akopọ pẹlu ikini pataki kan si ọna asopọ - asia -pthread:
$ gcc examples/thread-write.c -pthread -o thread-write
$ ./thread-write
/thread-write
Initial thread: launching a thread
Initial thread: joining a thread
Secondary thread: working
Secondary thread: done
Initial thread: done
$
Flag -f, bi ninu ọran ti awọn ilana deede, yoo ṣafikun pid ti ilana naa si ibẹrẹ ti laini kọọkan.
Nipa ti ara, a ko sọrọ nipa idanimọ okun ni ori ti imuse ti boṣewa POSIX Threads, ṣugbọn nipa nọmba ti oluṣeto iṣẹ ṣiṣe ni Linux. Lati oju wiwo igbehin, ko si awọn ilana tabi awọn okun - awọn iṣẹ ṣiṣe wa ti o nilo lati pin laarin awọn ohun kohun ti ẹrọ naa.
Nigbati o ba n ṣiṣẹ ni ọpọlọpọ awọn okun, awọn ipe eto di pupọ:
O jẹ iyanilenu kini awọn aṣiṣe pada gbogbo awọn italaya write, pẹlu ipe ti o farapamọ lẹhin ẹru. O jẹ oye nikan lati da aṣiṣe pada fun akọkọ ti awọn ipe:
$ strace -e trace=write -e inject=write:error=EBADF:when=1 -owrite-twice.log ./write-twice
write: Bad file descriptor
$ cat write-twice.log
write(1, "write me 1n", 12) = -1 EBADF (Bad file descriptor) (INJECTED)
write(3, "write: Bad file descriptorn", 27) = 27
+++ exited with 1 +++
Tabi keji:
$ strace -e trace=write -e inject=write:error=EBADF:when=2 -owrite-twice.log ./write-twice
write me 1
write: Bad file descriptor
$ cat write-twice.log
write(1, "write me 1n", 12) = 12
write(1, "write me 2n", 12) = -1 EBADF (Bad file descriptor) (INJECTED)
write(3, "write: Bad file descriptorn", 27) = 27
+++ exited with 1 +++
Ko ṣe pataki lati pato iru aṣiṣe:
$ strace -e trace=write -e fault=write:when=1 -owrite-twice.log ./write-twice
$ cat write-twice.log
write(1, "write me 1n", 12) = -1 ENOSYS (Function not implemented) (INJECTED)
write(3, "write: Function not implementedn", 32) = 32
+++ exited with 1 +++
Ni apapo pẹlu awọn asia miiran, o le "fifọ" wiwọle si faili kan pato. Apeere:
$ strace -y -P/tmp/test_file.log -e inject=file:error=ENOENT -o write-file.log ./write-file /tmp/test_file.log
open: No such file or directory
$ cat write-file.log
openat(AT_FDCWD, "/tmp/test_file.log", O_WRONLY|O_APPEND) = -1 ENOENT (No such file or directory) (INJECTED)
+++ exited with 1 +++
Ni afikun si abẹrẹ aṣiṣe, le ṣafihan awọn idaduro nigba ṣiṣe awọn ipe tabi gbigba awọn ifihan agbara.
Lẹhin Ọrọ
IwUlO strace - ohun elo ti o rọrun ati igbẹkẹle. Ṣugbọn ni afikun si awọn ipe eto, awọn ẹya miiran ti iṣẹ ti awọn eto ati ẹrọ ṣiṣe le jẹ yokokoro. Fun apẹẹrẹ, o le tọpa awọn ipe si awọn ile-ikawe ti o ni asopọ ni agbara. ltrace, wọn le wo iṣẹ ti ẹrọ ṣiṣe SystemTap и fifọ, ati ki o faye gba o lati jinna iwadi iṣẹ eto lofinda. Sibẹsibẹ, o jẹ strace - akọkọ ila ti olugbeja ni irú ti awọn iṣoro pẹlu ara mi ati awọn miiran eniyan eto, ati ki o Mo lo o ni o kere kan tọkọtaya ti igba kan ọsẹ.
Ni kukuru, ti o ba nifẹ Unix, ka man 1 strace ati ki o lero ọfẹ lati wo awọn eto rẹ!