news 2026/10/10 19:41:02

Laravel项目部署:从Windows 10到Gitee再到服务器的完整链路

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Laravel项目部署:从Windows 10到Gitee再到服务器的完整链路

做 Laravel 项目最尴尬的一个时刻,就是本地php artisan serve跑得好好的,给同事演示也没问题,结果一到部署就卡住。代码在 Windows 10 上写好,怎么弄到服务器上?用 U 盘拷贝?用压缩包上传再解压?这些办法也不是不行,但一旦项目要更新,你就得重复上传整个文件夹,时间一长谁也受不了。更专业的做法,是让 Gitee 当中间人:本地把代码推送到 Gitee,服务器再从 Gitee 拉取代码并完成部署。这篇文章就围绕这条链路,把 Windows 10 开发环境、Laravel 框架、Gitee 仓库、服务器部署这四件事串起来讲清楚,适合项目已经在本地跑通、但第一次面对“上线”这个动作的开发者。

这个流程远没有想象的复杂。本质上就三步:本地和 Gitee 建立信任关系,把代码推上去;服务器和 Gitee 也建立信任关系,把代码拉下来;最后在服务器上补齐依赖、配置环境并让网站跑起来。真正容易出问题的,是第一遍走流程时那些不起眼的细节。比如分支名对不上、.env被提交进仓库、服务器上storage目录权限不对、Nginx 伪静态没配导致路由 404。我会把每一步的操作命令、配置文件和踩坑点都写出来,你跟着走一遍,基本能避开 90% 的部署问题。

1. 项目拆解:从 Windows 10 到服务器,Laravel 项目的完整交付链路

1.1 为什么用“本地推送、服务器拉取”这套链路

很多第一次接触部署的人会问:为什么不能直接在服务器上开发?或者为什么不用 FTP 上传代码?答案很简单——这两条路对 Laravel 这种框架项目来说,都不可持续。

直接在服务器上开发,等于放弃本地开发环境的各种便利。你在 Windows 10 上装了 IDE、调试工具、浏览器扩展,这些在服务器上统统没有。而且服务器通常是 Linux 系统,你还要额外熟悉一套环境,效率很低。用 FTP 上传则更危险,因为 Laravel 项目里有大量文件,手动上传很容易漏文件、传错目录。更重要的是,FTP 无法保留版本历史——你改坏了代码,想回滚到上一个能跑的版本,FTP 做不到。

而“本地推送 → Gitee 中转 → 服务器拉取”这套链路,本质上是把 Git 的版本管理能力延伸到了部署环节。本地提交一次,Gitee 上就多一个历史版本。服务器拉取一次,线上代码就对应一个明确的提交记录。出了问题,git log一看就知道线上跑的是哪个版本,git checkout就能回到上一个稳定版。这套流程对单人开发有效,对团队协作更是刚需——Gitee 上的代码仓库可以接入成员管理、代码审查、Issue 跟踪,这些是 FTP 和 U 盘拷贝给不了的东西。

1.2 链路中三个角色各自要做的事

这条链路里一共有三个角色:开发机、Gitee 仓库、服务器。很多人对部署的理解是“把文件放到服务器上”,其实更准确的说法是“让三个角色之间形成一套标准流程”。

角色扮演方核心任务
开发机Windows 10编写 Laravel 代码、本地调试、提交代码并推送到远程仓库
远程仓库Gitee托管代码、保存版本历史、作为开发机与服务器之间的中转分发点
服务器Linux + Nginx + PHP-FPM + MySQL拉取代码、安装依赖、配置环境变量、对外提供 Web 服务

有一点要特别说明:Laravel 项目部署比静态网页或普通 PHP 项目更繁琐,原因在于它有三个典型特征。第一,它依赖 Composer 管理外部包,代码仓库里通常不包含vendor目录,服务器拉下来之后必须先安装依赖;第二,它依赖环境变量配置数据库、缓存、应用密钥等信息,.env文件不能直接放进 Git 仓库,服务器上需要单独创建;第三,它的入口文件在public目录下,Web 服务器的根目录必须指向public,还要配好伪静态规则,才能支持 Laravel 的路由系统。把这三点理解了,后面的部署操作就有清晰的目标了。

2. 本地准备:Windows 10 下的 Git 安装、SSH 密钥与 Gitee 连接

2.1 安装 Git 并配置全局参数

Windows 10 上第一步是安装 Git。直接去 Git 官网下载 Windows 版本的安装包,安装时一路默认即可。有几个选项可以留意一下:默认编辑器建议保留 Vim 或者改成 Notepad++,不影响后面操作;PATH 环境变量选择 “Git from the command line and also from 3rd-party software” 那一项;换行符转换建议选 “Checkout as-is, commit as-is”,这个选择能减少一部分换行符问题,后面我会专门讲 CRLF 的坑。

安装完 Git 之后,打开 Git Bash,先配置身份信息。这一步很重要,因为 Git 的每一次提交都会把这两个信息写进提交记录里。如果不配置,提交时会报错或者生成一串占位信息,到后面看历史记录时非常难受。

git config --global user.name "你的名字" git config --global user.email "你的邮箱@example.com"

强烈建议这里的邮箱和你在 Gitee 注册时用的邮箱保持一致。这样你推送到 Gitee 的提交记录能直接关联到你的 Gitee 账号,团队协作时能看清谁提交了什么。配置完成后可以用git config --list检查一下,确认两个参数都写进去了。

2.2 生成 SSH 密钥并把公钥加到 Gitee

Windows 10 下连接 Gitee 有两种协议可选:HTTPS 和 SSH。HTTPS 每次推送都要输账号密码,虽然 Git 可以缓存凭证,但换机器、换用户时经常会遇到凭证冲突。SSH 则是一次配置,永久免密,并且安全性更高——它通过公钥和私钥配对的方式验证你的身份,私钥保存在本地,公钥放在 Gitee。

生成 SSH 密钥的命令是在 Git Bash 里执行:

ssh-keygen -t rsa -b 4096 -C "你的邮箱@example.com"

执行后会出现提示让你选择保存路径,直接回车用默认路径即可。默认路径是C:\Users\你的用户名\.ssh\id_rsa.pub,其中id_rsa是私钥,id_rsa.pub是公钥。再次强调:私钥绝对不能泄露、不能上传到任何地方;公钥可以分发到 Gitee 等平台。

接着查看公钥内容:

cat ~/.ssh/id_rsa.pub

输出结果是一长串以ssh-rsa开头、以你的邮箱结尾的字符串。复制它,然后打开 Gitee 网站,登录后进入 设置 → 安全设置 → SSH 公钥,把复制的内容粘贴进去,起一个容易辨识的标题,比如“Windows10-dev”,保存即可。

2.3 验证连接与常见失败处理

配置好公钥后,在 Git Bash 里执行下面的命令验证是否连通:

ssh -T git@gitee.com

第一次执行时,系统会提示无法确认 host 身份,问你是否继续连接,输入yes回车。如果配置正确,会看到类似这样的输出:

Hi 你的用户名! You've successfully authenticated, but GITEE.COM does not provide shell access.

这句提示的意思是认证成功,但 Gitee 不提供 shell 登录能力,这很正常,说明 SSH 密钥已经生效。

我遇到过不少次Permission denied (publickey)的情况,排查顺序一般是:检查公钥是否完整复制到了 Gitee;检查本机 SSH key 是否存在(ls -la ~/.ssh);确认你当前用的账号和 Gitee 上添加公钥的账号是同一个。还有一种容易被忽略的情况:如果你之前用 HTTPS 方式克隆过仓库,Git 会优先尝试 HTTPS 认证,这时需要检查仓库的 remote 地址是不是git@gitee.com开头的 SSH 格式。

3. 推送实战:创建 Gitee 仓库、配置 .gitignore 并完成首次提交

3.1 创建 Gitee 仓库时的几个关键选择

SSH 配置好之后,下一步是去 Gitee 上创建一个空仓库。进入 Gitee 首页,点“新建仓库”,会看到几个需要填的选项。

仓库名称最好和项目名一致,比如laravel-blog,方便识别。路径会自动生成,一般不用改。“是否开源”这个选项要慎重:开源仓库是所有人都能看到的,私有仓库只有你和被你添加的成员能访问。如果你的项目里含业务敏感信息,或者暂时不想公开,就选“私有”。

下面有个初始化仓库的选项,里面包含是否自动生成 README 文件。我个人建议:先不要勾选自动生成 README,也不要在 Gitee 上勾选添加 .gitignore 模板。理由很简单——如果你在 Gitee 上初始化了仓库,本地第一次推送时就会出现“两边各自有独立提交历史”的冲突。后面对新手来说处理起来很麻烦,还要先 pull 再 push。先创建空仓库,本地直接推,是最顺滑的路径。

还要留意一个设置:Gitee 创建仓库时可以选“分支模型”,默认是master还是main,不同版本界面可能不一样,记住你选的这个分支名。后面本地仓库初始化的时候,要把本地分支名改成和远程一致,否则推送时会提示分支不匹配。

3.2 Laravel 项目的 .gitignore:哪些文件绝对不能进仓库

Laravel 项目创建时,根目录下已经自带了一份.gitignore文件。这份文件的作用是告诉 Git:某些目录和文件不要纳入版本控制。你可千万别觉得没必要,这是 Laravel 项目部署中几乎最重要的防线。

至少要确认下面这些内容在.gitignore里:

  • /vendor:Composer 安装的依赖包,每个环境都可以单独执行composer install生成,不需要、也不应该进仓库
  • node_modules:同理,前端依赖,由npm install或yarn生成
  • .env:环境变量文件,包含数据库密码、APP_KEY 等敏感信息,绝不能进仓库
  • /storage/*.key:存储目录下的密钥文件
  • storage/logs/*.log:日志文件
  • .idea、.vscode:IDE 的本地配置,不同开发者配置不同,不该提交
  • .phpunit.result.cache:测试缓存

如果你发现vendor已经被提交进了仓库,不要慌,用下面的命令把它从 Git 管理中移除,但保留本地文件:

git rm -r --cached vendor git commit -m "chore: remove vendor directory from version control"

这里特别强调.env的问题。我在现实中见过不止一次,因为.env被误提交导致数据库密码、邮箱密码泄露,甚至 APP_KEY 被公开后,攻击者可以利用 Laravel 的加密机制反序列化执行恶意代码。既然项目默认的.gitignore已经把你保护好了,就不要再自己去把.env手动git add进去。

3.3 首次推送到远程仓库:完整命令流

代码准备就绪后,开始首次推送。打开 Git Bash,进入你的 Laravel 项目根目录,依次执行:

# 初始化本地仓库 git init # 统一分支名(假设远程仓库分支模型是 main) git branch -M main # 把所有文件加入暂存区 git add . # 提交 git commit -m "feat: 初始化 Laravel 项目" # 关联远程仓库(换成你自己的仓库地址) git remote add origin git@gitee.com:你的用户名/你的仓库名.git # 推送并建立上游跟踪 git push -u origin main

关于git branch -M main这一步,多解释一句。不同版本的 Git 默认分支名不一样,有的是master,有的是main,如果不统一,推送时 Git 会提示fatal: The current branch master has no upstream branch或者远程拒绝推送。先加这个参数,保证本地分支和远程仓库分支一致,后面就不纠结了。

推送成功后,打开 Gitee 仓库页面就能看到代码了。-u参数的含义是“建立上游跟踪”,意思是把本地main分支和远程main分支关联起来,之后你再执行git push或git pull,就不用再带仓库地址和分支名了。

如果第一次推送就被拒绝(rejected),大概率是远程仓库里已经有提交记录了。解决思路很简单:如果你确认远程仓库是空的或不该有的,可以把远程仓库清掉重建;如果远程仓库里确实有你需要的内容(比如同事推过代码),那就先拉取再合并:

git pull --rebase origin main git push -u origin main

4. 服务器部署:从 Gitee 拉取代码到 Nginx 站点上线

4.1 服务器环境准备:LNMP 还是宝塔面板

代码推送到 Gitee 之后,主角切换到服务器。服务器操作系统一般用 Linux,常见的有 Ubuntu、Debian、CentOS。以 Ubuntu 22.04 为例,Laravel 10 要求 PHP 版本不低于 8.1,这里我装 PHP 8.2 比较稳妥。

服务器环境的搭建有两条路线:手动搭建 LNMP(Linux + Nginx + MySQL + PHP)或者用宝塔面板这类可视化工具。两者各有优劣。宝塔面板对新手极度友好,图形界面上点一点就能装好 Nginx、PHP、MySQL,还能创建站点、管理 SSL 证书。我自己的建议是:着急上线、不想折腾环境的,用宝塔;想理解部署原理、以后好排查问题的,手动搭建。不管用哪条路线,最终服务器上要有的核心软件是固定的:

  • Nginx:Web 服务器,负责接收 HTTP 请求、转发给 PHP 处理
  • PHP 8.x + PHP-FPM:PHP 解释器和进程管理器
  • MySQL / MariaDB:数据库
  • Composer:PHP 依赖管理工具
  • Git:用于从 Gitee 拉取代码

Ubuntu 上手动安装这些软件包的命令大概是这样:

sudo apt update sudo apt install -y nginx sudo apt install -y php8.2-fpm php8.2-cli php8.2-mysql php8.2-mbstring php8.2-xml php8.2-curl php8.2-zip php8.2-bcmath php8.2-gd sudo apt install -y composer sudo apt install -y git

注意 PHP 扩展我写了一个列表,这些是 Laravel 正常运行必需的。漏装php8.2-mbstring会导致使用字符串处理时报错,漏装php8.2-xml会导致一些依赖包安装失败,漏装php8.2-zip会直接影响composer install的执行。安装完成后,用php -v验证版本,用php -m列出已加载的扩展。

4.2 在服务器上生成 SSH 密钥并从 Gitee 拉取代码

服务器上的代码来源有两种方式:SSH 方式和 HTTPS 方式。HTTPS 方式最简单,克隆无需额外配置,但之后每次git pull都可能要求输入账号密码或 Token。SSH 方式需要做一次密钥配置,但配好之后一劳永逸。

服务器上生成 SSH 密钥:

ssh-keygen -t rsa -b 4096 -C "deploy@example.com"

生成后查看公钥:

cat ~/.ssh/id_rsa.pub

把输出的公钥添加到 Gitee。这里有一个细节:不建议把服务器公钥加在“个人 SSH 公钥”列表里,更好的做法是使用 Gitee 的“部署公钥”功能。部署公钥可以绑定到指定仓库,而且可以只给只读权限,这样即使服务器被入侵,也只是能拉取这个仓库的代码,不能往别的仓库推送东西,风险可控。

配置完成后,把代码克隆到服务器。我习惯统一放在/var/www目录下:

sudo mkdir -p /var/www cd /var/www sudo git clone git@gitee.com:你的用户名/你的仓库名.git

克隆完成后,你会看到/var/www/你的仓库名这个目录。这里要立刻处理目录权限问题。PHP-FPM 默认以www-data用户运行,如果项目目录的属主是 root,PHP 就没有权限写日志、写缓存。我通常的做法是把项目目录的属主改成www-data:

sudo chown -R www-data:www-data /var/www/你的仓库名

这一步看起来不起眼,但如果不做,后面 Laravel 报“Permission denied”会让你排查很久。

4.3 安装依赖与环境配置:composer install、.env 与 key:generate

代码拉下来之后,第一件要做的事就是安装 PHP 依赖。因为 Laravel 项目的vendor目录默认不进 Git 仓库,服务器上执行:

cd /var/www/你的仓库名 sudo -u www-data composer install --no-dev --optimize-autoloader

这是手动搭建环境时比较推荐的顺序。--no-dev表示不安装开发环境依赖,线上环境用不到phpunit、barryvdh/laravel-debugbar之类的包,装上去只会拖慢应用、增加被攻击面。--optimize-autoloader会生成优化过的自动加载映射,让 Laravel 加载类更快一点。

接下来创建环境变量文件。Laravel 默认提供.env.example作为模板,直接复制:

sudo -u www-data cp .env.example .env

然后编辑.env,把关键配置改成线上环境对应的值:

APP_NAME=你的应用名 APP_ENV=production APP_DEBUG=false APP_URL=https://你的域名 DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=你的数据库名 DB_USERNAME=你的数据库用户 DB_PASSWORD=你的数据库密码

这里有一个新手很容易忽略的点:.env修改完之后,必须执行:

sudo -u www-data php artisan key:generate

这个命令会生成一个随机的 32 位字符串写入.env的APP_KEY字段。Laravel 用它做加密解密、session 签名、cookie 加密。如果APP_KEY为空,页面会直接报错No application encryption key has been specified。在本地用php artisan serve时 Laravel 会自动处理,但到服务器上手动部署,这一步必须自己执行。

如果项目有数据库迁移,可以顺便跑一下:

sudo -u www-data php artisan migrate --force

--force参数是在生产环境跳过确认提示,因为这里不带APP_ENV=production的话,migrate 会停下来问“你确定要在生产环境执行吗”。

还要建一个软链接,让public/storage能访问到storage/app/public目录:

sudo -u www-data php artisan storage:link

如果你用了 Laravel 的Storage磁盘功能上传过文件,这一步一定要做,不然前端访问上传图片会 404。

关于权限,我再补一条硬性要求:

sudo chmod -R 775 storage bootstrap/cache

storage目录要写日志、编译 Blade 模板、存 session 和缓存,bootstrap/cache要存配置文件缓存。如果这两个目录不可写,页面会白屏或报 500。

4.4 Nginx 站点配置:根目录、伪静态与 PHP-FPM

Laravel 项目跑起来,需要 Nginx 把请求交给 PHP-FPM 处理。Nginx 的站点配置文件一般放在/etc/nginx/sites-available/下,然后在/etc/nginx/sites-enabled/里建软链接启用。创建一个站点配置,比如/etc/nginx/sites-available/laravel:

server { listen 80; server_name your-domain.com; root /var/www/你的仓库名/public; index index.php; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.2-fpm.sock; } location ~ /\.(?!well-known).* { deny all; } }

逐个说明几个关键配置。

root指向的是/var/www/你的仓库名/public,而不是项目根目录。因为 Laravel 的入口文件是public/index.php,所有 HTTP 请求都必须经过这个入口处理。如果把 root 指到项目根目录,用户访问时会把.env、storage等敏感目录直接暴露出来,非常危险。

try_files $uri $uri/ /index.php?$query_string;是 Laravel 路由的伪静态规则。它的逻辑是:先尝试把请求作为真实文件返回,找不到再当作目录处理,还找不到就全部交给index.php,由 Laravel 的路由系统解析。没有这一行,你访问/about这种路由时会直接 404,因为服务器上根本没有about这个文件。

location ~ \.php$这一段把以.php结尾的请求交给 PHP-FPM 处理。这里fastcgi_pass用的是 Unix socket,具体路径要看你的 PHP 版本,Ubuntu 上 PHP 8.2 对应/run/php/php8.2-fpm.sock。如果你用的不是 Ubuntu 或者 PHP 版本不同,用php -v或systemctl status php8.2-fpm查一下路径。

配置文件写好之后,测试语法再重载:

sudo nginx -t sudo systemctl reload nginx

到这里,如果域名 DNS 解析已经指向服务器,打开浏览器访问你的域名,Laravel 网站应该就能正常显示了。

5. 上线优化:部署后的缓存刷新与日常更新流程

5.1 上线前的几个必要设置

网站能打开只是第一步,上线前还要做几个优化设置,否则后面的维护会比较折腾。

Laravel 提供了一组缓存命令,把配置、路由、视图编译成缓存文件,提高整体响应速度:

sudo -u www-data php artisan config:cache sudo -u www-data php artisan route:cache sudo -u www-data php artisan view:cache

config:cache会把所有配置文件合并成一个缓存文件,Laravel 加载配置时就不需要逐个读取.env和config目录了。route:cache同样会把路由表打包,生产环境能明显降低路由匹配耗时。需要提醒的是:执行了config:cache之后,你再修改.env文件,配置不会立即生效。此时要执行php artisan config:clear才能重新读取环境变量。这个特性很多新人不知道,容易在改完数据库密码后得到一个“数据库连接错误”的 500 页面。

再把.env里的APP_ENV=production和APP_DEBUG=false确认一遍。APP_DEBUG=true时,一旦发生异常,Laravel 会把堆栈信息、环境变量、数据库连接信息打印在页面上。这在本地开发是神器,在生产环境就是定时炸弹——任何一个报错页面都会把你的服务器底细暴露给访问者。

如果条件允许,建议顺手把 Nginx 的 80 端口重定向到 443(HTTPS)。证书可以用 Let’s Encrypt 免费申请,配置好后在.env里把APP_URL改成https://开头,同时再执行一次php artisan config:cache刷新配置。HTTPS 对加密 Cookie、登录状态保护都很重要,这个不能省。

5.2 日常更新流程:拉取、装依赖、刷新缓存

服务器上的 Laravel 项目上线之后,你还会持续提交代码。日常发布更新的标准流程,也应该形成固定套路。

本地开发机上,正常提交并推送:

git add . git commit -m "feat: 增加某功能" git push origin main

服务器上,拉取最新代码并部署:

cd /var/www/你的仓库名 sudo -u www-data git pull origin main sudo -u www-data composer install --no-dev --optimize-autoloader sudo -u www-data php artisan migrate --force sudo -u www-data php artisan config:clear sudo -u www-data php artisan route:clear sudo -u www-data php artisan view:clear sudo -u www-data php artisan config:cache sudo -u www-data php artisan route:cache sudo -u www-data php artisan view:cache

如果你没有修改数据库结构,migrate可以不执行;如果你更新的代码没有新增配置项,config:clear和后面的config:cache也可以跳过。但我的习惯是每次都执行一套完整的部署命令,因为有些第三方扩展在安装时会向config目录发布配置文件,不刷新缓存会导致新配置不生效。

注意到我用sudo -u www-data执行所有命令,而不是直接用 root 或普通用户。原因前面提过:PHP-FPM 以www-data用户运行,用它执行这些命令,生成的文件属主就是www-data,PHP 才有权限读写。如果用 root 执行composer install,生成的vendor属主是 root,PHP 访问不到,页面照样报错。

这里说一句实在话:更新时最怕的不是代码写错,而是更新流程不固定。每次更新都靠“手动拖文件”或者“只传改过的那几个文件”,迟早会漏掉东西。把所有发布动作固定成上面这一串命令,做成一个脚本或写成笔记,每次照做,线上出问题就能快速定位是哪一步出了问题。

6. 常见问题排查:本地推送、服务器拉取与部署的坑

6.1 本地到 Gitee 的典型问题

推送时报Permission denied (publickey):

这个提示说明 Git 没有找到有效的 SSH 密钥,或者 Gitee 不认可你的公钥。检查顺序是:本地~/.ssh/id_rsa.pub是否存在;Gitee 后台是否添加了正确的公钥;执行ssh -T git@gitee.com看报什么错。如果提示Host key verification failed,是因为服务器指纹未确认,重连并输入yes即可。

报failed to push some refs:

远程仓库有本地没有的提交记录。最常见的原因就是你在创建 Gitee 仓库时勾选了自动生成 README 或 .gitignore。解决方法是先拉取合并再推送:

git pull --rebase origin main git push -u origin main

--rebase会把本地的提交“接”到远程提交的后面,保持线性历史,比直接默认合并更干净。

推送时出现LF will be replaced by CRLF警告:

这是 Windows 和 Linux 换行符差异导致的。Windows 用CRLF(回车+换行),Linux 用LF(换行)。Git 默认在 Windows 上会把LF转成CRLF,这个警告大多数情况下无影响。但如果项目里有 Bash 脚本,被转换后上传到 Linux 服务器执行,会报$'\r': command not found这种错误。解决方式是在项目根目录加一个.gitattributes文件:

* text=auto eol=lf *.sh text eol=lf

这样 Git 会把文本文件统一按LF提交,服务器拉取后就不会有\r的干扰。

6.2 服务器上的典型问题

composer install报内存不足:

服务器内存太小或者 PHP 的memory_limit太小,Composer 在解析依赖时会报Allowed memory size exhausted。临时解决方式:

sudo -u www-data COMPOSER_MEMORY_LIMIT=-1 composer install --no-dev --optimize-autoloader

-1表示不限制内存。但如果项目依赖很重,建议还是给服务器加内存,或者开启 Swap,否则 composer 装一半崩了,后面全是麻烦。

git pull时提示要输入密码:

说明服务器上这个仓库是用 HTTPS 协议克隆的。改成 SSH 方式:先在服务器上生成 SSH 密钥并添加到 Gitee,然后:

sudo -u www-data git remote set-url origin git@gitee.com:你的用户名/你的仓库名.git sudo -u www-data git pull origin main

改一次之后,后续 pull 就不用输密码了。

页面报 500,但storage/logs/laravel.log里没有内容:

有一种情况很隐蔽:storage目录权限是www-data,但你执行php artisan命令时用的用户是 root,导致storage/logs/laravel.log的属主被 root 占用,PHP 写不进去,日志文件里自然啥也没有。排查时先看文件属主:

ls -la /var/www/你的仓库名/storage/logs/ sudo chown -R www-data:www-data /var/www/你的仓库名/storage sudo -u www-data php artisan config:clear

6.3 部署后页面异常的排查速查表

我把部署后最常见的几种异常现象整理成一张表,你可以对照排查:

现象可能原因排查方向
首页直接显示 500 或白屏storage 不可写、vendor 缺失、.env 未配置查看storage/logs/laravel.log,确认目录权限
子路由全部 404,首页正常Nginx 没有配伪静态检查try_files配置,reload Nginx
页面能打开,但样式和图片全丢未执行storage:link或站点根目录不对确认 public 目录配置,执行php artisan storage:link
提示No application encryption keyAPP_KEY为空执行php artisan key:generate
数据库连接失败.env中数据库配置错误或账号权限不足核对 DB_HOST、DB_DATABASE、DB_USERNAME、DB_PASSWORD
修改.env后配置不生效之前执行过config:cache执行php artisan config:clear再刷新
访问.env文件直接下载Nginx root 根目录配错确保 root 指向public目录,而不是项目根目录

排查 Laravel 页面异常的通用套路是看日志:

sudo -u www-data tail -f /var/www/你的仓库名/storage/logs/laravel.log

日志里通常直接写着异常原因,比如某个扩展缺失、某个类找不到、数据库连接失败等。我处理部署问题时,90% 的答案都在这一个文件里。剩下的 10%,才是需要去检查 Nginx 配置、PHP-FPM 状态和系统权限。

最后再分享一个我自己的习惯:每次在大改之前,先给当前能跑的配置做个备份。Nginx 配置在改之前复制成xxx.conf.bak,.env在改之前也先备份一份。这套习惯让我在维护多个 Laravel 项目时少踩了很多坑——版本回滚容易,配置回滚有时候反而急得人直冒汗。部署这件事,第一步走通之后,后面就是重复和优化,但第一步走稳了,整条链路就顺了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/10 19:40:54

JWT认证原理与Spring Boot实践:从无状态Token到安全续签方案

做了这么多年后端,API接口被人扒得一干二净的经历真不少。很多项目一开始图省事,把用户身份直接塞进Cookie里,前后端分离一搞,跨域、CSRF、服务端Session存哪这些问题全冒出来了。后来普遍转向JWT(JSON Web Token&…

作者头像 李华
网站建设 2026/10/10 19:39:41

Playwright自动化实战指南:从原理到爬虫与AI Agent集成

我拿 Playwright 写了三年自动化代码,从最早拿来爬数据,到后来整个测试团队把脚本全部迁到这套框架上,再到现在各种内部平台把 Playwright 当作执行器来用。可以说,Playwright 这个词已经不只是某个开源库的名字,它已经…

作者头像 李华
网站建设 2026/10/10 19:39:17

Text-to-CAD实战:从自然语言到参数化3D模型的完整流程

1. 为什么“text-to-cad”突然成了硬需求先别急着把它当成又一个昙花一现的AI噱头。我在制造业和设计软件领域泡了十来年,最近半年被同行问得最多的问题就是:用一句话描述一个零件,真的能直接生成可编辑的三维模型吗?先说结论&…

作者头像 李华
网站建设 2026/10/10 19:34:17

Java线程中断机制详解:interrupt()协作式设计与实践

1. 先说清楚 interrupt() 到底做了什么很多写 Java 并发代码的人,第一次见到Thread.interrupt()都会下意识以为它跟Thread.stop()一样,能够强行把一个正在运行的线程干掉。我早年也犯过这个错,线上一个任务线程卡在循环里,我调了i…

作者头像 李华
网站建设 2026/10/10 19:28:32

FlyEnv本地开发环境:按需启动省内存,多版本切换告别环境折磨

干全栈开发这些年,我最崩溃的时刻从来不是在改bug,而是在配环境。以前我的电脑上同时躺着PHPStudy、XAMPP,后来为了跑微服务又装了Docker Desktop,三个工具加起来,先不说安装目录有多乱,光是它们各自带的My…

作者头像 李华