
上周给一台测试服务器装 PostgreSQL翻了翻网上的教程要么就是针对老版本的要么就是一笔带过直接给几条命令真正操作起来总会遇到各种小问题。索性自己把整个过程重新捋了一遍从选方案到初始化再到开机自启每一步都写清楚今天就整理出来分享给大家。这篇内容主要面向需要在 Linux 服务器上从零部署 PostgreSQL 12.0 的朋友无论你是刚接触数据库的运维新手还是想自己搭一套环境做测试开发的工程师都可以照着走一遍。我会重点聊几个容易被忽略的环节比如系统依赖的取舍、编译参数的坑、初始化数据库时的编码和认证方式以及用 systemd 托管服务时那些不起眼但致命的小细节。1. 安装前的方案选型与准备工作1.1 为什么我推荐用源码编译安装PostgreSQL 在 Linux 上的安装方式其实有好几种直接用发行版的包管理器装、下载官方编译好的二进制包、用 Docker 跑容器还有就是今天我主要讲的源码编译安装。包管理器安装比如 CentOS 上的dnf install postgresql-server确实最快但版本往往偏旧而且目录结构是发行版自己定义的跟官方文档里的默认路径不一致后续排查问题或者看教程时容易对不上号。Docker 方式适合快速拉起一个测试实例但做生产部署或者需要深度定制编译参数时容器化反而多了一层隔阂。源码编译安装的好处有三个第一版本完全可控官方源码包解压之后想编译哪些模块、想启用哪些特性都是自己说了算第二安装路径清晰我可以把它规范地放到/usr/local/postgresql下整个软件体量一目了然第三编译过程会让你对 PostgreSQL 的依赖关系有更直观的理解这些知识在日后排查问题时会派上大用场。1.2 准备编译环境和依赖包我用的是 CentOS 7.9 系统其他发行版按照对应的包管理器替换一下就行。在开始编译之前先把基础工具链装上这里建议用yum install -y一次装齐避免反复补充依赖。yum install -y gcc gcc-c readline-devel zlib-devel make perl python3这几个包分别的作用我简单说一下gcc是编译 C 源码必备的编译器readline-devel提供的命令行历史回显和自动补全功能没有它编译时虽然能过但后续用psql客户端敲命令会非常难受上下翻历史都不行zlib-devel是数据压缩所需的库PostgreSQL 的备份压缩和 WAL 日志压缩都要用到它。perl和python3主要用于一些辅助脚本和扩展模块的编译检查。另外建议在编译之前确认一下系统没有安装旧版本的 PostgreSQL避免程序名冲突。可以用which psql或者ps -ef | grep postgres先看一眼如果有残留先停掉服务再继续。1.3 创建独立的运行用户与目录规划PostgreSQL 有一个很核心的安全原则绝不能用 root 用户启动数据库服务。这是官方文档里明确强调的也是我在实际运维中见过很多人忽略的细节。用 root 启动数据库一旦服务被攻击或程序本身有漏洞攻击者就相当于直接拿到了服务器的最高权限。所以安装之前先创建一个专用的系统用户useradd -r -s /bin/bash -m postgres参数说明一下-r表示创建系统用户UID 会在一个特定范围内-s /bin/bash不给它登录 shell 也不行因为后面有些管理命令需要切到这个用户身份下执行如果用nologin操作起来反而繁琐-m顺便生成 home 目录后续有些配置文件喜欢往里面放。目录规划建议如下目录用途/usr/local/postgresqlPostgreSQL 软件安装目录包括二进制文件、库文件、头文件/data/postgresql/data数据库的数据目录实际存放 WAL 日志、数据文件的地方/data/postgresql/logs日志目录建议单独分出/var/run/postgresql运行时 socket 文件目录创建好目录之后记得把属主改成 postgres 用户chown -R postgres:postgres /data/postgresql /var/run/postgresql这一步非常容易漏后面初始化数据库的时候如果发现权限报错回头检查这里大概率能找到原因。2. 源码下载与编译参数的关键取舍2.1 从官方源码库下载 PostgreSQL 12.0源码包不要随便在网上找链接下载最好从 PostgreSQL 官方站点的 ftp 镜像获取。12.0 版本在我的构建时间点是稳定版本官网提供的地址格式是https://ftp.postgresql.org/pub/source/v12.0/postgresql-12.0.tar.gz。cd /usr/local/src wget https://ftp.postgresql.org/pub/source/v12.0/postgresql-12.0.tar.gz tar -xzf postgresql-12.0.tar.gz如果网络访问官方站点较慢可以使用国内高校或云厂商的镜像源但注意校验一下下载到的文件完整性。校验方法如下md5sum postgresql-12.0.tar.gz比对官方页面提供的 md5 值是否一致这一步能避免下载损坏或不完整的问题。2.2 configure 参数里容易被忽视的选项解压之后进入源码目录接下来最为关键的就是configure这个环节。许多初学者在这里直接无脑执行./configure这样也没问题但会丢失一些有用的功能。我的建议是至少加上这几个参数./configure --prefix/usr/local/postgresql \ --with-pgport5432 \ --with-perl \ --with-python \ --with-openssl \ --with-readline \ --with-zlib \ --enable-nls每个参数的含义拆开来看--prefix指定安装路径这决定了所有二进制文件会被复制到/usr/local/postgresql/bin下后续配置环境变量就有明确依据。--with-pgport设置默认端口为 5432虽然这个参数在后续的postgresql.conf里也可以改但既然现在定了后面就少一件事。--with-perl和--with-python启用 PL/Perl 和 PL/Python 过程语言支持。如果你以后需要写数据库函数用 Python 或 Perl 实现这个选项就是必须的。反过来说不确定用不用得上也建议先编译进去因为缺了之后想补要重新编译整个软件非常费时间。--with-openssl启用 SSL 加密连接支持。生产环境强烈建议打开特别是在公网上传输数据的时候。--with-readline和--with-zlib分别对应命令行体验和压缩能力前面已经说过属于日常使用的基本配置。--enable-nls是启用国际化消息支持如果你需要看中文提示信息这个选项配合环境变量LANGzh_CN.UTF-8就能生效。不过说实话数据库报错信息我还是建议看英文原版网上搜解决方案时关键词更容易匹配。2.3 编译过程中的性能和报错处理配置完成之后就可以编译了make -j 4-j 4表示用 4 个并行任务来编译这个数字根据你机器的 CPU 核心数来定。如果是 8 核的建议-j 8能明显缩短编译时间。需要注意并行编译虽然快但如果内存不足容易导致编译过程中 OOM内存溢出这时候反而需要用make -j 2甚至单线程编译来保证稳定。编译的时间通常在几分钟到十几分钟不等取决于机器性能。期间如果报错最常见的两个原因一是缺了系统依赖此时回到 1.2 节的依赖清单逐一检查二是磁盘空间不够编译产生的中间文件可能会占到将近 2GB用df -h检查一下分区剩余空间。编译无误后执行安装make install默认情况下头文件和文档也会一并安装到 prefix 目录下。装完之后把 PostgreSQL 的 bin 目录加到 PATH 环境变量里这样后续敲psql、pg_ctl这些命令就不用写全路径了。echo export PATH/usr/local/postgresql/bin:$PATH /etc/profile source /etc/profile3. 数据库初始化与基础配置3.1 环境变量与软链接的细节处理环境变量除了 PATH还有一个关键的变量叫LD_LIBRARY_PATH。PostgreSQL 的库文件默认安装在/usr/local/postgresql/lib下如果不把它加到共享库搜索路径里启动服务时可能报错说找不到libpq.so.5之类的库文件。echo export LD_LIBRARY_PATH/usr/local/postgresql/lib:$LD_LIBRARY_PATH /etc/profile source /etc/profile我见过不少同事在这里栽过跟头编译装都装好了结果pg_ctl start时提示找不到共享库排查了半天最后就是环境变量的问题。再一个容易忽略的点是psql默认连接的 socket 目录。PostgreSQL 默认 Unix socket 目录是/var/run/postgresql或者编译时指定的--with-socket-dir。如果这个目录不存在后面本地连接会失败。建议提前建好mkdir -p /var/run/postgresql chown postgres:postgres /var/run/postgresql3.2 initdb 初始化数据目录的核心参数数据目录初始化这一环节初学者最容易一头雾水。核心命令是su - postgres -c /usr/local/postgresql/bin/initdb -D /data/postgresql/data -E UTF8 --localeen_US.UTF-8 -U postgres参数逐个拆解-D指定数据目录的位置注意这个目录必须为空而且属主必须是 postgres 用户否则 initdb 会拒绝执行。-E UTF8设置数据库集群默认的字符编码为 UTF8。这个几乎可以说是唯一选择现在很少有场景还去用 LATIN1 或者其他编码。--localeen_US.UTF-8指定区域设置。locale影响字符串排序、日期格式化等一系列行为。这一步非常关键如果设置不当后面ORDER BY中文字段时会出现排序不符合预期的诡异问题。-U postgres指定超级用户的名称。默认情况下超级用户是当前执行 initdb 的用户这里显式指定可以规避后面习惯性用 postgres 账号登录却密码无论如何都认证失败的尴尬。initdb 执行完成后数据目录下会生成一组核心文件。说几个关键文件postgresql.conf是主配置文件pg_hba.conf是客户端认证配置文件PG_VERSION记录了数据库版本号base/、global/是实际存放数据库对象的目录pg_wal/存放 WAL 预写日志。3.3 为什么 PostgreSQL 12 不需要单独执行 CREATE DATABASE很多第一次接触 PostgreSQL 的人会有个疑惑MySQL 装完会有个初始化数据库的环节PostgreSQL 怎么没看到类似的操作其实 initdb 已经顺手创建了三个默认数据库postgres、template0和template1。template1是用户后续创建数据库时默认使用的模板也就是说你CREATE DATABASE example时实际上是把 template1 克隆了一份。template0是原始模板不能被修改即使你搞坏了 template1也有个干净来源可以恢复。postgres相当于一个普通的初始数据库方便客户端连接后执行首次操作。所以装好之后直接用psql -U postgres -d postgres就能连进去不需要做什么额外初始化。4. 用 systemd 管理 PostgreSQL 服务4.1 编写规范的服务管理脚本PostgreSQL 的官方二进制包没有自带 systemd 服务脚本需要我们自己编写。虽然也可以用pg_ctl start手动启动但生产环境强烈建议托管给 systemd这样可以获得崩溃后自动重启、开机自启、统一日志管理等一系列能力。在/etc/systemd/system/postgresql.service中写入如下内容[Unit] DescriptionPostgreSQL 12.0 database server Afternetwork.target [Service] Typeforking Userpostgres Grouppostgres EnvironmentPGDATA/data/postgresql/data EnvironmentPGLOG/data/postgresql/logs/postgresql.log ExecStart/usr/local/postgresql/bin/pg_ctl start -D ${PGDATA} -l ${PGLOG} ExecStop/usr/local/postgresql/bin/pg_ctl stop -D ${PGDATA} -m fast ExecReload/usr/local/postgresql/bin/pg_ctl reload -D ${PGDATA} TimeoutSec300 Restarton-failure [Install] WantedBymulti-user.target这里解释几个关键点TypeforkingPostgreSQL 的pg_ctl start会 fork 一个主进程后退出所以必须用 forking 类型systemd 才能正确跟踪服务状态。EnvironmentPGDATA...通过环境变量传入数据目录后面 ExecStart 里可以引用这样将来目录变化时只需改一处。Restarton-failure当服务异常退出时自动拉起这是生产环境的刚需配置。-m fast是停止模式的设置在 ExecStop 里。PostgreSQL 支持三种停止方式smart等待所有连接断开后才停止fast立即中断连接并做安全检查点后停止immediate直接强停相当于掉电。建议用fast兼顾数据安全和响应速度。4.2 日志输出路径与轮转思路上面脚本里我特意指定了PGLOG/data/postgresql/logs/postgresql.log把服务日志输出到一个固定文件里。现实中很多教程只写pg_ctl start -D xxx不指定日志文件结果日志全部输出到终端关闭终端服务就断了——这个坑非常经典systemd 脚本里如果漏了-l参数同样的问题也会发生。因为它会导致标准输出没有重定向systemd 会认为进程没有正常启动或记录不了日志。日志轮转建议用两个方案的组合方案。PostgreSQL 内置的log_rotation_age和log_rotation_size参数可以按时间和大小自动切分日志文件再加系统级的 logrotate 来做按天压缩归档/var/log/postgresql/postgresql.log { daily rotate 30 compress delaycompress missingok notifempty copytruncate }其中copytruncate参数很重要因为 PostgreSQL 持有文件的写句柄直接mv文件会导致服务写入到已经被移动的旧句柄上日志就丢了。copytruncate 会先复制再清空原文件规避这个问题。4.3 开机自启与字段的含义服务脚本写好后依次执行systemctl daemon-reload systemctl start postgresql systemctl enable postgresql systemctl status postgresqldaemon-reload必不可少systemd 只有在重载之后才会识别新增或修改过的服务单元文件。enable是设置开机自启它的本质是在/etc/systemd/system/multi-user.target.wants/下创建一个软链接指向这个服务单元文件。查看状态时如果出现active (running)就说明一切正常如果失败可以用journalctl -u postgresql查看详细日志这个命令定位启动问题非常高效。5. 认证策略与核心参数调优5.1 pg_hba.conf 的认证配置原则安装好之后默认的pg_hba.conf配置相对保守默认只允许本地 socket 连接。这个文件是所有客户端连接数据库的准入控制名单它的规则是从上到下匹配匹配到第一条就生效。生产环境推荐的配置模板如下# 本地管理员用 scp 拷贝数据时可以使用 peer 认证 local all postgres peer # 本地其他用户用 md5/scram 认证 local all all scram-sha-256 # 内网 IP 段允许访问具体网段按实际填写 host all all 192.168.1.0/24 scram-sha-256 # 禁止外网直接访问示例按需调整 host all all 0.0.0.0/0 reject关于认证方式要特别强调一下PostgreSQL 12 中默认的密码加密方式是md5但从安全角度考虑推荐改成scram-sha-256这是目前 PostgreSQL 支持的最强密码认证协议。如果客户端驱动比较老只支持 md5两者可以并存不影响。但是绝对不建议在生产环境使用trust认证它意味着任何能连上服务器的客户端都可以免密以任意用户身份登录数据库等于把数据库完全暴露了。5.2 postgresql.conf 中必调的十余个参数修改完认证配置接下来要调整postgresql.conf。文件路径在数据目录下用文本编辑器打开后逐个检查以下参数参数名推荐值说明listen_addresses*或具体 IP默认值是localhost只允许本机连接需要外网访问必须修改port5432默认端口如果被占用再改max_connections100或按业务评估每个连接都会占用缓存和内存不宜盲目调大shared_buffers物理内存的 25%PostgreSQL 共享缓存区太大会导致系统内存被耗尽effective_cache_size物理内存的 50%~75%不是实际分配内存是告知规划器系统可用缓存容量work_mem4MB起步每个排序或哈希操作的内存上限过高会吃爆内存maintenance_work_mem64MB以上用于 VACUUM、CREATE INDEX 等维护操作wal_buffers16MBWAL 日志内存缓冲区checkpoint_completion_target0.9控制检查点刷盘时间降低 IO 峰值random_page_cost1.1SSD或4.0机械盘SSD 时代机械硬盘默认值不再适用max_wal_size2GBWAL 日志最大值影响故障恢复时间和磁盘占用min_wal_size80MBWAL 日志最小保留值每个参数都有其存在的意义我挑三个最容易出问题的详细说shared_buffers不是越大越好。它占用的内存在 PostgreSQL 内部是共享内存段过大可能导致 MySQL 和 PostgreSQL 同时在一台机器上跑时直接内存不足触发系统 OOM Killer。安全的原则是先 25%观察内存余量再微调。max_connections每增加一个连接PostgreSQL 就会为它分配若干内存在进程栈和work_mem相关结构上。当连接数达到几百上千时内存消耗量非常惊人。如果业务上确实需要大量并发连接优先考虑部署 PgBouncer 等连接池中间件而不是盲目加大这个参数。random_page_cost是个有意思的参数它告诉查询优化器磁盘随机读取比顺序读取慢多少倍。传统机械硬盘这个值默认 4.0但 SSD 的随机读取性能大幅提升把值调整到 1.1~1.3 能让查询优化器更愿意采用索引扫描而不是顺序扫描某些慢查询性能可以直接受益。5.3 防火墙与 SELinux 的策略放行这是 Linux 系统部署数据库时绕不开的一道坎。即使 PostgreSQL 配置完全正确如果防火墙拦截或 SELinux 策略不允许外部客户端一样连不上。CentOS 7 上确认防火墙状态并放行端口firewall-cmd --permanent --add-port5432/tcp firewall-cmd --reload如果 SELinux 处于 enforcing 状态需要给 PostgreSQL 端口打上正确的安全上下文标识semanage port -a -t postgresql_port_t -p tcp 5432这两步做完外部连接请求才能顺利到达 PostgreSQL 服务进程。很多教程完全不提这些导致许多人排查了一整天却发现是系统安全策略挡住了一切。6. 启动验证与周边运维工具6.1 本地连接验证与版本确认服务启动后第一步在服务器本地验证数据库能正常响应su - postgres -c /usr/local/postgresql/bin/psql -p 5432 -U postgres -d postgres -c SELECT version();如果能输出 PostgreSQL 12.0 的版本信息说明整个安装部署链路已经打通。接着验证数据库列表SELECT datname FROM pg_database;这里的pg_database是系统目录表存储了所有数据库的信息。我们前面提到的postgres、template0、template1应该都能查出来。6.2 远程连接测试的完整链路远程连接测试要在另一台机器上执行不要直接在数据库服务器上自己测自己。用本机或者另一台有psql客户端的机器psql -h 数据库服务器IP -p 5432 -U postgres -d postgres执行后会提示输入密码这时输入你在 initdb 之后设置的密码。如果连接成功说明从网络层、防火墙、SELinux、认证策略到服务本身的整条链路全部畅通。如果连不上按以下顺序排查ping 数据库服务器IP看网络是否通telnet 数据库服务器IP 5432看端口是否可达检查 PostgreSQL 日志常见报错如password authentication failed密码错误、no pg_hba.conf entry for host认证规则未放行、Connection refused服务未启动或端口错误6.3 创建业务账号与测试库的规范姿势部署完成后通常需要创建一个专用的业务账号和对应的数据库而不是都用超级用户 postgres 来操作。这既是安全习惯也是规范要求。su - postgres -c /usr/local/postgresql/bin/psql -d postgres进入 psql shell 后执行CREATE USER app_user WITH PASSWORD StrongPassw0rd; CREATE DATABASE app_db OWNER app_user ENCODING UTF8; GRANT ALL PRIVILEGES ON DATABASE app_db TO app_user;CREATE USER和CREATE ROLE本质上一样唯一区别是 USER 默认具备 LOGIN 权限。设置密码要满足一定复杂度避免使用常见弱口令。ENCODING UTF8再次显式声明编码防止某些机器上默认 template1 编码不同导致新库编码异常。6.4 基本的日常巡检命令与压测规范部署完成后推荐在服务器上配置一个日常巡检脚本定期检查数据库的基本健康状况。# 检查数据库连接数占用 SELECT count(*) FROM pg_stat_activity; # 查看数据库大小 SELECT pg_database_size(postgres)/1024/1024 AS size_mb; # 查看表大小 SELECT pg_size_pretty(pg_total_relation_size(table_name)); # 查看当前运行的SQL SELECT pid, state, query, now()-query_start AS duration FROM pg_stat_activity;这些查询都是基于统计视图不会给数据库带来负载。如果做性能验证建议用pgbench这是 PostgreSQL 官方自带的基准测试工具pgbench -i -s 10 -U postgres postgres pgbench -c 20 -j 4 -T 60 -U postgres postgres-c 20表示模拟 20 个并发客户端-j 4使用 4 个线程-T 60持续测 60 秒。测试的结果会报告 TPS每秒事务数和平均延迟可以作为调整配置参数的参考基线。7. 部署中常见的坑与排查思路7.1 启动失败日志权限与目录所有权问题上次我在新服务器上部署时systemctl start postgresql后状态一直不变成 runningjournalctl -u postgresql只看到一行很笼统的could not open log file。细查之后发现 logs 目录是我在 root 用户下mkdir创建的属主没有改成 postgres。这个问题很好解决chown -R postgres:postgres /data/postgresql/logs systemctl restart postgresql这类问题其实是最常见的部署坑根源只有一个数据库进程运行在 postgres 用户下它没有权限写 root 创建的文件。7.2 pg_ctl 进程残留导致端口冲突另一种常见情况是启动时报could not bind to 5432端口被占用。排查手段如下ss -tlnp | grep 5432很可能是之前你用 root 手动执行过pg_ctl start进程还在后台跑着只是你忘记了。这时候找到 PID用kill通知关闭或者让它自然运行然后用新的 systemd 脚本托管即可。注意不要用kill -9强杀 PostgreSQL 主进程除非万不得已否则可能造成数据目录状态不一致甚至无法恢复。7.3 认证失败scram 与 md5 的兼容问题有一次远程客户端连接时报password authentication failed但密码明明是对的最后发现问题出在认证方式上。服务端 pg_hba.conf 配置的是scram-sha-256而客户端驱动版本太老只支持 md5 认证两边的认证机制对不上。解决办法有两个方向一是升级客户端驱动到支持 scram 的版本二是临时在服务端放宽认证方式用md5配合修改密码策略。从安全角度我建议优先升级客户端毕竟 md5 强度不如 scram。不过当时情况紧急我先临时把 pg_hba.conf 里该条目的认证方式改成了md5然后systemctl reload postgresql但它本质上是即时的不会中断现有连接。连接不中断这个问题要注意然后等客户端升级后再切回 scram。7.4 慢查询并非配置问题而是统计信息缺失建完库导完数据后发现一些查询异常缓慢排查执行计划发现走了顺序扫描即使有索引也不走。核心原因就是表数据量增长后没有更新统计信息查询规划器缺乏足够数据做出优化决策。执行VACUUM ANALYZE;问题能够得到大幅改善。这个操作建议做成周期性任务每天深夜执行一次全库 VACUUM ANALYZE周一对大表单独做一次REINDEX。8. 备份策略与延伸建议8.1 逻辑备份与物理备份的适用场景部署往往只是开始一个真正可用的数据库系统还必须配套备份方案。PostgreSQL 提供两大备份类手段基于pg_dump的逻辑备份与基于连续归档和 WAL 归档的物理备份。逻辑备份适合中小数据量、跨版本迁移、单表或单库恢复场景pg_dump -h 127.0.0.1 -U postgres -d app_db -F c -f /backup/app_db.dump-F c表示自定义压缩格式后续恢复时用pg_restore选择性恢复单个表或某个 schema非常灵活。但它的弱点是恢复时需要回放全部数据大数据量下比较慢。物理备份适合海量数据场景直接使用pg_basebackup做基础备份配合 WAL 连续归档实现任意时间点恢复PITR。生产环境通常是两者结合每天逻辑备份留档每周物理备份打底WAL 每小时归档。8.2 从 12.0 升级到新版本的思路预览虽然本文讲的是 12.0 的部署但如今 PostgreSQL 已经发布到更高版本我也把从 12.0 升级的常用路径简单说一下。升级有两种主流方式pg_upgrade原地升级和逻辑迁移。pg_upgrade需要新版本可执行文件然后执行命令pg_upgrade -b /usr/local/pgsql12/bin -B /usr/local/pgsql16/bin -d /data/pg12/data -D /data/pg16/data -U postgres命令执行前要保证新旧两个版本的二进制已安装并停服且新数据目录已经初始化。升级过程会比较路径、兼容性、用户定义对象等一系列内容一旦报错也能定位。不过因为 12.0 和之后版本之间的大版本跃迁跨度不小建议先在测试环境完整演练一遍再上生产。逻辑迁移则是使用pg_dump导出后再pg_restore导入到新版本虽然速度慢一些但对兼容性要求低适合数据量不是特别大的环境。8.3 个人维护习惯从装好那一刻就养成的好习惯最后分享几个我长期维护 PostgreSQL 环境养成的小习惯都是直接用得上的安装完立刻给 postgres 超级用户设置一个高强度密码而不是依赖 peer 认证裸奔。每次修改postgresql.conf前先备份一份快照版本改完确认无误再删。把log_min_duration_statement设置为1000超过 1 秒的 SQL 都会记录到日志中这是排查慢查询的第一手线索。有条件就开archive_modeon即使暂时没有完整的归档脚本也要把开关和环境准备好免得以后想开的时候要重启数据库。建议用第三方的 PostgreSQL 集群管理方案但前提是先把单机部署和运维做扎实否则复杂度叠加上去会非常痛苦。说到底PostgreSQL 的安装部署在 Linux 平台上本身并不算难真正考验人的是装好之后怎么理解它、运维它、保护它。希望这篇从源码编译到 systemd 托管再到认证配置的完整记录能帮你少走几步弯路把这套流程跑得明明白白。