Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

How do I implement a wrapper script pstrace in bash that changes the interface of

[sudo] strace -c -p [PID]


[sudo] pstrace -c -p [PROCESS-NAME]

similar to how

killall [PROCESS-NAME]

is used. With completion and everything.

share|improve this question

Deceptively complicated requirements :-)

In two parts, firstly the pstrace wrapper script for strace, this uses pgrep for the name-to-PID operation.


IFS=$' \t\n'

# process the arguments to find "-p procname", only support one instance though
for ((nn=1; nn<=$#; nn++)); do
    if [ "${!nn}" = "-p" ]; then
    elif [ "$prev" = "-p" ]; then
        args+=( "${!nn}" )    # just copy 

if [ -n "$pname" ]; then
    # skip this shell's PID, which pgrep -f will match
    # note the use of exec to avoid picking up a matching subshell too
    # uncomment  && printf for pid/pname list
    while read pp pname; do 
         [ "$pp" != "$$" ] && pids+=($pp) # && printf "%6i %s\n" "$pp" "$pname"
    done < <(exec pgrep -l -f "${pname}")


if [ $npids -eq 0 ]; then
    echo "No PIDs to trace."; exit 2
elif [ $npids -eq 1 ]; then
    args=( "${args[@]}" -p ${pids[0]} )
elif [ $npids -le 32 ]; then
    read -p "$npids PIDS found, enter Y to proceed: " yy
    [ "$yy" != "Y" ] && echo "Cancelled..." && exit 1
    args=( "${args[@]}" ${pids[@]/#/-p } ) 
    echo "Too many PIDs to trace: $npids (max 32)."; exit 2

strace "${args[@]}"

For the second part I'll use bash programmable completion to complete processes by name, put this in your ~/.bash_profile or similar:

# process-name patterns to ignore
PROCIGNORE=( "^\[", "^-bash" )

_c8n_listprocs ()
    local cur prv ignore IFS nn mm

    case "$prv" in
              IFS=$'\n' COMPREPLY=( $(ps axwwo "args") ) IFS=$' \t\n'
              COMPREPLY=(${COMPREPLY[*]// */})  # remove arguments

              ignore="0" # ps header
              for ((nn=1; nn<${#COMPREPLY[*]}; nn++)); do
                  # filter by (partially) typed name in cur
                  # use  " =~ ^$cur " for prefix match, without ^ it's substr match
                  [[ -n "$cur"  &&  ! "${COMPREPLY[$nn]}" =~ $cur ]] && {
                      ignore="$nn $ignore"
                  } || { 
                      # skip names matching PROCIGNORE[]
                      for ((mm=0; mm<${#PROCIGNORE[*]}; mm++)); do
                          [[ "${COMPREPLY[$nn]}" =~ ${PROCIGNORE[$mm]} ]] && 
                              ignore="$nn $ignore"
              # remove unwanted, in reverse index order
              for nn in $ignore; do unset COMPREPLY[$nn]; done

        *)    COMPREPLY=()
complete -F _c8n_listprocs pstrace

Tested & used on linux with bash-3.x and bash-4.x. ps options may need tweaking on non-Linux platforms, should also support truss with a one-line change.

Limitations include:

  • no correct escaping of kernel-thread like process [names], this will cause pgrep to (likely) not do what you want
  • mismatched of processes with space in the name ("args" is used instead of "comm" so that /paths can be used , where available)
share|improve this answer

Thy this:

ps auxw | grep [PROCESS-NAME] | awk '{print"-p " $2}' | xargs strace
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.