Orphaned processes and layered IP block troubleshooting in cPanel and CloudLinux#
On servers running cPanel and CloudLinux hosting multiple accounts, operating system mechanics and network rules can be deceptive when two separate issues collide: interactive processes refusing to terminate after SSH disconnects, and legitimate IP addresses blocked for reasons invisible inside the control panel.
I ran into this exact situation recently. On one hand, an account was piling up disconnected log-monitoring processes that crowded the process table. On the other hand, a test client IP was facing connection drops despite being listed as clean in the main firewall.
Below is the step-by-step investigation I used to isolate kernel signal drops, apply the correct pkill flags for account-based cleanup, and audit IP filtering layers across the server.
The ghost of detached interactive sessions#
The first symptom was an accumulation of lingering processes consuming system resources. Running ps aux to inspect a specific cPanel user (user) revealed multiple interactive shells and orphaned file-monitoring commands:
[root@server ~]# ps aux | grep user
user 3131927 0.0 0.0 5352 4276 ? S 10:32 0:00 /bin/bash -l
user 3146071 0.0 0.0 3104 1892 ? S 10:33 0:00 tail -f domain.com
user 3279880 0.0 0.0 5352 4296 ? S 15:16 0:00 /bin/bash -l
user 3446124 0.0 0.0 3104 1892 ? S 10:54 0:00 tail -f domain.com
user 3480583 0.0 0.0 3104 1892 ? S 15:30 0:00 tail -f domain.com-ssl_log
root 3864491 0.0 0.0 3884 2468 pts/5 S+ 15:55 0:00 grep --color=auto user
Kernel behavior and the lost controlling terminal#
In the TTY column, the question mark (?) indicates that these processes were detached from their controlling terminal.
When someone connects via SSH, the OpenSSH daemon invokes fork() followed by execve() to launch /bin/bash -l. The -l flag tells bash to run its login routine, reading /etc/profile and ~/.bash_profile. If the network connection drops abruptly due to a timeout or lost packet stream, the kernel sends a SIGHUP signal to the session leader. However, if the shell ignores the signal or if child processes (tail -f) were spawned in a way that prevents signal propagation down the tree, the process is reparented to PID 1 (systemd). It enters the sleep state (S), waiting for I/O indefinitely.
Commands like tail -f make this worse. In GNU coreutils, tail -f uses the Linux kernel's inotify_add_watch API or falls back to poll() to monitor file descriptors. With no active terminal to receive STDOUT, it sleeps continuously while waiting on buffer events that will never be consumed.
Why default pkill commands fail silently#
The initial instinct is often to terminate everything by typing the username:
[root@server ~]# pkillall -9 user
-bash: pkillall: command not found
[root@server ~]# pkill -9 user
The first command fails because pkillall is not installed by default on AlmaLinux or Red Hat systems (the tool is killall, provided by the psmisc package). The second command, pkill -9 user, exits without output but fails to kill any workers.
pkill belongs to procps-ng. By default, it evaluates the search string against the executable name stored in /proc/[pid]/stat, not against the system username. Because no executable binary was literally named user, the search returned zero hits.
To match by the owning user account, the -u flag (Effective UID) must be supplied:
# Correct termination using pkill by user
pkill -9 -u user
# Alternative using killall
killall -9 -u user
Issuing SIGKILL (-9) prevents the target application from handling the signal via sigaction(). The kernel stops execution immediately, reclaims memory, and closes attached file descriptors. However, application-level lock files (.lock) will remain on the filesystem, which requires caution if running processes were writing to databases or active session stores.
Inspecting open descriptors and system calls#
Before terminating unknown processes, I inspect what is keeping them alive:
- Open file descriptors and sockets: using
lsofto inspect file references:
lsof -p 3131927
- Tracing system calls with strace: attaching to the running process to verify whether it is blocked on input:
strace -p 3131927
If the output shows read(0, ...), the shell is waiting for input from STDIN on a terminal that no longer exists.
To prevent abandoned sessions from accumulating, I added an automatic idle timeout variable to the global profile:
# /etc/profile.d/timeout.sh
readonly TMOUT=900
export TMOUT
With this in place, idle shells without terminal activity for 15 minutes are cleanly closed by bash itself.
Tracing layered IP blocks in cPanel and CloudLinux#
Once the process table was cleared, I investigated why a test IP (177.93.168.253) was unable to reach server services. In cPanel environments running on CloudLinux, connection failures are rarely caused by a single iptables rule. Filtering happens across multiple independent layers.
I traced the packet path through the following CLI steps:
1. Network and kernel layer (Netfilter and CSF)#
The CSF firewall interacts with the Linux kernel's netfilter subsystem. If an IP triggers repeated login errors via LFD, it is placed in temporary or permanent drop chains.
To search and release the address:
# Global search inside CSF rules
csf -g 177.93.168.253
# Temporary unblock and rule reload
csf -dr 177.93.168.253 && csf -r
If CSF shows no record of the IP, inspecting raw iptables rules confirms whether other chains are dropping packets:
iptables -L INPUT -v -n | grep 177.93.168.253
2. Application and WAF layer (Imunify360 and ModSecurity)#
On CloudLinux, Imunify360 integrates with Apache or LiteSpeed using ModSecurity rules and ipset collections. It maintains a greylist that redirects suspicious traffic to a CAPTCHA screen on port 52223.
To check IP status within the agent:
# Query WAF lists
imunify360-agent blacklist ip list | grep 177.93.168.253
imunify360-agent graylist ip list | grep 177.93.168.253
# Add to permanent whitelist
imunify360-agent whitelist ip add 177.93.168.253 --comment "Acesso Admin"
3. Service and PAM authentication layer (cPHulk)#
When TCP handshakes succeed on ports 22 (SSH) or 2083 (cPanel) but authentication fails immediately, cPHulk is usually responsible. It hooks into the local PAM stack and queries an internal database to stop brute-force attacks at the application tier:
# Check cPHulk command-line records
/usr/local/cpanel/bin/cphulk_pam_ctl --list | grep 177.93.168.253
# Review brute-force history via WHM API
whmapi1 get_cphulk_user_brute_force_log IP=177.93.168.253
# Flush recorded blocks for the IP
whmapi1 flush_cphulk_login_history_for_ips ip=177.93.168.253
4. Account resource boundaries (CloudLinux LVE and CageFS)#
If an IP belongs to a user reporting blank pages or HTTP 508 errors, the block is not caused by network filtering, but by account resource limits in LVE or mount namespace issues inside CageFS:
# Check real-time process and memory use
lvetop
# Check historical limit faults for the account
lveinfo --user user
# Verify virtualized mount namespaces
cagefsctl --check-environment
5. Multi-log audit across system daemons#
To avoid guessing which component dropped the request, I run a single search command across all daemon logs simultaneously:
grep -r "177.93.168.253" /var/log/exim_mainlog /var/log/messages /var/log/secure /usr/local/apache/logs/error_log /var/log/cpanel/cphulkd.log /var/log/imunify360/error.log /etc/apache2/logs/modsec_audit.log
This immediately reveals whether the request was rejected by Exim, locked out by PAM, or flagged by a ModSecurity rule.
From process tables to network filters: an integrated workflow#
Managing multi-tenant CloudLinux hosts requires an understanding of both process lifecycles and packet filtering layers. A hanging command is typically waiting on a detached terminal rather than suffering a system freeze, and an inaccessible IP can be held by PAM or WAF engines even when firewall ports are open in the kernel.
Knowing the correct syntax for commands such as pkill -u, inspecting system calls with strace, and methodically checking CSF, Imunify360, and cPHulk resolves incidents faster while avoiding arbitrary service reboots.
Was this article helpful?
Leave a quick reaction to help prioritize future technical guides:
This post is licensed under CC BY-NC.



Comments
Join the discussion below.
0 comments