I have cronjobs doing various cleanup tasks:

$ crontab -l
0 * * * * find ${HOME}/Downloads -depth 1 -d -mtime +12h -exec /usr/local/bin/trash {} \;
* * * * * /usr/bin/defaults delete com.apple.Spotlight userHasMovedWindow > /dev/null
* * * * * /usr/bin/defaults delete com.apple.Spotlight windowHeight > /dev/null

However, it seems the jobs, for some reason, never exits. Instead they linger on and show as (cron) companioned by either (find) or (defaults) in the output of ps and in the activity monitor.

It happens for all jobs.

After hours or days, the computer freezes as the OS won't allow any more processes to spawn.

$ sw_vers 
ProductName:    Mac OS X
ProductVersion: 10.15
BuildVersion:   19A583

Redirect stderr to /dev/null as well as stdout:

* * * * * /usr/bin/defaults delete com.apple.Spotlight userHasMovedWindow &> /dev/null
* * * * * /usr/bin/defaults delete com.apple.Spotlight windowHeight &> /dev/null

From trial and error it seems to be the stderr output of those commands that prevents the cronjob from exiting. I have no clue why that is, but it may be related to permissions to mail the output.


The traditional UNIX way of preventing a program from having multiple copies running is with a .pid (or lock) file. The following example appears on multiple places:

#!/bin/sh

NAME=$(basename "$0")

if [ -f /var/run/"$NAME.pid" ] &&
  ps -p $(cat /var/run/"$NAME.pid") >/dev/null 2>&1
then
   echo "Script is currently in progress... aborting..."
   exit 3
fi

# Remove the .pid file on exit (by setting a trap)
trap 'rm -f /var/run/"$NAME.pid"' EXIT

# Echoes the current PID to the .pid file
echo $$ > /var/run/"$NAME.pid"

The downside is that you'd need to move your commands into script files.

Disclaimer: you still need to figure out why the programs don't exit as they should, but this allows you to, at least, not overtax your system. You can also opt yo kill the offending PID instead of exiting the newly started script.