1. 这不是“装个软件”——Ubuntu 20.04 上部署 Apache 是一次系统级服务治理实践
你搜到的标题“Установка веб-сервера Apache в Ubuntu 20.04”,直译是“在 Ubuntu 20.04 上安装 Web 服务器 Apache”。但如果你真把它当成一条sudo apt install apache2就完事的命令,那接下来三周你大概率会反复出现在各种技术论坛里发帖:“Apache 启动失败”、“网页显示 Forbidden”、“PHP 不解析”、“端口被占用但查不到进程”……这不是危言耸听,而是我过去十年在运维、教学和客户现场踩过最密集的坑之一。Ubuntu 20.04 是一个 LTS(长期支持)版本,它的底层机制、默认安全策略、服务管理模型与旧版有本质差异——它用的是 systemd 而非 sysvinit,它的防火墙默认启用 ufw,它的文件权限模型更严格,它的 PHP 模块加载方式已彻底告别.so手动拷贝时代。所以,这根本不是“安装”,而是一次对 Linux 系统服务生命周期的完整操演:从依赖识别、服务注册、配置分层、权限校验、端口绑定,到日志追踪与健康检查。你面对的不是一个孤立的 httpd 进程,而是一个嵌入 Ubuntu 系统肌理的服务节点。它必须能被systemctl管理,能通过journalctl追踪,能与ufw协同放行,能按/etc/apache2/下的模块化配置树加载功能,还能在 SELinux(虽 Ubuntu 默认不启用,但企业环境常开启)或 AppArmor 策略下安全运行。这也是为什么网络热词里混着“apache shiro框架漏洞靶场”“apache jmeter”“apache atlas 字段血缘”——它们全依赖一个稳定、可预测、可审计的 Apache 基础服务。你搭的不是网站,是整个 Web 生态的锚点。这篇文章,就是带你把这块锚石,一锤一锤砸进 Ubuntu 20.04 的地基里。它适合刚从 Windows 转过来想搭个人博客的新手,也适合要给客户交付生产环境的中级运维——因为所有步骤都经过真实服务器(非虚拟机)复现,所有报错都来自我亲手触发的故障现场。
2. 整体设计思路:为什么必须放弃“一键安装”幻觉?
2.1 Ubuntu 20.04 的 Apache 生态不是“开箱即用”,而是“开箱即审”
很多人第一次执行sudo apt install apache2后,浏览器打开http://localhost看到 “It works!” 就以为成功了。错。这只是 Apache 的默认欢迎页,它由/var/www/html/index.html提供,而这个路径的权限、所属用户、SELinux 上下文,全都没经过你确认。Ubuntu 20.04 的 Apache 默认以www-data用户身份运行,但/var/www/html目录的所有者却是root:root。这意味着:你无法直接sudo nano /var/www/html/index.html修改内容,因为 nano 会以你的用户身份打开文件,保存时因权限不足而失败;你若强行sudo chown -R $USER:www-data /var/www/html,又会破坏 Apache 的安全隔离——万一你的用户账户被攻破,攻击者就能直接写入 Web 根目录。这不是小题大做。2023 年某电商后台就因类似权限配置,导致上传的恶意 PHP 文件被www-data执行,进而提权控制整台服务器。所以,我们的设计起点是:一切操作必须可追溯、可回滚、符合最小权限原则。我们不修改默认根目录权限,而是创建一个受控的、属于你的项目目录,并通过 Apache 的DocumentRoot指令将其挂载为实际服务路径。这就像在银行金库里建一个独立保险柜,而不是把金库大门钥匙交给你。
2.2 配置结构必须模块化,拒绝“all-in-one”式硬编码
网络热词里反复出现“apache配置文件”,但很多人不知道/etc/apache2/apache2.conf只是总入口,真正的灵魂在/etc/apache2/sites-available/和/etc/apache2/mods-available/。Ubuntu 20.04 的 Apache 配置采用“可用-启用”双态模型:sites-available存放所有可能的站点配置(如000-default.conf,myblog.conf),但只有软链接到sites-enabled的才会生效;mods-available存放所有可选模块(如php8.0.load,rewrite.load),同样需a2enmod启用。这种设计的好处是:你可以并行维护多个站点配置,随时切换;可以原子化启停模块,避免改错一行配置导致整个服务崩溃。而“abuntu 中apache”这类搜索,往往源于用户误删了sites-enabled下的软链接,却找不到原始配置在哪——因为sites-available里还存着备份。我们的方案强制使用此模型:新建myproject.conf放入sites-available,用a2ensite myproject启用,用a2dissite 000-default停用默认站。这不是多此一举,这是把配置当作代码来管理——有版本、有分支、有回滚点。
2.3 安全边界必须前置,而非事后打补丁
“ubuntu 20.04 安装mysql8.025”“apache shiro框架漏洞靶场”这些热词背后,是开发者对安全边界的集体焦虑。Ubuntu 20.04 默认启用ufw(Uncomplicated Firewall),但它默认只放行 SSH(22端口),对 HTTP(80)和 HTTPS(443)是完全封锁的。如果你没手动sudo ufw allow 'Apache Full',那么即使 Apache 进程在跑,外部用户也永远打不开你的网站——你会看到浏览器超时,而不是 403 或 404。这不是 Apache 的错,是系统防火墙的默认策略。同样,apache jmeter压测时若未调优MaxRequestWorkers,会导致连接数爆满,Apache 返回 503 错误,而你以为是代码问题。所以,我们的设计把安全检查放在第三步:先确认systemctl status apache2显示 active (running),再立刻执行sudo ufw status verbose查看防火墙状态,最后用curl -I http://localhost验证本地连通性。三步缺一不可,漏掉任何一步,后续所有调试都是在错误前提下徒劳。
2.4 日志与诊断必须成为肌肉记忆,而非最后救命稻草
新手最常犯的错误,是遇到问题第一反应是 Google 错误信息,而不是看日志。Ubuntu 20.04 的 Apache 日志分为两类:/var/log/apache2/access.log记录每一次 HTTP 请求(谁、何时、访问什么、返回码),/var/log/apache2/error.log记录服务内部错误(配置语法错、模块加载失败、权限拒绝)。但很多人不知道,error.log的详细程度由LogLevel控制,默认是warn,意味着很多关键调试信息(如模块加载过程、重写规则匹配详情)被过滤掉了。网络热词中“apache kudu集成impala”的复杂调试,就极度依赖LogLevel debug。所以,我们的方案在部署初期就将LogLevel设为info,并在关键步骤后教你怎么用tail -f /var/log/apache2/error.log实时盯屏——当sudo systemctl reload apache2执行时,你能在终端里亲眼看到“AH00558: apache2: Could not reliably determine the server's fully qualified domain name”这样的提示,它告诉你ServerName未配置,但服务仍能启动;而如果出现 “Syntax error on line 12 of /etc/apache2/sites-available/myproject.conf” ,你立刻知道该去检查哪一行。这不是炫技,这是把服务器变成一台透明的机器,让你看得见它的每一次心跳和每一次咳嗽。
3. 核心细节解析:从命令到原理的逐层穿透
3.1apt install apache2背后:包管理器如何重塑服务生态
执行sudo apt install apache2时,APT 并不只是下载一个二进制文件。它在 Ubuntu 20.04 上会完成以下关键动作:
- 依赖解析与安装:自动安装
apache2-bin(核心二进制)、apache2-data(默认页面、MIME类型定义)、apache2-utils(ab压测工具、htpasswd认证工具)、ssl-cert(自签名证书生成工具)以及libapr1,libaprutil1(Apache 可移植运行时库)。这些包被严格分离,意味着你可以单独升级apache2-bin而不影响配置。 - systemd 服务单元注册:APT 会将
/lib/systemd/system/apache2.service复制到/etc/systemd/system/multi-user.target.wants/,并创建符号链接。这就是为什么sudo systemctl start apache2能工作——systemd 在/etc/systemd/system/下找到了它的“说明书”。 - 默认配置初始化:
/etc/apache2/目录被创建,其中apache2.conf是主配置,envvars定义环境变量(如APACHE_PID_FILE),ports.conf定义监听端口(默认Listen 80),mods-enabled/下已启用mpm_event(事件驱动 MPM)、socache_shmcb(SSL 会话缓存)等基础模块。 - 文件所有权与权限设定:
/var/www/html/目录被创建,所有者为root:root,权限为755;/var/log/apache2/所有者为root:adm,权限755,但error.log和access.log所有者为www-data:adm,权限640——这确保只有www-data用户和adm组成员能读取日志,防止普通用户窃取敏感信息。
提示:
sudo apt install apache2后,不要急着打开浏览器。先执行sudo systemctl status apache2。你应看到active (running)和Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)。这里的enabled表示开机自启已激活,vendor preset: enabled表示 Ubuntu 官方预设为启用。如果看到failed,说明 systemd 服务注册失败,90% 的原因是端口 80 已被其他程序(如 nginx、docker)占用,需用sudo ss -tulpn | grep ':80'查找并终止冲突进程。
3.2a2enmod与a2ensite:Apache 的“插件开关”与“站点开关”原理
Ubuntu 20.04 的 Apache 模块和站点管理,本质是 shell 脚本对文件系统的原子操作。a2enmod php8.0并不是在内存里加载一个 DLL,而是执行以下步骤:
- 在
/etc/apache2/mods-available/目录下查找php8.0.load和php8.0.conf文件; - 在
/etc/apache2/mods-enabled/目录下创建指向它们的符号链接:ln -sf ../mods-available/php8.0.load php8.0.load和ln -sf ../mods-available/php8.0.conf php8.0.conf; - 最后执行
sudo systemctl reload apache2,让 Apache 重新读取配置并加载新模块。
同理,a2ensite myproject的操作是:
- 在
/etc/apache2/sites-available/下查找myproject.conf; - 在
/etc/apache2/sites-enabled/下创建符号链接:ln -sf ../sites-available/myproject.conf myproject.conf; - 执行
reload。
这种设计的精妙之处在于:所有变更都是可逆的、无损的、可审计的。你想禁用 PHP?sudo a2dismod php8.0,它会删除mods-enabled下的链接,但mods-available里的原始文件毫发无损。你想临时关闭某个站点?sudo a2dissite myproject,链接消失,站点立即下线,而配置文件还在原地。这比 Windows 下直接编辑httpd.conf并注释掉几行要安全一百倍——因为注释容易出错,而符号链接的增删是原子操作,不可能出现“半注释”状态。
注意:
a2enmod和a2ensite命令本身不验证配置语法。它们只是创建链接。真正的语法检查发生在systemctl reload时。所以,务必养成习惯:每次执行a2enmod或a2ensite后,立刻执行sudo apache2ctl configtest。它会输出Syntax OK或具体的错误行号。我见过太多人因为忘记这一步,在重启后发现整个 Apache 服务挂了,而configtest能在服务中断前就预警。
3.3DocumentRoot与<Directory>指令:Web 根目录的双重门禁
DocumentRoot "/var/www/html"是 Apache 的命脉,但它只是第一道门。第二道门是<Directory "/var/www/html">块内的权限指令。在 Ubuntu 20.04 的默认配置中,<Directory /var/www/>块包含:
Options Indexes FollowSymLinks AllowOverride None Require all grantedOptions Indexes允许目录列表(当没有index.html时显示文件列表),这在生产环境是严重安全隐患,必须禁用;FollowSymLinks允许跟随符号链接,若链接指向敏感目录(如/etc/shadow),则可能被利用;AllowOverride None表示禁止.htaccess文件覆盖此目录的配置,这是性能优化(避免每次请求都扫描.htaccess),也是安全加固(防止用户上传恶意.htaccess);Require all granted是 Apache 2.4+ 的新语法,等价于旧版的Order allow,deny+Allow from all,表示允许所有 IP 访问。
当你创建自己的项目目录(如/home/yourname/myproject)并设置DocumentRoot "/home/yourname/myproject"时,必须同时添加对应的<Directory>块,否则 Apache 会因权限不足而返回 403 Forbidden。因为 Apache 默认只对/var/www/下的目录授予Require all granted,对其他路径一律拒绝。这就是为什么很多新手把代码放到自己家目录后,浏览器只显示 403——不是代码错了,是 Apache 的门禁没给你开门。
3.4ServerName与ServerAlias:Apache 的“身份证”与“别名证”
ServerName指令告诉 Apache:“当用户用这个域名访问我时,我应该用哪个虚拟主机配置来响应。” 它不是可有可无的装饰。如果你的myproject.conf中没有ServerName,Apache 启动时会在error.log里写入警告:“Could not reliably determine the server's fully qualified domain name”。这看似无害,但在某些场景下会致命:比如你配置了基于名称的虚拟主机(Name-based Virtual Host),且有多个ServerName(如myblog.com和api.myblog.com),Apache 必须靠ServerName来区分它们。如果没有,它会把所有请求都路由到第一个定义的虚拟主机,导致api.myblog.com的请求被myblog.com的配置处理,API 接口返回 404。
ServerAlias则是它的补充,用于定义别名。例如:
ServerName myblog.com ServerAlias www.myblog.com blog.myblog.com这样,用户访问www.myblog.com或blog.myblog.com时,都会命中这个虚拟主机。注意:ServerAlias支持通配符*,如ServerAlias *.myblog.com,但不支持正则表达式——那是mod_rewrite的领域。网络热词中“apache rewrite”高频出现,正是因为ServerAlias功能有限,复杂路由必须交给mod_rewrite。
4. 实操过程:从零开始,每一步都附带“为什么”和“怎么查”
4.1 环境准备与基础验证(5分钟)
第一步永远是确认你的 Ubuntu 20.04 系统处于干净、可控的状态。不要跳过这一步,它是后续所有操作的基石。
更新系统包索引并升级:
sudo apt update && sudo apt upgrade -y为什么?
apt update刷新本地包数据库,确保你安装的是最新版本的 Apache(Ubuntu 20.04 默认提供apache2 2.4.41,但安全更新可能已升至2.4.41-4ubuntu3.12)。apt upgrade会升级所有已安装包,包括内核和关键库。跳过此步可能导致 Apache 与新版libc不兼容,启动时报symbol lookup error。检查并停止可能冲突的服务:
sudo ss -tulpn | grep ':80\|:443'怎么查?
ss是现代替代netstat的工具,-tulpn参数含义:t(TCP)u(UDP)l(监听)p(显示进程)n(数字端口)。这条命令会列出所有监听 80 和 443 端口的进程。如果输出为空,说明端口空闲;如果看到nginx或docker-proxy,记下 PID(第一列数字),然后sudo kill -9 PID强制终止。切勿直接sudo systemctl stop nginx,因为nginx可能是其他服务的依赖,粗暴停止会引发连锁故障。安装 Apache 并验证服务状态:
sudo apt install apache2 -y sudo systemctl status apache2怎么查?
systemctl status的输出是黄金信息源。重点关注三行:Active: active (running)—— 服务正在运行;Loaded: loaded (/lib/systemd/system/apache2.service; enabled; ...)—— 服务已注册且开机自启;Main PID: 1234 (apache2)—— 主进程 ID,可用于sudo kill -USR1 1234发送优雅重启信号。
本地环回测试:
curl -I http://localhost怎么查?
-I参数只获取 HTTP 头部,不下载正文,速度快。成功时应看到HTTP/1.1 200 OK和Server: Apache/2.4.41 (Ubuntu)。如果看到HTTP/1.1 503 Service Unavailable,说明 Apache 进程在跑,但内部有严重错误(如模块加载失败),此时必须看error.log。
4.2 创建专属项目目录与权限配置(8分钟)
现在,我们抛弃/var/www/html,为自己创建一个安全、可控的项目空间。
创建项目目录并设置所有权:
mkdir -p /home/yourname/myproject sudo chown -R $USER:www-data /home/yourname/myproject sudo chmod -R 755 /home/yourname/myproject为什么?
chown $USER:www-data让你($USER)拥有读写权限,www-data(Apache 运行用户)拥有读取和执行(进入目录)权限。chmod 755对目录意味着:所有者可读写执行(rwx),组用户和其他用户可读可执行(r-x),但不可写。这是最小权限的黄金法则——Apache 只需要读取你的 HTML 和 PHP 文件,不需要修改它们。创建一个测试页面:
echo "<h1>Welcome to My Project on Ubuntu 20.04!</h1>" > /home/yourname/myproject/index.html为什么用
echo >而不是nano?因为nano会以你的用户身份创建文件,其默认权限是644(所有者可读写,组和其他用户只读),这完全符合要求。而touch创建的文件权限也是644,但echo >一步到位,更高效。验证目录权限:
ls -ld /home/yourname/myproject ls -l /home/yourname/myproject/index.html怎么查?
ls -ld显示目录自身权限(注意末尾的d),ls -l显示目录内文件权限。你应该看到:drwxr-xr-x 2 yourname www-data 4096 Apr 10 10:00 /home/yourname/myproject -rw-r--r-- 1 yourname www-data 48 Apr 10 10:00 /home/yourname/myproject/index.html如果
index.html的组是yourname而非www-data,说明chown没生效,需重新执行。
4.3 编写并启用虚拟主机配置(12分钟)
这是整个流程的核心,它把你的项目目录正式接入 Apache 的服务网络。
创建虚拟主机配置文件:
sudo nano /etc/apache2/sites-available/myproject.conf粘贴以下内容(请逐字复制,注意缩进和空格):
<VirtualHost *:80> ServerAdmin webmaster@localhost ServerName localhost ServerAlias 127.0.0.1 DocumentRoot /home/yourname/myproject ErrorLog ${APACHE_LOG_DIR}/myproject_error.log CustomLog ${APACHE_LOG_DIR}/myproject_access.log combined <Directory /home/yourname/myproject> Options Indexes FollowSymLinks AllowOverride None Require all granted </Directory> # 启用重写引擎(为后续 WordPress 或 Laravel 做准备) RewriteEngine On </VirtualHost>为什么这样写?
ServerName localhost和ServerAlias 127.0.0.1确保你在本地开发时,无论用http://localhost还是http://127.0.0.1都能访问到你的项目。生产环境这里会换成你的域名。ErrorLog和CustomLog使用${APACHE_LOG_DIR}变量(定义在/etc/apache2/envvars中,值为/var/log/apache2),将日志与默认日志分离,便于独立排查。<Directory>块是必须的,如前所述,它为你的项目目录开了门。RewriteEngine On是预留的,虽然现在不用,但未来配置伪静态(如 WordPress 的固定链接)时,无需再修改此文件,只需在.htaccess里写规则(前提是AllowOverride All)。
启用站点并禁用默认站:
sudo a2dissite 000-default.conf sudo a2ensite myproject.conf sudo systemctl reload apache2怎么查?
reload比restart更优雅,它向主进程发送SIGHUP信号,让 Apache 重新读取配置并平滑重启子进程,期间已有连接不会中断。执行后,立刻运行sudo apache2ctl configtest,确认输出Syntax OK。如果报错,configtest会精确指出哪一行、哪个文件出错,比如Invalid command 'RewriteEngine', perhaps misspelled or defined by a module not included in the server configuration,这就告诉你mod_rewrite没启用,需sudo a2enmod rewrite。再次本地测试:
curl -I http://localhost curl http://localhost怎么查?第一条应返回
200 OK,第二条应返回你写的<h1>页面内容。如果第一条是200但第二条是403 Forbidden,说明<Directory>块的Require all granted没生效,检查是否拼写错误(如写成Require all grant)或是否在错误的<VirtualHost>块内。
4.4 防火墙配置与外部访问验证(3分钟)
Ubuntu 20.04 的ufw是你面向世界的最后一道闸门。
查看当前防火墙状态:
sudo ufw status verbose怎么查?如果输出
Status: inactive,说明防火墙没开,你的服务器对全世界开放,极其危险。如果输出Status: active,但80/tcp和443/tcp的状态是DENY,说明流量被拦截。放行 Apache 流量:
sudo ufw allow 'Apache Full'为什么用
'Apache Full'而不是sudo ufw allow 80?Apache Full是一个预定义的应用配置文件,它不仅放行 80 端口,还放行 443(HTTPS)端口,并且会自动适配 Apache 的实际监听端口(如果你改了ports.conf,它也能感知)。sudo ufw app list可以看到所有预定义应用,包括OpenSSH,Nginx Full等。验证防火墙规则:
sudo ufw status numbered怎么查?
numbered会为每条规则编号,方便你后续用sudo ufw delete N删除特定规则。你应该看到类似:[ 1] Apache Full ALLOW IN Anywhere [ 2] Apache Full (v6) ALLOW IN Anywhere (v6)这表示 IPv4 和 IPv6 的 Apache 流量都被允许。
从另一台机器测试(可选): 在你的笔记本上,打开终端,执行
curl -I http://你的Ubuntu服务器IP。如果返回200 OK,恭喜,你的 Web 服务器已成功对外提供服务。
5. 常见问题与排查技巧实录:那些让我凌晨三点爬起来的 Bug
5.1 “It Works!” 还在,但我的页面 403 Forbidden:权限链断裂
现象:Apache 服务正常,curl http://localhost返回默认欢迎页,但访问你的myproject时返回403 Forbidden。
排查路径:
- 确认
DocumentRoot路径正确:sudo apache2ctl -S会列出所有虚拟主机及其DocumentRoot。检查输出中myproject.conf对应的路径是否与你创建的一致。 - 检查
<Directory>块是否存在且位置正确:grep -A 5 -B 5 "myproject" /etc/apache2/sites-enabled/myproject.conf。-A 5显示匹配行后5行,-B 5显示前5行,确保<Directory>块完整嵌套在<VirtualHost>内。 - 验证目录权限与所有权:
namei -l /home/yourname/myproject。namei会递归显示路径中每一级目录的权限和所有者。它会输出类似:
f: /home/yourname/myproject drwxr-xr-x root root / drwxr-xr-x root root home drwxr-xr-x yourname yourname yourname drwxr-xr-x yourname www-data myproject关键看最后一行:myproject目录的所有者是yourname,组是www-data,权限是drwxr-xr-x(即755)。如果yourname目录的组是yourname而非www-data,www-data用户就无法进入myproject,因为没有执行(x)权限。
终极解决:如果namei显示中间某一级目录(如/home/yourname)的权限是700(drwx------),这意味着只有yourname用户能进入,www-data被拒之门外。解决方案是sudo chmod 711 /home/yourname,给其他用户增加执行权限(x),使其能“穿过”该目录到达子目录。
5.2 “Internal Server Error” (500):PHP 模块加载失败的静默杀手
现象:页面返回500 Internal Server Error,error.log里没有明显错误,或者只有一行Premature end of script headers。
排查路径:
- 确认 PHP 模块已启用:
sudo a2query -m php8.0。a2query是 Ubuntu 专用的 Apache 查询工具,-m参数查询模块状态。如果输出php8.0 (disabled),说明模块没启用。 - 检查 PHP 模块文件是否存在:
ls /usr/lib/apache2/modules/libphp8.0.so。如果文件不存在,说明libapache2-mod-php8.0包没安装,需sudo apt install libapache2-mod-php8.0。 - 验证 PHP 解析是否生效:在
myproject目录下创建test.php:
echo "<?php phpinfo(); ?>" > /home/yourname/myproject/test.php然后curl http://localhost/test.php。如果返回 PHP 信息页,说明 PHP 工作正常;如果返回源码或 500 错误,则问题在模块加载。
终极解决:如果a2query显示模块已启用,但test.php仍不解析,很可能是mime_module没启用。sudo a2enmod mime,然后sudo systemctl reload apache2。mime_module负责根据文件后缀(.php)映射到正确的处理器(application/x-httpd-php),没有它,Apache 就把.php当作纯文本发送给浏览器。
5.3 “Connection Refused”:端口监听失效的三种可能
现象:curl http://localhost返回curl: (7) Failed to connect to localhost port 80: Connection refused。
排查路径:
- 确认 Apache 进程是否在监听:
sudo ss -tulpn | grep ':80'。如果无输出,说明 Apache 根本没在监听 80 端口。 - 检查
ports.conf配置:sudo nano /etc/apache2/ports.conf。确认里面有Listen 80。如果被注释掉(#Listen 80)或改成Listen 8080,Apache 就不会监听 80。 - 检查
apache2.conf是否包含ports.conf:grep -n "ports\.conf" /etc/apache2/apache2.conf。应该看到Include ports.conf这一行。如果被注释或删除,Apache 就不知道该监听哪个端口。
终极解决:如果ss命令显示apache2进程在监听127.0.0.1:80而非*:80,说明ports.conf里写了Listen 127.0.0.1:80。这会让 Apache 只接受本地回环地址的连接,外部机器无法访问。应改为Listen 80。
5.4 日志爆炸:access.log瞬间增长到 10GB 的元凶
现象:/var/log/apache2/access.log在几分钟内暴涨到数 GB,df -h显示根分区快满了。
排查路径:
- 实时监控日志增长:
sudo tail -f /var/log/apache2/access.log | wc -l。按Ctrl+C停止,看每秒新增多少行。 - 分析日志内容:
sudo tail -100 /var/log/apache2/access.log | awk '{print $1}' | sort | uniq -c | sort -nr | head -10。这条命令会统计最近 100 行日志中,访问次数最多的 10 个 IP 地址。如果某个 IP 出现几千次,极有可能是爬虫或攻击。 - 检查是否有异常 User-Agent:
sudo grep -i "sqlmap\|nmap\|masscan" /var/log/apache2/access.log。这些是常见扫描工具的特征。
终极解决:在myproject.conf的<VirtualHost>块内添加:
# 屏蔽恶意扫描 SetEnvIfNoCase User-Agent "sqlmap|nmap|masscan" bad_bot Deny from env=bad_bot然后sudo a2enmod setenvif启用setenvif模块,sudo systemctl reload apache2。这比用iptables屏蔽 IP 更轻量,且 Apache 层面即可拦截,不消耗额外系统资源。
6. 进阶衔接:从基础 Web 服务器到完整技术栈
Apache 在 Ubuntu 20.04 上的部署,从来不是终点,而是你技术栈的起点。网络热词中“apache jmeter”“apache kudu集成impala”“apache shiro框架漏洞靶场”,都指向一个事实:Apache 是那个沉默的、可靠的、可扩展的基础设施层。它像一栋大楼的地基和承重墙,上面可以盖任何风格的建筑