ps -f gives an output like:
chazelas 11042 10528 1 08:49 ? 00:00:03 /usr/lib/firefox/firefox -contentproc -childID 6 -isForBrowser -prefsLen 7847 -prefMapSize 699608 -parentBuildID 20200720193547 -appdir /usr/lib/firefox/browser 10528 true tab
Doing grep "$1" to return the lines for a given process name is wrong on many accounts:
- that fails if
$1 starts with -. You need grep -e "$1" or grep -- "$1". You should really get into the habit of using the end-of-options delimiter when passing arbitrary data to commands.
grep takes a regexp pattern to match on (that's the re in grep). So grep a.py would match on aspy for instance. You can use grep -F to search for substrings instead.
ps -f does not report the process names but the process arguments (including argv[0] which by convention is generally a path to the command).
- you're grepping for regexp/substrings, without restricting where within the lines it matches. So above for
$1 == as for instance, it would match on the as in chazelas. Or it could match on the other arguments than argv[0].
grep | wc -l is grep -c.
Here, there is a (non-standard but very common) command to match processes by name (or other criteria for that matters): pgrep
pgrep -xc -- "$1"
Would count the processes whose name (like that reported by ps without -f) matches exactly the regexp in $1. With -f, pgrep matches on the full list of arguments (as reported by ps -f) instead of the process name.
That leaves the problem of process names containing regexp operators (like the . mentioned above). Unfortunately, pgrep doesn't have a -F option to do a string comparison instead of regexp match, so you'd need to escape the regexp operators in there.
Another option is to tell ps to only report the process names and then use grep -xF to do exact Fixed-string comparison:
ps -Ao comm= | grep -Fxce "$1"
Replace comm with args to print the list of arguments (possibly truncated though, some ps implementations allow one or more -w to raise the line length limit) instead of process name.
In any case, any user can create any process with any name and with any list of arguments, so finding processes by name is quite brittle. Anybody can trick you into thinking your process is there by starting one with the same name and same list of arguments running a completely different command.
It's generally better to check for the availability of services that your process is providing or hold on some resource it's currently using.
In some cases, you can add other criteria to your search such as effective uid (-u in pgrep), or the path of the executable it is currently running.
On Linux and with zsh:
pids=(/proc/<->(Nnu[chazelas]e['[[ $REPLY/exe -ef /usr/bin/sleep ]]']:t]))
Would store in $pids the ids of the processes that are running code in the /usr/bin/sleep file as the chazelas user for instance and you can use if (($#pids > 0)); then... to check that that list is not empty. (replace /usr/bin/sleep with =sleep or $commands[sleep] for searching the sleep command in $PATH).
More generally, it's much better to rely on your service manager to manage services and processes. Modern ones such as systemd will provide facilities to do that reliably.