How to Diagnose High CPU Usage on a Linux Web Server

A high-CPU alert is a signal, not a diagnosis. On a Linux web server, slow responses can come from actual CPU saturation, blocked disk I/O, memory pressure, a traffic surge, expensive PHP requests, database queries, background jobs, or a compromised account.

The safest troubleshooting approach is to preserve evidence first, classify the bottleneck, and only then change configuration. Restarting services may restore availability, but it can also erase the clues needed to identify the root cause.

1. Record the incident before changing anything

Capture the time, affected sites, response codes, recent deployments, backup jobs, and monitoring alerts. Then record a small system snapshot:

date
uptime
free -h
df -h
ps aux --sort=-%cpu | head -20

Keep the output with the incident notes. A single screenshot of top is useful, but it does not show what happened before or after the sample.

2. Compare load average with the number of CPUs

uptime
nproc
lscpu

Load average counts runnable tasks and tasks waiting in uninterruptible sleep, so a high load value does not always mean the CPUs are fully busy. Compare the 1-, 5-, and 15-minute load averages with the number of logical CPUs and then inspect CPU states.

A short spike may reflect a deployment or scheduled job. A sustained load above available CPU capacity needs deeper investigation, but high I/O wait can produce a similar symptom.

3. Read CPU states instead of only the headline percentage

Run:

top
vmstat 1
mpstat -P ALL 1

Focus on:

Check whether one core is saturated while others are mostly idle. A single-threaded process can bottleneck one CPU without showing 100% across the entire machine.

4. Identify the process and thread consuming resources

ps -eo pid,ppid,user,comm,%cpu,%mem,etime --sort=-%cpu | head -30
pidstat -u -r -d 1

If one process is consistently at the top, identify its parent, user, start time, and open files before terminating it:

ps -fp PID
pstree -p PID
lsof -p PID | head

For a multi-threaded process, inspect threads:

top -H -p PID
ps -L -p PID -o pid,tid,pcpu,comm --sort=-pcpu

Do not kill a process solely because it appears at the top for one sample. A busy process may be doing legitimate work while another bottleneck causes the queue.

5. Check memory pressure, swap, and the OOM killer

free -h
vmstat 1
swapon --show
dmesg -T | grep -i -E 'out of memory|oom|killed process'

Low “free” memory is not automatically a problem because Linux uses memory for cache. Look at available memory, sustained swapping, major page faults, and OOM events. Heavy swap activity can make a server appear CPU-bound while requests wait on storage.

6. Separate disk I/O from CPU pressure

iostat -xz 1
iotop -oPa

High latency, queue depth, or I/O wait may point to backups, log rotation, database writes, malware scans, or storage limits. Correlate the start of the incident with Cron, backup, and snapshot schedules.

Avoid using one universal threshold for every disk. NVMe, local SSD, network storage, and shared cloud volumes have different latency and throughput characteristics. Compare current values with the server’s normal baseline.

7. Determine whether traffic caused the load

Check active connections and the busiest client addresses:

ss -s
ss -ant state established | wc -l
ss -ant | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr | head

Review the web access log for request rate, repeated URLs, status codes, bots, and expensive endpoints. A traffic increase may be legitimate, abusive, or caused by a retry loop.

Do not block an IP until you understand the traffic. Shared proxies, search crawlers, monitoring systems, and customer networks can produce many requests from one address.

8. Inspect Apache or Nginx behavior

Apache

Check the active MPM, worker limits, process count, and server-status if it is safely restricted:

apachectl -M | grep mpm
ps -C apache2 -o pid,pcpu,pmem,cmd --sort=-pcpu
ps -C httpd -o pid,pcpu,pmem,cmd --sort=-pcpu

Nginx

Check worker CPU, connection states, upstream response time, and error logs:

ps -C nginx -o pid,ppid,pcpu,pmem,cmd
nginx -T | less

High web-server CPU may actually originate in an upstream PHP-FPM pool or application server. Compare access-log timing with upstream timing where available.

9. Inspect PHP-FPM pools and slow requests

Confirm which pool serves the affected site, then review its error and slow logs. Useful checks include:

A larger pm.max_children is not always better. Every child consumes memory; increasing the limit without capacity planning can turn a CPU issue into swapping or an OOM event.

10. Check MySQL or MariaDB before tuning blindly

mysqladmin processlist
mysql -e 'SHOW FULL PROCESSLIST;'

Enable and review the slow-query log for a representative period. Look for repeated expensive queries, missing indexes, lock waits, temporary tables, and application patterns. Do not run OPTIMIZE TABLE or change buffer sizes as a reflex; first verify that the proposed change addresses the measured bottleneck.

11. Correlate the spike with scheduled activity

systemctl list-timers --all
crontab -l
ls -la /etc/cron.*

Backups, antivirus scans, compression, statistics jobs, certificate tasks, and WordPress Cron can overlap. Stagger heavy jobs and verify that backup software has appropriate CPU and I/O limits.

12. Preserve evidence during recovery

If availability is affected, recovery may require restarting a failed service, scaling resources, limiting a runaway job, or temporarily rate-limiting traffic. Before doing so:

A practical decision tree

  1. High user CPU: identify application, PHP, or database work.
  2. High system CPU: inspect kernel, networking, interrupts, and storage behavior.
  3. High I/O wait: identify the device and process generating I/O.
  4. High steal time: investigate hypervisor or cloud-host contention.
  5. Low CPU but slow site: check connections, queues, locks, memory, DNS, and upstream dependencies.

How to verify the fix

Re-run the same measurements under comparable traffic. Confirm that response time, queue length, error rate, load, CPU states, and resource saturation improved together. A lower CPU graph alone is not enough if requests are now queued or failing elsewhere.

If you need a structured review of a hosting environment, see the server administration and infrastructure services offered on this site.

رفع خطای 500 وردپرس؛ چک‌لیست عیب‌یابی از سمت هاست و سرور

خطای 500 Internal Server Error به این معنی است که وب‌سرور هنگام پردازش درخواست با مشکلی روبه‌رو شده، اما نتوانسته جزئیات دقیق آن را به مرورگر اعلام کند. در وردپرس، این خطا ممکن است از یک افزونه یا قالب ناسازگار، خطای PHP، تنظیم نادرست فایل .htaccess، کمبود منابع یا پیکربندی وب‌سرور ایجاد شود.

اشتباه رایج این است که بدون دیدن لاگ، چند تنظیم را هم‌زمان تغییر دهیم. روش مطمئن‌تر این است که ابتدا زمان و محدوده خرابی را مشخص کنیم، سپس با کمترین تغییر ممکن علت را جدا کنیم.

قبل از شروع: از وضعیت فعلی نسخه پشتیبان بگیرید

پیش از ویرایش فایل‌ها یا غیرفعال‌کردن افزونه‌ها، از فایل‌های سایت و دیتابیس نسخه پشتیبان بگیرید. اگر سایت تولیدی است، تغییرات را در بازه کم‌ترافیک انجام دهید و برای هر مرحله راه بازگشت داشته باشید.

مرحله اول: محدوده خطا را مشخص کنید

اول پاسخ این سؤال‌ها را پیدا کنید:

برای بررسی هدر پاسخ می‌توانید از دستور زیر استفاده کنید:

curl -I https://example.com/problem-page/

تفکیک کدهای 5xx مهم است؛ برای مثال 502 معمولاً به ارتباط وب‌سرور با PHP-FPM یا Upstream مربوط است، در حالی که 504 بیشتر به Timeout اشاره می‌کند.

مرحله دوم: لاگ را قبل از حدس‌زدن بخوانید

مهم‌ترین مدرک، خطایی است که در همان زمان درخواست ثبت شده است. بسته به محیط، این مسیرها را بررسی کنید:

برای فعال‌کردن لاگ وردپرس، خطوط زیر را قبل از عبارت توقف ویرایش در wp-config.php قرار دهید:

define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);

نمایش خطا روی سایت عمومی را خاموش نگه دارید؛ پیام خطا ممکن است مسیر فایل‌ها یا اطلاعات حساس را افشا کند. بعد از عیب‌یابی نیز Debug را غیرفعال کنید. راهنمای رسمی Debugging in WordPress جزئیات بیشتری دارد.

مرحله سوم: افزونه‌ها را به روش قابل بازگشت بررسی کنید

اگر پیشخوان باز می‌شود، افزونه‌ای را که دقیقاً قبل از خرابی نصب یا به‌روزرسانی شده غیرفعال کنید. اگر پیشخوان در دسترس نیست، از File Manager یا SSH نام پوشه افزونه مشکوک را در wp-content/plugins موقتاً تغییر دهید.

همه افزونه‌ها را یک‌باره حذف نکنید. اگر مجبورید همه را غیرفعال کنید، پس از بازگشت سایت آن‌ها را یکی‌یکی فعال کنید و بعد از هر تغییر، URL مشکل‌دار و لاگ را دوباره بررسی کنید. این روش منبع خطا را مشخص می‌کند و از نتیجه‌گیری اشتباه جلوگیری می‌کند.

مرحله چهارم: قالب فعال را جدا کنید

خطاهای Fatal در فایل‌های قالب یا توابع سفارشی می‌توانند پاسخ 500 ایجاد کنند. برای تست، موقتاً یک قالب پیش‌فرض سازگار فعال کنید. اگر سایت باز شد، لاگ را برای نام فایل و شماره خط بررسی کنید؛ فعال‌ماندن قالب پیش‌فرض راه‌حل نهایی نیست، بلکه فقط تست جداسازی است.

مرحله پنجم: فایل htaccess و Rewrite را بررسی کنید

در Apache و LiteSpeed، اشتباه نحوی یا دستور پشتیبانی‌نشده در .htaccess می‌تواند بلافاصله خطای 500 بسازد. فایل را تغییر نام دهید، سپس از بخش «تنظیمات ← پیوندهای یکتا» قوانین استاندارد وردپرس را دوباره ذخیره کنید.

اگر با حذف موقت فایل مشکل حل شد، دستورها را مرحله‌به‌مرحله برگردانید. قوانین امنیتی، Redirectها، تنظیمات PHP و دستورهایی مانند Options یا SetEnv باید با پیکربندی هاست سازگار باشند.

مرحله ششم: نسخه PHP، افزونه‌های PHP و محدودیت‌ها

نسخه PHP باید با هسته وردپرس، قالب و افزونه‌ها سازگار باشد. بعد از تغییر نسخه PHP این موارد را بررسی کنید:

افزایش Memory Limit بدون دیدن لاگ ممکن است فقط نشانه را پنهان کند. اگر خطا Allowed memory size exhausted است، علاوه بر افزایش منطقی محدودیت، افزونه یا Query پرمصرف را پیدا کنید.

مرحله هفتم: مالکیت و سطح دسترسی فایل‌ها

Permission نامناسب یا Owner اشتباه، مخصوصاً پس از انتقال سایت، می‌تواند اجرای PHP یا خواندن فایل‌ها را مختل کند. مقادیر رایج 755 برای پوشه و 644 برای فایل است، اما تنظیم نهایی باید با مدل اجرای PHP و سیاست هاست هماهنگ باشد. از 777 به‌عنوان راه‌حل دائمی استفاده نکنید.

مرحله هشتم: منابع و سلامت سرویس‌ها

اگر خطا مقطعی است، فقط وردپرس را بررسی نکنید. CPU، RAM، I/O، تعداد Processها، محدودیت Entry Process و اتصال دیتابیس را هم ببینید:

uptime
free -h
df -h
ps aux --sort=-%cpu | head
systemctl status php-fpm
systemctl status mariadb

در هاست اشتراکی، نمودار Resource Usage می‌تواند نشان دهد خطا هم‌زمان با رسیدن به Limit رخ داده است. در سرور اختصاصی، لاگ Kernel و OOM Killer نیز مهم است.

ترتیب پیشنهادی عیب‌یابی

  1. ثبت زمان، URL و کد پاسخ
  2. بررسی Error Log همان درخواست
  3. بازگردانی آخرین تغییر
  4. تست افزونه و قالب به‌صورت کنترل‌شده
  5. بررسی htaccess و Rewrite
  6. بررسی PHP، Permission و منابع
  7. تست نهایی و خاموش‌کردن Debug

چطور مطمئن شویم مشکل واقعاً حل شده است؟

فقط بازشدن صفحه اصلی کافی نیست. صفحه مشکل‌دار، ورود، فرم‌ها، Cron، ارسال ایمیل و یک عملیات دیتابیس را تست کنید. سپس لاگ خطا و مانیتورینگ را حداقل برای یک چرخه پرترافیک بررسی کنید. اگر خطا تکرار شد، زمان دقیق و شناسه درخواست را برای مقایسه نگه دارید.

برای بررسی یا رفع اصولی مشکلات میزبانی می‌توانید با بخش مدیریت سرور و زیرساخت در ارتباط باشید.