Script to clean up old files that should only run one instance
General impressions - nice neat code, well commented.  It's good that you use trap to clean up on exit.

Shellcheck picks up a couple of oversights:

206596.sh:11:11: note: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?. [SC2181]
206596.sh:22:1: warning: Use 'cd ... || exit' or 'cd ... || return' in case cd fails. [SC2164]
206596.sh:27:5: note: read without -r will mangle backslashes. [SC2162]
206596.sh:44:1: warning: Use 'find .. -print0 | xargs -0 ..' or 'find .. -exec .. +' to allow non-alphanumeric filenames. [SC2011]




Let's do a walk-through:


#!/bin/bash


Why bash?  I don't think there's anything here that can't be achieved with standard POSIX shell.
NUM_PROCS=4


What's special about 4?  If it's the number of cores you have available, then we could automate that:

NUM_PROCS=$(getconf _NPROCESSORS_ONLN)

PIDFILE="/tmp/cleanup.pid"


I'm not sure about CentOS, but on the platforms I'm more familiar with, pidfiles normally live under /run (or /var/run on older installations).
PID_NOW="$$"


Never modified; I think it's clearer to simply use $$ where it's needed.
echo "$1" &gt; "$PIDFILE"

if [[ "$?" -ne 0 ]]; then


Instead of testing $?, we should use the result directly (and since we never call this with anything other than our own pid, let's just embed that in the function rather than passing as argument).  Give the function a POSIX-compliant name, and declare it without the deprecated function keyword:

save_pid() {
    if ! echo $$ &gt;"$PIDFILE"
    then
        # If we couldn't save the PID to the lockfile...
        echo &gt;&amp;2 "Failed to create PID file for PID $$ in $PIDFILE; exiting"
        exit 1
    fi
}


Note that the message is printed to standard error (stream 2) rather than standard output.
cd /scratch


There's no checking that this command succeeded.  We could append || exit 1 or similar, but we can catch more errors by setting shell flags -e and -u at the beginning of the script.

There's really no need to change working directory at all; we could just omit this command, and use the directory name where we need it.
if [[ -f "$PIDFILE" ]]


The comment says we're testing for existence, so we should be using -e (or change the comment).  And we can use the standard [ command; there's nothing to be gained from Bash-specific [[.
    read PID_SAVED &lt; "$PIDFILE"


Shellcheck complains about using read without -r option.  Whilst we don't expect to see shell escapes in this file, there's no harm in pacifying the warning.  Or, we could just interpolate the file directly:

if ps --quick-pid "$(cat $PIDFILE)" &amp;&gt; /dev/null


Or just test for the existence in procfs:

if [ -e "/proc/$(cat $PIDFILE)" ]


We could add further tests to ensure that we don't have a re-used pid that's running a different program, but I won't pursue that here.
This structure can be simplified:

if a
then
    if b
    then exit 1
    else do-c
    fi
else do-c
fi


It's exactly equivalent to

if a &amp;&amp; b
then exit 1
fi
do-c


That simplification gives us:

if [ -e "$PIDFILE" ] &amp;&amp; [ -e "/proc/$(cat $PIDFILE)" ]
then
    # A process exists with our saved PID
    echo &gt;&amp;2 "Cleanup script is already running with PID $PID_SAVED; exiting"
    exit 1
fi

save_pid

trap clean-up HUP INT QUIT ILL ABRT BUS SEGV PIPE TERM ERR


Instead of listing all these signals, we just want to clean up however the shell exits:

trap clean_up EXIT

ls | xargs -P "$NUM_PROCS" -I{} \


It's dangerous to pipe the output of ls like that.  Files not under your control can contain almost anything, including newlines and other significant space.  I don't think we really want to ignore dot-files, either.  I recommend find -maxdepth 1 -mindepth 1, which can then write safely to xargs using --print0.  We might want to eliminate symlinks from the listing, although we know that the inner find won't follow them without -H or -L.
save_pid and clean_up are only used once each now, so could be usefully inlined.




Modified code

#!/bin/sh

set -eu

LIMIT_TIME=30 # days
NUM_PROCS=$(getconf _NPROCESSORS_ONLN)
PIDFILE="/var/run/cleanup.pid"

# check pidfile
if [ -e "$PIDFILE" ] &amp;&amp; [ -e "/proc/$(cat $PIDFILE)" ]
then
    # A process exists with our saved PID
    echo &gt;&amp;2 "Cleanup script is already running with PID $PID_SAVED; exiting"
    exit 1
fi

# write pidfile
    if ! echo $$ &gt;"$PIDFILE"
then
    # If we couldn't save the PID to the lockfile...
    echo &gt;&amp;2 "Failed to create PID file for PID $$ in $PIDFILE; exiting"
        exit 1
    fi

trap 'rm "$PIDFILE"' EXIT

# Now start working
find /scratch -maxdepth 1 -mindepth 1 \! -type l --print0 \
     | xargs -0 -P "$NUM_PROCS" -I{} \
             find {} -xdev -type f -mtime "+$LIMIT_TIME" -delete




After all that, consider that you might be reinventing a wheel.  Most likely, you have a tmpreaper package available that can be configured to do exactly this task.