strace

Latest response

Hi,
Using strace on a running program,how can i see that this program use system call?

Responses

Hi Marius Tanislav,

Please see if this Red Hat solution helps.

Regards,
RJ

That's what I was going to say too. That knowledgebase page reflects the best practice we've found using strace over many years.

One addition I can think, if the process you're tracing creates a lot of sub-processes then you could use -ff which puts each sub-process into its own file.

I find that's handy for tracing very big busy things like the Java Virtual Machine.

i use this script y.sh

#!/bin/sh
while true
do
        :
done

from https://thevivekpandey.github.io/posts/2017-09-25-linux-system-calls.html i see that read is systemcall.

i used

strace -fvttTyy -s 4096 -o /tmp/strace.txt ./y.sh

i see there are

3847  02:23:41.052518 getrlimit(RLIMIT_NPROC, {rlim_cur=3795, rlim_max=3795}) = 0 <0.000012>
3847  02:23:41.052851 rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0 <0.000012>
3847  02:23:41.052912 open("./y.sh", O_RDONLY) = 3</root/y.sh> <0.000016>
3847  02:23:41.052984 ioctl(3</root/y.sh>, TCGETS, 0x7ffc8331bc70) = -1 ENOTTY (Inappropriate ioctl for device) <0.000013>
3847  02:23:41.053084 lseek(3</root/y.sh>, 0, SEEK_CUR) = 0 <0.000012>
3847  02:23:41.053145 read(3</root/y.sh>, "#!/bin/sh\nwhile true\ndo\n\t:\t\ndone\n", 80) = 33 <0.000016>
3847  02:23:41.053203 lseek(3</root/y.sh>, 0, SEEK_SET) = 0 <0.000011>
3847  02:23:41.053256 getrlimit(RLIMIT_NOFILE, {rlim_cur=1024, rlim_max=4*1024}) = 0 <0.000011>
3847  02:23:41.053305 fcntl(255, F_GETFD) = -1 EBADF (Bad file descriptor) <0.000012>
3847  02:23:41.053365 dup2(3</root/y.sh>, 255) = 255</root/y.sh> <0.000014>
3847  02:23:41.053432 close(3</root/y.sh>) = 0 <0.000012>
3847  02:23:41.053481 fcntl(255</root/y.sh>, F_SETFD, FD_CLOEXEC) = 0 <0.000012>
3847  02:23:41.053537 fcntl(255</root/y.sh>, F_GETFL) = 0x8000 (flags O_RDONLY|O_LARGEFILE) <0.000012>
3847  02:23:41.053632 fstat(255</root/y.sh>, {st_dev=makedev(253, 0), st_ino=34833645, st_mode=S_IFREG|0755, st_nlink=1, st_u
id=0, st_gid=0, st_blksize=4096, st_blocks=8, st_size=33, st_atime=1630653677 /* 2021-09-03T03:21:17.452080997-0400 */, st_at
ime_nsec=452080997, st_mtime=1630653675 /* 2021-09-03T03:21:15.990017913-0400 */, st_mtime_nsec=990017913, st_ctime=163065367
5 /* 2021-09-03T03:21:15.992017999-0400 */, st_ctime_nsec=992017999}) = 0 <0.000012>
3847  02:23:41.053708 lseek(255</root/y.sh>, 0, SEEK_CUR) = 0 <0.000011>
3847  02:23:41.053767 rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0 <0.000011>
3847  02:23:41.053826 read(255</root/y.sh>, "#!/bin/sh\nwhile true\ndo\n\t:\t\ndone\n", 33) = 33 <0.000013>
3847  02:23:41.053892 rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0 <0.000011>
3847  02:23:52.881259 --- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---
3847  02:23:52.881867 +++ killed by SIGINT +++

how to understand the above? at 3847 is red the y.sh script.then no system call is used?

You're seeing the system calls that /bin/sh performs as it sets up an environment to run the script. It apparently opens the script, swaps the script file descriptor to number 255 which leaves the next available FD as 3, then reads the contents of the script and runs it.

The script itself doesn't perform any action which requires a system call, so no further action is observed in strace until you end the script with Ctrl+c, which generates a signal to interrupt the sh process and end it.

Just because there is nothing printed in strace doesn't mean nothing is happening. Your script is performing its logic in userspace (your infinite loop) which doesn't require any system call, so nothing is observed in strace.

For example, if you make your script do something which needs a syscall:

#!/bin/sh
for I in 1 2 3; do
    echo "$I"
done

Then we do see activity in strace:

write(1</dev/pts/4<char 136:4>>, "1\n", 2) = 2 <0.000036>
write(1</dev/pts/4<char 136:4>>, "2\n", 2) = 2 <0.000012>
write(1</dev/pts/4<char 136:4>>, "3\n", 2) = 2 <0.000011>

What's your overall aim here?

If you're just learning system calls, you'll probably find it easier to write your own minimal code in C and strace your own program so you understand what's supposed to happen.

As you have seen, pre-existing things like /bin/sh perform lots of actions which are not obvious and might even be the result of actions performed by libraries.

Even a basic hello world program is quite busy as it links in the GNU C Library to use printf, but you can usually ignore all that stuff until your actual program logic starts.