Взаимодействие с именем процесса вместо PID

2768
Nordlöw

Как реализовать скрипт оболочки pstraceв bash, который изменяет интерфейс

[sudo] strace -c -p [PID] 

в

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

похоже на то, как

killall [PROCESS-NAME] 

используется. С завершением и всем.

4

2 ответа на вопрос

2
ymn

Твой это:

ps auxw | grep [PROCESS-NAME] | awk '' | xargs strace 
1
mr.spuratic

Deceptively complicated requirements :-)

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

#!/bin/bash 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 pname="${!nn}" else args+=( "${!nn}" ) # just copy fi prev="${!nn}" done pids=() 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 "$") fi npids=${#pids[*]} if [ $npids -eq 0 ]; then echo "No PIDs to trace."; exit 2 elif [ $npids -eq 1 ]; then args=( "$" -p $ ) elif [ $npids -le 32 ]; then read -p "$npids PIDS found, enter Y to proceed: " yy [ "$yy" != "Y" ] && echo "Cancelled..." && exit 1 args=( "$" $ ) else echo "Too many PIDs to trace: $npids (max 32)."; exit 2 fi strace "$" 

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 prv=$ cur=$ case "$prv" in '-p') IFS=$'\n' COMPREPLY=( $(ps axwwo "args") ) IFS=$' \t\n' 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" && ! "$" =~ $cur ]] && { ignore="$nn $ignore" } || { # skip names matching PROCIGNORE[] for ((mm=0; mm<${#PROCIGNORE[*]}; mm++)); do [[ "$" =~ $ ]] && ignore="$nn $ignore" done } done # remove unwanted, in reverse index order for nn in $ignore; do unset COMPREPLY[$nn]; done ;; *) COMPREPLY=() ;; esac } 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)