Everything that systemd provides to a process invoked for a service — its arguments, its environment, the control group(s) containing it, its resource limits, its open file descriptors — can be and is done by other service managers, too. Moreover, there is no shared convention for identifying what service manager is managing services; no conventional environment variables, nor other markers.
You might be thinking of checking the executable name of the parent process. This is a non-starter, for the reasons expounded in https://unix.stackexchange.com/a/196252/5132 . The name of the executable program image of the parent process (for system-wide services) will be
/sbin/init on Debian Linux operating systems, because Debian has the convention of that being an alternatives-style symbolic link to the actual process 1 program image file, and the the
/init program in the initramfs only needing to know that one name.
You might be thinking that, despite what I just wrote, control groups are a systemd marker. They are not. Here's the control group tree of a service process being managed by a completely different service manager,
service-manager from the nosh toolset:
% systemd-cgls /system.slice/service-manager.service/tinydns@.service
Control group /system.slice/service-manager.service/tinydns@.service:
tinydns program, finding a control group in
/proc/self/cgroup, has no justification for assuming that systemd set up that control group. It was actually set up by the
% cat /email@example.com/service/run
#Run file generated from ./tinydns@.socket
#DNS/UDP socket on 127.53.0.1
udp-socket-listen --systemd-compatibility --combine4and6 127.53.0.1 domain
envuidgid -- tinydns-d
setlogin -- tinydns-d
hardlimit -d 3000000
softlimit -d hard
No other process state changes are unique to systemd. Environment variables can be set with
setenv (the chain-loading tool)
export (the chain-loading tool), resource limits with
ulimit (the chain-loading tool), or
s6-softlimit, open file descriptors with
fdredir, namespaces with
unshare, scheduling priorities with
chrt, NUMA policy with
numactl; and so forth.
systemd is not the only speaker of the
LISTEN_FDS protocol, as can be seen from the aforegiven.
INVOCATION_ID is likewise just an exercise in populating
env/INVOCATION_ID at the start of a
run program and chaining through
envdir. None of these are reliable as markers.
There's also the flaw that you want to exclude processes started by
cron. The conceptual flaw here is that
cron is a service, and the processes that it spawns are running in the context of that service. There is no magic distinction between a process spawned by the
cron process in the
cron service and a process spawned by some other service process in some other service, that makes the former somehow distinguishable from the latter.
Rid yourself of this conceptual error, and an answer appears. The thing that distinguishes dæmons is that the (POSIX) sessions that they belong to do not have controlling terminals, and they have no other associations (from the name set by
setlogin, through systemd's user-space login session mechanism, to various security contexts) with any login session. There's not a portable direct way to query what the controlling terminal of a session is, but noting that opening
/dev/tty fails is an available indirect route. Note that some superficially promising C library functions are actually unreliable in practice.