To summarize before we begin: use
strace -f to generate a nice graph of all the programs run by a given command.
I have a CLI tool that’s meant to wrap several other tools to make using them together more convenient. It does this by offering a couple commands, each of which encapsulates several other commands. E.g. the full build process is like this:
- Run ‘language-specific-build-tool’ in
dir0with options x, y, and z
- Take the output of the first step and use that with ‘second-lang-specific-build-tool’ in
dir1with options foo, bar and baz
- Etc, etc
Theres a tool for doing all this via more conventient commands since it’s a relatively widespread workflow. Ostensibly, this is awesome, but debuging such a monolithic build process can be painful. In such a case, it would be awesome if we could break down what the build tool is doing to debug the component steps.
Briefly, you use the program
strace -f to dump all the syscalls made by a program, and all the syscalls of it’s children, recursively. Then, you feed the output of that program into a perl script called
strace-graph to create a nice graph of what programs spawned what processes with which arguments.
To dump to a file, use the
-o "OUTPUT_LOG_PATH" flag with
strace -f to dump to a file.
Also, it seems
strace-graph was written to parse the output of an old
strace that outputs a couple fewer fields than current
strace does. To remove them, I use bash process substitution with sed to remove the troublesome lines:
./strace-graph <(sed '/---/d' process_strace_output.log | sed '/exited with/d')
All together, here are the commands I use:
strace -f -s 100 -o "OUTPUT_LOG_PATH" program_to_run_and_analyze ./strace-graph <(sed '/---/d' "OUTPUT_LOG_PATH" | sed '/exited with/d')
The resulting output looks something like this:
ember cordova:build --platform=android node /home/leland/.nvm/versions/node/v0.12.7/bin/ember cordova:build --platform=android +-- (anon) +-- (anon) +-- sh(/bin/sh) -c watchman version +-- sh(/bin/sh) -c ember build --environment development | `-- ember build --environment development | node /home/leland/.nvm/versions/node/v0.12.7/bin/ember build --environment development | +-- (anon) | `-- sh(/bin/sh) -c watchman version `-- sh(/bin/sh) -c cordova build android `-- cordova build android node /home/leland/.nvm/versions/node/v0.12.7/bin/cordova build android `-- build(/home/leland/example_project/cordova/platforms/android/cordova/build) node /home/leland/example_project/cordova/platforms/android/cordova/build +-- sh(/bin/sh) -c java -version | `-- java -version | `-- (anon) | +-- (anon) | +-- (anon) | +-- (anon) | `-- ... +-- sh(/bin/sh) -c android list targets --compact | `-- android list targets --compact | +-- (anon) | +-- dirname /home/leland/Android/Sdk//tools/android | +-- (anon) | +-- basename /home/leland/Android/Sdk//tools/android | +-- dirname /home/leland/Android/Sdk/tools | +-- uname | +-- uname | +-- java -jar /home/leland/Android/Sdk/tools/lib/archquery.jar java.ext.dirs | | `-- (anon) | | +-- (anon) | | +-- (anon) | | +-- (anon) | | `-- ... | +-- java -jar /home/leland/Android/Sdk/tools/lib/archquery.jar | | `-- (anon) | | +-- (anon) | | +-- (anon) | | +-- (anon) | | `-- ... | java -Xmx256M -Dcom.android.sdkmanager.toolsdir=/home/le... | `-- (anon) | +-- (anon) | +-- (anon) | +-- (anon) | `-- ... +-- sh(/bin/sh) -c javac -version | `-- javac -version | `-- (anon) | +-- (anon) | +-- (anon) | +-- (anon) | `-- ... `-- gradlew(/home/leland/example_project/cordova/platforms/android/gra... bash /home/leland/example_project/cordova/platforms/android/gradle... +-- basename /home/leland/example_project/cordova/platforms/android/gradlew +-- uname +-- (anon) +-- dirname /home/leland/example_project/cordova/platforms/android/gradlew +-- (anon) +-- (anon) java(/usr/lib/jvm/java-7-openjdk-amd64/bin/java) -Dorg.gradle.app... `-- (anon) +-- (anon) +-- (anon) +-- (anon) +-- (anon) `-- ...