Le risposte alle domande sul MacLe domande sul Mac

pssearch - v. 1.3

Main topics: ResourcesMacDownload

Argomenti: UtilityOpensourceTerminaleMac OS 32 bitMac OS 64bit

Author: Marco Balestra

Digging with ps looking for a process isn’t that pleasure.

Of course we can grep, but it’s still hard to read values without headings, and determine launch hierarchy.

On some linux distros there is the pstree command, I tried to do something similar for this pssearch.

This utility is also useful to determine which process is using a file or a folder, e.g. preventing its deletion.

Syntax

pssearch requires one argument:

  • pssearch path-to-file-or-folder
  • pssearch pid-number
  • pssearch case-insensitive-part-of-command

Please note:

  • When the argument is a path to an existing file or folder then will be reported the process (if any) that is using the file or the folder.
  • When the argument only contains numbers it’s assumed to be a PID number.
  • case-insensitive-part-of-command is used inside a regex case insensitive match, it can actually be a simple regex - e.g.: “chrome.+content”
    Therefore if you want to use verbatim for special characters (like .+*?()[]$\) prexif them with double backslash - e.g.: + => \\+, \ => \\\\
  • pssearch accepts one and only one argument.
    Should such argument contain whitespaces, wrap it with quotes or quote whitespaces with \.
    E.g.: pssearch "google chrome", pssearch google\ chrome

Output

% pssearch pssearch Path: /Users/marco/Documents/dev/pssearch/pssearch `--> In use by PID 21877 [PID:1] [USER:root] [TIME:12:52.48] [STAT:Ss] /sbin/launchd `--> [PID:21877] [USER:marco] [TIME:2:28.12] [STAT:S] /Applications/BBEdit.app/Contents/MacOS/BBEdit % pssearch chrome [PID:1] [USER:root] [TIME:0:34.36] [STAT:Ss] /sbin/launchd `--> [PID:515] [USER:marco] [TIME:0:23.62] [STAT:S] /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [PID:1] [USER:root] [TIME:0:34.36] [STAT:Ss] /sbin/launchd `--> [PID:515] [USER:marco] [TIME:0:23.62] [STAT:S] /Applications/Google Chrome.app/Contents/MacOS/Google Chrome `--> [PID:758] [USER:marco] [TIME:0:04.92] [STAT:S] /Applications/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Versions/117.0.5938.149/Helpers/Google Chrome Helper (Renderer).app/Contents/MacOS/Google Chrome Helper (Renderer) --type=renderer --disable-nacl --origin-trial-disabled-features=WebGPU --lang=en-GB --num-raster-threads=4 --enable-zero-copy --enable-gpu-memory-buffer-compositor-resources --enable-main-frame-before-activation --renderer-client-id=12 --time-ticks-at-unix-epoch=-1696577818407481 --launch-time-ticks=74899392 --shared-files --field-trial-handle=1718379636,r,658519363837203859,834477175066415890,262144 --seatbelt-client=89 [PID:1] [USER:root] [TIME:0:34.36] [STAT:Ss] /sbin/launchd `--> [PID:515] [USER:marco] [TIME:0:23.62] [STAT:S] /Applications/Google Chrome.app/Contents/MacOS/Google Chrome `--> [PID:6100] [USER:marco] [TIME:0:00.28] [STAT:S] /Applications/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Versions/117.0.5938.149/Helpers/Google Chrome Helper (Renderer).app/Contents/MacOS/Google Chrome Helper (Renderer) --type=renderer --disable-nacl --origin-trial-disabled-features=WebGPU --lang=en-GB --num-raster-threads=4 --enable-zero-copy --enable-gpu-memory-buffer-compositor-resources --enable-main-frame-before-activation --renderer-client-id=282 --time-ticks-at-unix-epoch=-1696577818407481 --launch-time-ticks=6326131680 --shared-files --field-trial-handle=1718379636,r,658519363837203859,834477175066415890,262144 --seatbelt-client=143 […]
.zip

Requirements

This utility isn’t limited to Mac, it can be used on wathever *nix operating system  with ps and perl (roughly whatever *nix).

In addition:

  • fuser command, if available, is used to convert the full path of a file into the PID of the process that is using it.
  • perl Cwd module if used to convert local path to absolute paths for fuser.
    If the module is missing you can still use absolute paths.

Install

Download the attached script, unzip it.

Then cd to the expanded folder, and:

sudo cp -p pssearch /usr/local/bin

Source

#!/usr/bin/perl # v. 1.3 # © 2023 faqintosh.com my $arg = shift(@ARGV) || ""; if ( $arg eq "" ) { die <<'ENDOFHELP'; Syntax: pssearch <argument> Argument can be: - a path If argument is a path to an existing file or folder then whateve PID locking the resource (if any) will be reported. - a number Report for such PID - a string Running processes commands will be filtered case insensitive for containing the string - a regex As above, in the string basic regex interpolation is supported. Regex, not wildcards: use "." (not "?") or ".+" (not "*") Only one argument is supported. Should the argument contain whitespaces wrap it within "..." ENDOFHELP } my $all = getAllPs(); my @pids = byArg( $arg ); print formatOut($_) for @pids; print "\n"; sub getAllPs { my $all = {}; my @rows = split(/\n+/,`ps -ajx | grep -v pssearch`); my @headers = split(/[ \t]+/,shift(@rows)); my $qtheads = $#headers; for my $row (@rows) { chomp $row; my @vals = split(/[ \t]+/,$row); my $ps = {}; for (my $i=0; $i <= $qtheads; $i++) { my $k = $headers[$i]; my $v = $i < $qtheads ? shift(@vals) : join(' ',@vals); $ps->{$k} = $v; } $all->{$ps->{PID}} = $ps if $ps->{PID}; } return $all; } sub byFuser { my $path = shift; my $fuser = `which fuser`; return { message => "fuser not found" } unless $fuser =~ m,^/,; chomp $fuser; if ( $path !~ m,^/,) { eval 'use Cwd "abs_path"; $path = abs_path($path);'; return { message => "Cwd perl module is missing - use full path", error => "$@" } if $@; } my $out = `"$fuser" -f "$path" 2>/dev/null`; chomp $out; return { pid => $out, message => "In use by PID $out", path => $path } if $out =~ m,^[0-9]+$,; return { message => "Not in use by any process", path => $path }; } sub byArg { my $arg = shift; my @out; if ( -e $arg) { my $fu = byFuser($arg); my $path = $fu->{path}||$arg; print "\nPath: $path\n"; $arg = $fu->{pid} if $fu->{pid}; print " `--> $fu->{message}\n" if $fu->{message}; return @out if ( $fu->{path} and ! $fu->{pid} ) } if ( $arg =~ m/^[0-9]+$/) { push(@out,$all->{$arg}{PID}); } else { foreach my $pid (keys %$all) { my $ps = $all->{$pid}; push(@out,$pid) if $ps->{COMMAND} =~ m/$arg/i; } } return @out; } sub makeTree { my $pid = shift; my $ps = $all->{$pid}; return "" unless $ps; my $out = {}; $out->{PID} = $pid; if ( $ps->{PPID} ) { my $parent = makeTree( $ps->{PPID} ); if ( $parent ) { $out->{parent} = $parent; $out->{level} = $parent->{level} +1; } else { $out->{zombie} = 1; $out->{level} = 0; } } else { $out->{level} = 0; } return $out; } sub formatOut { my $pid = shift; my $sel = makeTree($pid); my @lines; @lines = formatSelEntry($sel,@lines); return join("\n","",@lines,""); }; sub formatSelEntry { my $sel = shift; my @lines = @_; my $pid = $sel->{PID}; my $ps = $all->{ $pid }; die "PID not found: $pid\n" unless $ps; my $out = ""; for my $flag (qw/PID USER TIME STAT/ ) { $out .= "[$flag:$ps->{$flag}] " if $ps->{$flag}; } if ( $sel->{level} ) { my $pre = " `--> "; if ( $sel->{level} > 1 ) { my $qt = ( $sel->{level} -1 ) * 6; $pre = (" " x $qt).$pre; } $out = $pre . $out; } $out .= '[ZOMBIE] ' if $sel->{zombie}; $out .= $ps->{COMMAND}; unshift @lines,$out; @lines = formatSelEntry($sel->{parent},@lines) if $sel->{parent}; return @lines; }
Powered by JBLOUD, © 2021 altersoftware.IT