2

I'm trying to call a self-defined function funk_a in strace but it doesn't seem to find it. I confirmed that funk_a can be called by itself. I appreciate any opinions.

$ source ./strace_sample.sh 
$ funk_a
Earth, Wind, Fire and Water
$ funk_b
Get on up
strace: Can't stat 'funk_a': No such file or directory

$ dpkg -p strace|grep Vers
Version: 4.8-1ubuntu5
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 14.04.5 LTS
Release:        14.04
Codename:       trusty

strace_sample.sh

#!/bin/bash

function funk_a {
  echo "Earth, Wind, Fire and Water"
}

function funk_b {
  echo "Get on up"
  strace -o trace_output.txt -c -Ttt funk_a
}

Thank you.

IsaacS
  • 175

2 Answers2

7

strace can only strace executable files.

funk_a is a function, a programming construct of the shell, not something you can execute.

The only thing strace could strace would be a new shell that evalutes the body of that function like:

strace -o trace_output.txt -Ttt bash -c "$(typeset -f funk_a); funk_a"

(I removed -c as it makes no sense with -Ttt).

But you'll then see all the system called made by bash to load and initialise (and after to clean-up and exit) in addition to that one write system call made by that funk_a function.

Or you could tell strace to trace the pid of the shell while it evaluates the funk_a function:

strace -o trace_output.txt -Ttt -p "$$" &
funk_a
kill "$!"

Though, by the time strace attaches to the PID of the shell, the shell could very well have finished interpreting the function. You could try some synchronisation like

strace -o trace_output.txt  -Ttt -p "$$" &
tail -F trace_output.txt | read # wait for some output in trace_output.txt

funk_a
kill "$!"

But even then depending on timing, trace_output.txt would include some of the system calls used interpret tail|read, or kill could kill strace before it has had the time to write the trace for the echo command to the output file.

A better approach could be to wrap the call to funk_a between two recognisable system calls like

strace -fo >(sed -n '1,\|open("///dev/null|d
                     \|open("/dev///null|q;p' > trace_output.txt
  ) -Ttt -p "$$" &
sleep 1 # give enough time for strace to start
exec 3<  ///dev/null # start signal
funk_a
exec 3< /dev///null # end signal
1

Figured out by myself after finding out in this thread that strace can only call an executable.

Changing my example above as follows worked.

util.sh

#!/bin/bash
echo "Earth, Wind, Fire and Water"

strace_sample.sh

#!/bin/bash

function funk_b {
  echo "Get on up"
  #strace -o funk_a.out -c -Ttt funk_a
  strace -o util.out -c -Ttt ./util.sh
}

Result

$ funk_b
Get on up
Earth, Wind, Fire and Water
$ more util.out 
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
  0.00    0.000000           0         7           read
  0.00    0.000000           0         1           write
  0.00    0.000000           0        27        18 open
:
IsaacS
  • 175