简介:面向银河麒麟高级服务器操作系统V10 SP3 2303的运维、安全与合规人员,这份安全三级加固手册围绕等保三级要求整理落地检查项,可用于系统上线前自查、日常基线核查和测评前整改。压缩包仅含1个PDF文件,约321KB,按安全服务、密码强度、账户锁定、系统安全、系统审计、系统设置、磁盘检查、资源分配、系统维护九个领域组织,每项多从说明、检查方法与修改建议展开,便于按条目定位配置要求并形成整改记录。已有1812人学习下载,说明其在麒麟服务器安全加固场景中具有较高参考价值。读者可据此梳理系统服务与口令策略、账户锁定、审计配置、磁盘与资源分配等常见风险点,建立可执行的核查清单,提升等保合规准备与日常运维排错效率。
1. 拿到一份等保三级加固手册,先别急着敲命令
某公司内网一批服务器要过等保三级测评,负责实施的工程师从资源包里翻出这份《银河麒麟高级服务器操作系统V10 SP3 2303安全三级加固手册》,9 个领域、每个检查点都按“说明—检查方法—修改建议”三段式写。第一反应通常是照着命令一条条敲,但真跑过一遍的人都知道,手册里最容易出事的地方不是“改什么”,而是“改完怎么退”——多数条目的还原方法只有一句话,且往往和加固方法不对称。这份资源适合正在做等保整改的运维、系统集成实施人员,以及需要给测评机构交材料的工程师;它最大的价值不是命令本身,而是把散落在系统各处的检查点串成了一条可执行的线。
2. 身份鉴别三件套:密码复杂度、过期警告和账户锁定怎么调
身份鉴别这块是测评必查项,也是加固时最容易“配了但不生效”的地方。手册把密码强度、口令过期警告、账户失败锁定分成三个独立小节,实际上它们都落在 PAM 和几个文本配置文件上,改错一个文件或者顺序放错,命令回显正常但策略不工作,属于典型的黑匣子环节。下面按小节拆,每个都给出检查、修改和验证三步。
2.1 pwquality 的四个 credit 参数:-1 到底代表什么
/etc/security/pwquality.conf里的ucredit、dcredit、ocredit、lcredit分别控制大写字母、数字、其他字符、小写字母的最少数量。这里有个反直觉点:-1不是“允许一个”,而是“至少一个”。正值表示“最多允许 N 个”,负值才表示“至少 N 个”,0 表示不限制。很多人按手册改成1,结果策略反而放宽了,测评工具一跑就露馅。
检查命令如下,如果这四个键被注释掉、值为 0 或正数,都不符合:
# 只提取未注释的四个 credit 配置行 grep -E '^(ucredit|dcredit|ocredit|lcredit)' /etc/security/pwquality.conf修改时不要直接改原行,先把旧行注释掉,再在文件末尾追加新配置。这样还原时删掉追加行、去掉注释即可,来回都可控:
# 改动前备份,带日期后缀便于回滚 cp -a /etc/security/pwquality.conf /etc/security/pwquality.conf.bak.$(date +%F) # 注释掉已有的四个 credit 配置行(保留原值便于追溯) sed -i -E 's/^(ucredit|dcredit|ocredit|lcredit)/#\1/' /etc/security/pwquality.conf # 追加等保三级要求的复杂度策略 cat >> /etc/security/pwquality.conf <<'EOF' ucredit=-1 dcredit=-1 ocredit=-1 lcredit=-1 minlen=8 EOF参数说明:minlen手册正文没单独列,但只设四个 credit 不设长度,理论上aA1!四个字符就能过,实际测评会被追问“长度策略在哪”。常见做法是minlen=8起步,同时配retry=3限制重试次数、difok=3要求新密码与旧密码至少三个字符不同。这几项在pwquality.conf里都有对应键,改法一致。
验证时用一个测试账号试改弱密码,应该被系统拒绝:
# 测试账号改弱密码,预期返回错误 echo 'Ab1!' | passwd --stdin testuser如果这里没被拒绝,先别怀疑配置文件,去看/etc/pam.d/system-auth里pam_pwquality.so这一行是不是被注释了。配置文件的策略再严,PAM 栈里没挂载这个模块,等于没开。
2.2 PASS_WARN_AGE 只管新用户,已有账户得靠 chage
手册的检查方法写了两步:grep PASS_WARN_AGE /etc/login.defs和chage -l <用户名>看警告天数。这两步对应两个不同的作用域,只做第一步是实施时最常见的漏项。
/etc/login.defs是useradd创建新用户时读取的默认模板,改它不会影响已经存在的账户。已有账户的密码策略存在/etc/shadow的第 6 字段(警告天数),必须用chage改。手册示例里PASS_WARN_AGE 30和检查项要求“7 或更长”是两个口径,前者是模板值,后者是测评底线,实际按测评要求取 7 到 30 之间。
# 查看当前模板值和某个用户的警告天数 grep -E '^PASS_WARN_AGE' /etc/login.defs chage -l alice | grep -i warn # 注释旧行并追加新值 sed -i -E 's/^PASS_WARN_AGE.*/#&/' /etc/login.defs echo 'PASS_WARN_AGE 30' >> /etc/login.defs # 批量刷新已有普通用户(uid>=1000 且 shell 不是 nologin/false) awk -F: '($3>=1000 && $7!~/nologin|false/){print $1}' /etc/passwd | while read -r u; do chage --warndays 30 "$u" done参数说明:chage --warndays只改警告天数,不动密码最大有效期。手册 2.2 节检查项里还要求“有效期 90 天以内”,那对应的是--maxdays,两个参数要分开设。chage -l输出里的“在密码过期之前警告的天数”如果从未设置过,可能为空或 0,脚本里grep匹配不到时要做容错,别直接判定为失败。
这里有个血泪经验:批量脚本别把系统账户一起刷了。uid>=1000这个条件在多数发行版上够用,但有些环境把服务账号也放在 1000 以上,跑之前先用awk打一遍名单,人工确认再执行。
2.3 faillock 的三行策略:preauth、authfail、authsucc 分别在什么时机触发
这是整份手册里最容易配错的一节。三行不是三选一,而是 PAM 认证栈的三个钩子,各管一段:
preauth:用户输入密码之前执行,负责检查该账户当前是否已被锁定;authfail:认证失败时执行,负责累加失败计数;authsucc:认证成功时执行,负责把计数清零。
deny=5是失败阈值,unlock_time=600是锁定时长(秒),even_deny_root表示 root 也纳入锁定,audit表示把事件写进审计日志。四个参数缺一个,测评口径就不完整。
# 两个 PAM 文件都要改,且都要先备份 cp -a /etc/pam.d/system-auth /etc/pam.d/system-auth.bak.$(date +%F) cp -a /etc/pam.d/password-auth /etc/pam.d/password-auth.bak.$(date +%F) # 注释已有的 pam_faillock 行,避免新旧策略叠加 sed -i -E 's/^(auth.*pam_faillock)/#\1/' /etc/pam.d/system-auth /etc/pam.d/password-auth # 在 auth 段靠前位置插入三行策略 for f in /etc/pam.d/system-auth /etc/pam.d/password-auth; do sed -i '/^auth\s\+required\s\+pam_env.so/i\ auth required pam_faillock.so preauth audit deny=5 even_deny_root unlock_time=600\n\ auth [default=die] pam_faillock.so authfail audit deny=5 even_deny_root unlock_time=600\n\ auth sufficient pam_faillock.so authsucc audit deny=5 even_deny_root unlock_time=600' "$f" done顺序是这段配置的玄学所在:preauth必须排在pam_unix.so之前,否则密码都验完了才检查锁定状态,等于没锁;authsucc用sufficient控制位,命中后直接跳过后续 auth 模块。PAM 栈不报语法错,配错位置只是静默不生效,所以改完必须实测。
# 连续输错密码触发锁定 for i in $(seq 1 5); do ssh wrongpass@127.0.0.1; done # 查看账户锁定状态 faillock --user alice # 测试完成后手动解锁 faillock --user alice --reset还有一处容易忽略:/etc/ssh/sshd_config里UsePAM必须是yes,否则 SSH 登录不走 PAM 栈,faillock 对远程登录完全无效。手册 3.1 和 3.2 两节的修改建议内容一模一样,读的时候容易以为是排版重复,实际 3.2 强调的是“SSH 方式”这条路径,落点就在UsePAM和 sshd 重启上。改完 PAM 记得systemctl restart sshd,不然老连接还是旧栈。
3. 系统安全底座:strict 模式、box 开关和 firewalld 的最小规则集
系统安全这章在手册里篇幅不长,但涉及内核参数、安全模块和防火墙三层,属于“改错一个就影响面很大”的区域。尤其是 box 状态在不同 SP 版本上读取命令不同,照着一台机器的命令去敲另一台,会得到“命令不存在”的反馈,第一次遇到很容易误判为系统损坏。
3.1 先关服务再谈加固:不必要服务的禁用与还原
手册 1.1 节列了一串不必要服务:chargen-dgram、daytime-stream、echo-stream、klogin、tcpmux-server、tftp、rsync、time-dgram等。这些大多是 inetd/xinetd 时代的老服务,现代系统上多数默认就没装,但检查动作不能省——测评看的是“你确认过”。
# 列出所有 unit 及其开机状态,过滤手册点名的服务 systemctl list-unit-files --type=service | \ grep -E 'chargen|daytime|echo|discard|klogin|tcpmux|tftp|rsync|time-' # 老系统上还在用 chkconfig 的话,用这条看运行级别状态 chkconfig --list 2>/dev/null | grep -E 'chargen|daytime|echo|tftp|rsync'禁用时优先用systemctl,chkconfig off在部分版本上只是兼容层,实际效果取决于是否还有 SysV 脚本:
# 停止并禁用,--now 表示立即停 systemctl disable --now tftp.service 2>/dev/null systemctl disable --now rsync.service 2>/dev/null # 确认状态,inactive + disabled 才算完成 systemctl is-enabled tftp.service; systemctl is-active tftp.service参数说明:disable只去掉开机自启,--now才会立即停止当前进程。只disable不stop,服务这次开机还在跑,测评扫端口照样能扫到。还原时反向操作即可:systemctl enable --now <服务名>,但如果这个服务本来就没装,enable会报 unit not found,属于正常现象,别当成加固失败。
3.2 strict 模式与 box 状态:SP3 和 SP1/SP2 的命令不一样
安全模式分两件事:security-switch管的 strict 模式,和 box 内核模块的开关状态。strict 是强制访问控制策略的总开关,box 是内核态的安全增强模块,两者独立,测评会分别看。
# 查看当前安全模式,输出 strict 为符合 security-switch --get # SP3 查看 box 状态,on 为符合 getstatus -m box # SP1/SP2 查看 box 状态,值为 1 为符合 cat /sys/kernel/security/box/status手册在这里少见的按版本分开写了:SP3 用getstatus -m box,SP1/SP2 读/sys或 grub 参数。这个差异不是文档冗余,是真实存在的命令差异,实施前先cat /etc/kylin-release确认版本,再选对应命令。
# 开启 strict 模式 security-switch --set strict # SP3 开启 box setstatus box -s enableSP1/SP2 要改 grub 参数,在security=kysec后面追加,box:
# 注意这是修改后的内核命令行片段,不是完整行 # 原:security=kysec # 改:security=kysec,box提示:直接编辑
/boot/grub2/grub.cfg是下策。这个文件是grub2-mkconfig的生成产物,任何一次内核升级都会把它重写,加固成果直接归零。正确做法是改/etc/default/grub里的GRUB_CMDLINE_LINUX,再执行grub2-mkconfig -o /boot/grub2/grub.cfg;或者用grubby --update-kernel=ALL --args="security=kysec,box"一条命令搞定。手册写的是改产物文件,因为它是给单次整改用的,不负责长期可维护性。
3.3 firewalld 的最小规则集:--permanent 和 --reload 缺一不可
手册 4.2 节的检查只有两条命令:firewall-cmd --state和firewall-cmd --list-all,修改建议是systemctl enable/restart firewalld加“提示用户手动添加规则”。这段写得像检查表,实际落地时缺了规则设计这一环,而这恰恰是防火墙加固最容易翻车的地方。
# 状态确认:active 才是运行中 systemctl status firewalld --no-pager firewall-cmd --state # 看默认 zone 和现有规则,重点关注 ports/services/rich rules 是否为空 firewall-cmd --get-default-zone firewall-cmd --list-all # 启用并设开机自启 systemctl enable --now firewalld # 最小放行:只开 SSH 和业务端口,写持久化配置 firewall-cmd --permanent --add-service=ssh firewall-cmd --permanent --add-port=8080/tcp firewall-cmd --reload # 确认持久化后的规则 firewall-cmd --list-all参数说明:--permanent写的是/etc/firewalld/zones/*.xml,不加它只改运行时内存,--reload或重启后规则消失,这是 firewalld 最经典的踩坑点。手册里--remove命令没带具体参数,实际删除必须写成--remove-port=8080/tcp或--remove-service=ssh,否则命令直接报参数错误。
还有一个顺序问题:远程 SSH 管理的机器,如果先enable firewalld再去加 ssh 放行,中间那段时间可能把自己关在门外。稳妥顺序是先--add-service=ssh --permanent,再--reload,最后才enable。或者用firewall-cmd --runtime-to-permanent把当前已经调通的运行时规则一次性固化。zone 的选择也要注意,trustedzone 等于全放通,开了防火墙但选 trusted,测评一样判不合格。
4. 审计与系统维护:audit 规则、swatch、tripwire 和资源限制
审计和系统维护这两块在手册里分布得比较散,5 章管审计软件和 audit 规则,6 到 9 章管会话超时、完整性校验、资源分配和 grub 维护模式。这些点单个看都不复杂,但都属于“装完不配等于没装、配完不持久化重启就丢”的类型,需要按可复现的路径一次性做对。
4.1 auditctl 加的规则重启就没了,必须落到 rules.d
手册 5.2 节给了两条示例规则:auditctl -w /tmp/file1 -k file和auditctl -a exit,always -F arch=b64 -S execve -F uid=0。这两条执行完立刻生效,但只存在内核内存里,systemctl restart auditd或重启系统就消失。真正的持久化位置是/etc/audit/rules.d/*.rules,由augenrules合并成/etc/audit/audit.rules。
# 临时验证用,重启失效,适合先确认规则语法和效果 auditctl -w /tmp/file1 -p wa -k file_access auditctl -a always,exit -F arch=b64 -S execve -F uid=0 -k root_exec # 持久化写法,落到 rules.d 目录 cat > /etc/audit/rules.d/99-djbh.rules <<'EOF' ## 监控 /tmp/file1 的写和属性变更,key 用于检索 -w /tmp/file1 -p wa -k file_access ## 监控 root 用户触发的 execve 系统调用,64 位表 -a always,exit -F arch=b64 -S execve -F uid=0 -k root_exec ## 锁定规则,禁止运行时用 auditctl -D 清空,测评加分项 -e 2 EOF # 合并规则并加载,然后确认 augenrules --load auditctl -l参数说明:-p wa里的w是写、a是属性修改,读和写要分开监控的话再加一行-p r。-k是检索 key,后续用ausearch -k root_exec过滤。arch=b64指 64 位系统调用表,32 位兼容层要另加arch=b32,否则跑 32 位程序时审计会漏。-e 2是锁定模式,设置后规则只能重启才能改,这正是等保三级“审计功能不可绕过”的落地手段,代价是后期调规则要安排重启窗口。
grub 里的audit=1也要确认。systemctl status auditd只说明用户态守护进程在跑,内核审计是否开启要看内核命令行:
# 确认内核带了 audit=1 grep -o 'audit=[01]' /proc/cmdline磁盘风险必须提前算:execve 全量监控在编译机或容器宿主机上一天能写几个 G。常见做法是只监控uid=0,或者加-F auid!=4294967295排除系统守护进程,同时把/etc/audit/auditd.conf里的max_log_file和num_logs调好,别等/var满了才发现。
4.2 swatch 和 tripwire:装完不初始化等于没装
swatch 是日志关键字监控工具,手册的检查是rpm -qa | grep swatch,修改建议是yum install swatch。装完还要配/etc/swatch.conf和 watch 文件,定义匹配规则和告警动作,否则它只是个躺在系统里的包,不会产生任何作用。测评看包在不在,但从运维价值角度,配好规则才有意义。
tripwire 同理。手册 7.1 节只写了“如未安装则提醒用户安装”,没给初始化步骤。tripwire 装完必须建库,否则tripwire --check直接报数据库不存在:
# 安装后初始化策略库,会交互式要求设置口令 tripwire --init # 建立首次基线 tripwire --check # 修改策略文件后重新生成并更新 tripwire --update-policy /etc/tripwire/twpol.txt参数说明:--init会读取/etc/tripwire/twpol.txt生成策略和数据库,口令用于签名,丢了很麻烦,实施时记在密码管理工具里。--check输出的是与基线的差异,首次跑完基线之后才有对比意义。数据库文件默认在/var/lib/tripwire/<主机名>.twd,这个文件不在,包装了也不算完成。
4.3 TMOUT、quota、cgroup 与 GRUB 维护模式
TMOUT 手册要求放在/etc/profile,检查项是“所有 TMOUT 行不超过 600 秒”。两个细节:一是/etc/profile只对交互式登录 shell 生效,SSH 执行单条命令不读它;二是单纯export TMOUT=600会被用户自己export TMOUT=0覆盖,安全做法加readonly。
# 放到 profile.d 下,对所有登录 shell 生效,且不可被用户覆盖 cat > /etc/profile.d/tmout.sh <<'EOF' # 无操作自动退出,readonly 防止运行期被改 TMOUT=600 readonly TMOUT export TMOUT EOF # 立即生效 source /etc/profile.d/tmout.shquota 要真正生效,光装包不够,必须改挂载参数。/etc/fstab对应的文件系统加usrquota,grpquota,重新挂载后执行quotacheck -cugm和quotaon。cgroup 在 V10 上要确认内核是 v1 还是 v2 混合模式,libcgroup是 v1 的用户态工具,v2 靠 systemd slice 管理,装不装包不影响功能,这一点测评口径和实际实现要对齐。
GRUB 维护模式的修改建议在手册里被截断了,实际做法是给启动菜单设口令,防止有人在启动时按e编辑内核参数进单用户绕过所有安全控制:
# 交互式设置 grub 口令,生成 /boot/grub2/user.cfg grub2-setpassword # 确认生成文件权限为 600 chmod 600 /boot/grub2/user.cfg /boot/grub2/grub.cfg注意:grub 口令一旦设置,忘记后只能进救援模式清除。设置前先确认有带外管理或物理接触条件,别在纯远程机器上第一次试。
5. 五条加固翻车记录:从锁死 root 到规则重启即失效
这一节记录的是实施过程中真实撞上的五类问题,每条按“现象—原因—解决”写。加固本身不难,难的是这些坑在命令回显里看不出来,往往要等测评复测或者业务报障才暴露。
5.1 给 root 开了 even_deny_root,然后手抖输了五次错密码
现象:SSH 连 root 提示认证失败,换控制台登录也提示账户锁定,等了十分钟才恢复。
原因:faillock 策略里deny=5 even_deny_root,root 同样计入失败次数,输错五次触发unlock_time=600。配置本身符合要求,但实施时没给自己留后路。
解决:本地控制台或带外管理登录,执行faillock --user root --reset清零计数。生产环境首次上策略时,我一般先不加even_deny_root,等观察一周确认没有自动化脚本用 root 反复认证,再补上。另外配置期间保留一个已登录的 root 会话不要退,这是现成的后悔药。
5.2 用 auditctl 加了规则,重启后 auditctl -l 空空如也
现象:测评前一天自测规则都在,第二天复测auditctl -l输出为空,规则全丢。
原因:auditctl直接写内核,不落盘。手册示例给的正是这种临时写法,照着敲完以为完成了。
解决:写到/etc/audit/rules.d/99-xxx.rules,执行augenrules --load,并确认systemctl is-enabled auditd是 enabled。验证时不能只看auditctl -l当前输出,要重启一次再查,或者至少systemctl restart auditd后复查。
5.3 手工编辑 grub.cfg 加 box,内核升级后被覆盖
现象:加固完成时getstatus -m box显示 on,一个月后系统打补丁重启,box 状态变回关闭。
原因:/boot/grub2/grub.cfg是grub2-mkconfig的生成产物,内核包升级会触发重新生成,手工加的,box参数被覆盖。
解决:改/etc/default/grub的GRUB_CMDLINE_LINUX再grub2-mkconfig -o,或者用grubby --update-kernel=ALL --args="security=kysec,box"。改完重启验证一次,别只信命令回显。
5.4 firewalld 规则没加 --permanent,reload 后业务端口没了
现象:业务方反馈 8080 端口不通,firewall-cmd --list-ports输出为空,但明明加过。
原因:加规则时用的是运行时的--add-port=8080/tcp,没带--permanent,后续因为改别的配置执行了--reload,运行时规则被持久化配置覆盖。
解决:所有需要长期保留的规则统一带--permanent,加完--reload再--list-all复查。已经调通的运行时规则可以用firewall-cmd --runtime-to-permanent一次性固化,比逐条补--permanent快。
5.5 TMOUT 设得太紧,夜间批处理被踢导致任务中断
现象:备份脚本跑到一半连接断开,日志停在中间某一步,第二天业务方发现数据不全。
原因:TMOUT 对交互式 shell 计时,某些通过su -或脚本包装建立的会话也被计入。批处理中间有长时间无输出的步骤,触发超时。
解决:批处理改用nohup或setsid脱离终端,脚本开头trap '' SIGHUP忽略挂断信号。TMOUT 取值按测评要求来,600 秒是底线,能设 900 就别设 300,别为了“看起来更严”把正常运维也干掉。
5.6 tripwire 装完没 init,测评时被判未落实
现象:rpm -qa | grep tripwire有输出,但测评人员要求看数据库文件时找不到。
原因:只装了包,没执行tripwire --init,/var/lib/tripwire/下没有.twd数据库。
解决:装完立刻--init建基线,口令记进密码管理工具,然后跑一次--check确认输出正常。这个顺序不能反,先 check 后 init 会直接报错。
6. 加固后的验证:一份可复跑的自检脚本和回滚习惯
加固做完不等于结束,真正省时间的是把检查项固化成可重复执行的脚本,加固前后各跑一次,对照 PASS/FAIL 变化。下面这份脚本只读不改,放在/root/audit-check.sh,每次改动配置后跑一遍,比逐条翻手册快得多。
#!/bin/bash # 等保三级加固自检脚本,只读不修改,可重复执行 pass=0; fail=0 check() { local name="$1"; local cmd="$2" if eval "$cmd" >/dev/null 2>&1; then echo "[PASS] $name"; pass=$((pass+1)) else echo "[FAIL] $name"; fail=$((fail+1)) fi } # 身份鉴别 check "pwquality 四个 credit 均为 -1" \ "grep -qE '^ucredit=-1' /etc/security/pwquality.conf && grep -qE '^lcredit=-1' /etc/security/pwquality.conf" check "PASS_WARN_AGE >= 7" \ "awk '/^PASS_WARN_AGE/{exit !(\$2>=7)}' /etc/login.defs" check "faillock deny=5" \ "grep -q 'deny=5' /etc/pam.d/system-auth" # 系统安全 check "security 模式为 strict" \ "security-switch --get | grep -q strict" check "firewalld 运行中" \ "systemctl is-active firewalld" # 审计 check "auditd 开机自启" \ "systemctl is-enabled auditd" check "审计规则非空" \ "test -n \"\$(auditctl -l 2>/dev/null)\"" # 会话与完整性 check "TMOUT 已设置且不大于 600" \ "grep -qE '^TMOUT=([1-9][0-9]{0,2})$' /etc/profile.d/tmout.sh" check "tripwire 已安装" \ "rpm -q tripwire" check "tripwire 数据库存在" \ "ls /var/lib/tripwire/*.twd >/dev/null 2>&1" echo "----- PASS=$pass FAIL=$fail -----" # 有失败项时返回非零,方便接入巡检系统 [ "$fail" -eq 0 ]脚本里eval传字符串是为了让每个检查项压成一行,可读性好,但生产环境建议改成函数数组,避免命令拼接带来的注入风险。awk那条检查PASS_WARN_AGE时用了exit !(条件)的写法,条件不满足直接以非零退出,正好对上check函数的判定逻辑。最后一行[ "$fail" -eq 0 ]让脚本在有失败项时返回非零退出码,接定时巡检时能被上层捕获。
回滚习惯比脚本更重要。我的做法是每次改动前cp -a备份带日期后缀,改动用“注释原行 + 追加新行”的方式,还原时删追加行、去注释即可,和手册每一节给的还原方法一一对应。手册的还原命令散在各章,我一般会在加固前先建一个rollback.sh,把本次要动到的每一处还原命令按相反顺序写进去,加固脚本和回滚脚本成对存放。从那以后我每次上机做加固,都强制先跑一遍备份和回滚脚本的空转测试,确认每一条cp和sed都能对上真实文件路径,再开始改第一行配置。希望帮到你。
本文还有配套的精品资源,点击获取