How To List All Services In Linux

How To List All Services In Linux

Reading time1 min
#Linux#Sysadmin#Security#systemd#services#LinuxCommands

Mastering Service Discovery: How to List All Running and Available Services on Linux

Knowing what’s active or enabled on a Linux host isn’t optional—it underpins troubleshooting, performance tuning, and especially containment against lateral movement or resource leakage. Relying on a single tool or just the systemd interface is naive; service management in Linux remains fragmented across init systems, legacy startup scripts, and plain userland launches.


Quick view: The usual suspects rarely tell the full story

systemctl list-units --type=service --state=running

Gives you only running systemd services—ignoring everything not registered in its unit database. Try:

systemctl list-unit-files --type=service

for all recognized unit files; but again, only what systemd “sees”. Unregistered binaries or leftover init scripts won’t show.


Legacy and compatibility: /etc/init.d/, chkconfig, and Upstart

Init scripts (SysVinit, present on older RPM/DEB distros and occasionally still used for backward compatibility):

ls /etc/init.d/

Many distros keep these directories populated for non-systemd managed services, though not always used at boot.

To check enabled SysVinit services on RHEL 6/CentOS 6:

chkconfig --list | grep '3:on'

(3 is standard multi-user/no GUI; adjust for custom runlevels.)

Upstart (common on Ubuntu ≤ 14.10, some custom appliances)

initctl list

If you see:

init: unrecognized job: <foo>

you’re not running Upstart, move on.

Note: Confirm your primary init system via

ps -p 1 -o comm=

and verify the output (systemd, init, or upstart).


Hidden daemons: Processes not managed by unit/init scripts

Not every long-running process is a registered service. Look for custom socket servers, Java VMs, or hand-rolled Go daemons kicked off by cron or rc.local.

ps -eo pid,ppid,cmd,etime | grep -E 'nginx|httpd|postgres|sshd|java|go|python'

This surface-scraping approach is blunt but occasionally reveals “zombie” daemons—services started by a user or installer script and forgotten.


Network sockets: Which processes bind to which ports

Network-exposed services remain attack surface #1. Use ss, or fallback to netstat (if available):

sudo ss -tulnp

Columns show LISTEN state, associated PIDs, and executable names.

ProtoLocal AddressPID/Program name
tcp0.0.0.0:22651/sshd
tcp127.0.0.1:54328912/postgres

Grep for high-numbered ports; they're often where ad-hoc or third-party software listens.


Systemd: What's enabled to start at boot?

systemctl list-unit-files --type=service --state=enabled

This shows everything that will attempt to start at boot (though dependencies and ordering can still interfere). Spot-check for spurious entries—“stale” units from failed uninstallations are common.

For SysVinit:

ls -l /etc/rc3.d/S*

The ordering (numbers after S) determines start sequence, and missing scripts can cause inconsistent system states—seen this trip up more than one migration.


Practical example: Enumerating services on a Fedora 38 host

  1. systemd units (running):

    sudo systemctl list-units --type=service --state=running
    
  2. Registered services (installed):

    sudo systemctl list-unit-files --type=service
    
  3. Legacy init scripts:

    ls /etc/init.d/
    
  4. Sockets in use:

    sudo ss -tulnp | grep -v '127.0.0.1'
    
  5. Detached or user-launched daemons:

    ps aux | grep -E 'python|node|go|java|daemon'
    
  6. Detect unexpected autostarts:

    find /etc/rc*.d/ -type l -lname '*foo*'
    

Pro tip: Compare after patching or software installs

After dnf upgrade or a third-party app install, diff your service listing (systemctl list-unit-files --type=service > /tmp/services-before.txt) before and after. Many installers silently drop in autostart units.


Side effects and common missteps

  • On hybrid (old-to-new) systems, both SysVinit and systemd scripts can exist concurrently—potentially fighting for control (notably on Debian 8, RHEL 7 upgrades).
  • Not every binary in /etc/init.d/ has meaning, especially after package churn. Check file timestamps and contents for relevance.
  • systemctl daemon-reload is required after changing unit files for immediate effect; forgetting causes confusion mid-maintenance.

Key takeaway

Comprehensive service inventory requires cross-checking multiple sources: systemd, SysVinit, Upstart, direct process scans, and network binders. Anything less, you'll miss services—opening the door to unreliable operations and incomplete security postures.

For a deeper dive, automate these queries via custom Ansible modules or use tools like osquery for fleet-wide visibility. But start with rigor at the command line—plenty of surprises still crop up.


Further reading: man pages for systemctl(1), ss(8), and distribution-specific admin guides. Regular review of these techniques is best practice, especially ahead of quarterly patch cycles or before rolling out software to production estates.