资讯动态

Linux小组实战周报:Shell脚本、Git协作与权限进程管理复盘

发布时间:2026/10/16 2:06:44 来源:尧图企业网站定制
XiyouLinux Group 的第一期周报整理出来了。说它是周报不如说是一群常年混迹终端的人每周固定做的一次复盘这周实际学了什么、踩了哪些坑、下一周又准备把哪条技术路线往前推一截。Linux 学习最怕只看不练尤其是几个人各自埋头折腾的时候很容易陷入收藏大量教程却迟迟没有产出的状态。周报在这里起到的作用是一种温和但有效的约束把零散的知识变成一条可追踪的进度线。这一期覆盖的方向是 Shell 脚本自动化、Git 多人协作、文件权限与进程管理最后附带一份常见问题排查记录。无论你是刚开始接触 Linux、准备加入一个开源社区还是正在带自己的技术小组这份周报里既有可以直接抄作业的脚本也有我们反复踩过坑之后总结出的步骤。1. 周报的初衷与整体运营思路1.1 为什么一个Linux小组需要周报这个得从我们小组的实际场景说起。组里十来个人水平参差不齐有人已经开始折腾内核模块有人还在纠结 vim 怎么退出。如果没有一个统一的信息同步机制每周例会基本就是少数人发言、多数人旁听散会之后各自行动学什么、学到什么程度完全不清楚。周报的价值在这里就体现出来了。它是一种异步沟通不需要所有人同时在线把每周的学习进度、踩坑经历、问题总结写下来周五统一提交周末由轮值成员整理汇总再同步到小组仓库。经过这样一轮沉淀每个人的努力都被量化看得见、可追溯也方便后来的人直接检索这些历史记录。我见过很多类似的组织最后周报都流于形式原因是把周报写成了“本周我学了 xx 命令”这种流水账。要避免这种情况最好的办法是在周报模板里强制设置三个栏目本周完成的具体任务、遇到的问题和排查过程、下周计划。流水账填不满这三个栏目的字数自然就被过滤掉了。1.2 周报的内容结构与节奏安排我们目前采用的是一周一期的固定节奏结构上分成四块本周任务进展每个人正在推进的技术方向与完成度学习笔记与实操记录本周学到的关键知识点要求配实际命令或代码问题与解决记录踩坑过程哪怕问题最后没解决也要写出来下周计划明确下一周要推进的目标这个结构看起来简单实际运营起来有几个细节需要注意。首先轮值整理人不能只做内容的搬运工而是要把相似主题合并把有价值的命令、脚本补充注释再检查有没有明显错误。整理的过程本身就强迫你把别人写的东西读一遍很多理解不到位的细节会在这一步暴露出来。其次周报发布后要留出讨论窗口尤其是“问题与解决”部分。没有解决完的问题会在下一次周会前被单独拎出来讨论避免“报备了就等于解决了”的错误心态。节奏上我们固定每周五晚上截止提交周日晚上发布整理版。这个时间点卡得很重要太早提交会压缩周四周五的学习时间太晚发布又会撞上下一周的开始大家没有时间消化。1.3 让周报真正产生复利的一些经验周报坚持写了半年之后我才真正意识到它最大的价值不是记录而是可检索。小组仓库里的周报文件夹已经积累了三十多份文档里面有各种各样的 shell 脚本、网络排查过程、编译错误解决方案。新人加入小组的适应期因此被大大缩短很多问题不用再问第二遍直接搜索历史周报就有答案。要做到这一点光有文本还不够我们给周报文件夹维护了一个简单的索引文件 README.md每条记录包含日期、主题分类、关键词、涉及成员四个字段。搜索的时候直接用 grep 或者进仓库全局搜索效率非常高。注意周报不是日记不需要事无巨细地记录日常操作。记录那些“别人可能也会遇到”的问题才是周报能产生复利的前提。这个经验我觉得是很多技术小组可以立刻参考的先跑起来哪怕是手写 Markdown 也没关系坚持三个月之后再回头看仓库本身就是一个知识库。2. 本周技术主题Shell 脚本自动化实践2.1 为什么Shell脚本是Linux小组的必修课这一周分享的主题是 Shell 脚本自动化。为什么选这个因为它是投入产出比最高的 Linux 技能。你不需要理解内核调度不需要背系统调用的参数只要掌握变量、循环、条件判断和几个核心命令的组合就能把重复性的手工操作变成一条命令搞定的事。举个最简单的例子我们小组每周都要在服务器上部署一次最新的网站代码。在还没有脚本化的阶段每个人都要手动执行同样的操作先备份旧目录再解压新包改配置文件最后重启服务。一套流程下来至少十五分钟一个人做还行全组轮着来就很容易出错。用脚本把这些步骤固化之后部署变成了一行命令。既省时间又避免了因为某个人忘了备份造成的回滚困难。更进一步脚本写好后可以被审查和测试这比依赖于某个人的“手感”要可靠得多。Shell 脚本在这类场景里就是自动化的最小单元不值得花大力气上一套配置管理系统之前脚本往往是最务实的起点。2.2 一个可直接抄作业的日志清理脚本这周 A 同学提交了一个日志自动清理脚本很好地演示了 Shell 脚本的典型写法。场景是这样的服务器上的应用会持续写入日志文件如果不做处理磁盘很快会被占满导致服务异常。常规做法有两种一是在应用层配置日志轮转二是用脚本定期清理过期日志。A 同学写的是第二种方案脚本本身不长但覆盖了几个重要知识点#!/bin/bash # description: 清理指定目录下超过7天的日志文件 # usage: ./clean_old_logs.sh /var/log/myapp LOG_DIR${1:-/var/log/myapp} RETENTION_DAYS7 if [ ! -d $LOG_DIR ]; then echo [ERROR] Directory $LOG_DIR does not exist. exit 1 fi find $LOG_DIR -type f -name *.log -mtime $RETENTION_DAYS -delete echo [INFO] Cleaned log files older than ${RETENTION_DAYS} days in $LOG_DIR这段脚本里有几个细节值得展开说。第一${1:-/var/log/myapp}是参数的默认值写法如果不传参数就使用默认目录。这样脚本既可以被直接调用也可以配合定时任务使用灵活性高。第二find命令的-delete参数直接完成删除操作看起来简洁但也意味着如果路径写错了会直接删掉不该删的文件。所以脚本里先判断目录是否存在属于必要的前置保护。第三真正执行删除之前建议先去掉-delete换成-print跑一遍确认列出的文件确实都是过期日志再重新加上删除参数。这一步在我的经验里非常重要尤其是脚本要接到crontab里无人值守执行的时候任何疏漏都会被无限放大。2.3 易踩的坑文件名空格与换行问题A 同学的脚本提交之后我们在审查时发现了一个隐藏问题这里必须重点讲一下。问题是这样的如果日志目录下有文件名包含空格比如app 2024-01.log那么普通的for file in $(find ...)写法会把文件名按空格拆分成多个词导致后续操作失败或误操作。这是新手写 Shell 脚本最容易踩的坑之一。从表面看命令执行没有报错但实际处理的文件已经变了。正确做法是使用find的-exec或者-print0配合xargs -0让文件名以空字符作为分隔符而不是空格或换行。以清理脚本为例更稳妥的实现是find $LOG_DIR -type f -name *.log -mtime $RETENTION_DAYS -print0 | xargs -0 -r rm -f-r参数表示如果输入为空就不执行rm避免在没有匹配文件时报错。使用-print0/-0的意义在于空字符是文件名中不允许出现的字符所以用空字符做分隔符天然安全。还有一个相关的坑是find -delete在某些情况下比xargs rm更安全因为它不会调用外部进程也不受文件名换行问题影响。但-delete不支持用-printf输出预览所以调试阶段我一般用-print确认无误后再改-delete。提示如果在脚本里对文件列表做了循环处理涉及批量操作时优先考虑find -exec或while IFS read -r的写法不要直接对$(find ...)的结果做for循环。2.4 把脚本接到定时任务里脚本写完只是第一步真正让它发挥作用的是配合 crontab 自动执行。我们在服务器上为清理脚本配置了每天凌晨 3 点执行的定时任务。crontab -e在打开的编辑器里添加一行0 3 * * * /home/group/scripts/clean_old_logs.sh /var/log/myapp /tmp/clean_logs.log 21这里有几个新手很容易踩的坑。第一crontab 里执行的脚本必须写绝对路径因为定时任务环境默认的 PATH 非常精简脚本内部如果依赖某些自定义命令很有可能执行时找不到。第二要在脚本内部尽可能用绝对路径或者显式声明 PATH避免命令找不到这种很难排查的诡异问题。第三标准输出和错误输出最好重定向到日志文件否则脚本执行报错时你根本不知道它是否运行成功。配置完成后先手动执行一遍脚本确认输出正常再观察一两天定时执行的真实日志。这个验证步骤不能跳过我至少遇到过两次定时任务没生效原因分别是脚本权限不对和 crontab 里的时间格式写错。排查方式非常简单查看日志文件有没有记录、执行crontab -l确认任务列表。遇到这类问题别急着怀疑系统异常先看自己写的那几行配置。3. 本周协作复盘Git 分支管理与冲突解决3.1 为什么会频繁遇到 Git 冲突本周小组在做一个模拟项目X的官网开发基础是 Git 仓库开发方式是从主分支拉取功能分支完成后合并回主干。按理说这是个标准的流程但实际运行一周后发现几乎每天都有成员报告“冲突了不会解决”。冲突的本质是两个人修改了同一个文件的同一段区域Git 不知道怎么把两个版本自动合并。很多人以为冲突是 Git 的问题实际上 Git 的行为恰恰是合理的它在不确定哪个改变是对的的时候拒绝猜测把决定权交还给人类。避免冲突最好的方法是小步提交、频繁合并只在自己负责的模块里改动并且每次提交前先git pull --rebase同步远端最新状态。但实践里总会有人疏忽所以学会处理冲突依然是每个成员的必修课。冲突本身不可怕可怕的是在不知道冲突内容的情况下乱改文件。3.2 一次典型的冲突排查全过程这周 B 同学和 C 同学同时修改了项目的配置文件config.ini一个人改了数据库连接串另一个人改了缓存路径结果在合并时发生了冲突。我们完整走了一遍排查和解决流程过程很有代表性。首先C 同学在合并分支时收到了提示CONFLICT (content): Merge conflict in config.ini Automatic merge failed; fix conflicts and then commit the result.这个时候第一反应不是慌而是先看状态。执行git status会清楚地看到哪些文件处于both modified状态这就是冲突文件。接着查看文件内容冲突段落会被特殊标记包围形式是这样的database_url mysql://user:passlocalhost/app HEAD cache_path /var/cache/app cache_path /opt/app/cache feature-cache HEAD到之间是当前分支的内容到之间是另一个分支的内容。解决冲突的实质就是决定保留哪一边或者手动编辑成两边都包含的正确配置。在这个例子里两个修改其实不矛盾所以保留两行不同的配置即可删掉标记符号保存文件。最后执行git add config.ini并提交冲突就解决了。整个过程最重要的是提交之前用git diff --check确认没有遗留的冲突标记防止某个残留在代码里造成破坏。这类残留问题比冲突本身更隐蔽因为它不一定会立刻报错直到运行到那一行才暴露。3.3 值得长期坚持的 Git 协作习惯经过这次冲突我在周报里给小组强调了几个协作习惯这些习惯看起来琐碎实际上能大幅减少冲突概率和解决成本。第一提交信息一定要写清楚。理想的格式是“类型 简短描述”比如fix: 修正配置缓存路径。好的提交信息不仅方便别人审查也决定了日后git log的可读性。我们至少因为提交信息不清晰在合并时多花过十分钟去猜某个提交的意图。第二功能分支尽量短命。分支创建后尽快完成任务、合并、删除避免长期不合并的分支变成“死亡分支”。分支活得越久与主干之间的差异越大冲突的几率和复杂度都会显著上升。第三遇到解决不了的冲突时及时寻求帮助或直接用git merge --abort回到冲突前状态不要在同一天反复尝试五次。强制自己停下来有时比硬碰硬更高效。这个经验是小组用一次不愉快的通宵换来的希望后来的人不用再经历一遍。3.4 代码审查时我们重点关注什么这周的小组作业里有一条提交引起了大家的讨论它在解决配置冲突后顺手把另一个文件里的两处空行删掉了。虽然功能上没有影响但这类无关改动在审查时非常不受欢迎因为它会让差异变得模糊掩盖真正重要的逻辑变化。我们在代码审查时统一了一个标准一次提交只做一件事。如果是修 bug就只修 bug如果是增加新功能就只增加新功能格式化、重构、调整目录结构这些改动要单独提交。这样可以保证git log的历史干净出问题的时候也方便用git revert精准回退。另一个关注点是配置文件中的敏感信息。开发环境里出现密码、密钥这类内容时即使只存在于本地提交也可能随着分支推送进入远端仓库。我们采取的措施是第一时间修改凭据然后更新.gitignore把配置模板化。这些经验看起来不直接属于 Linux 命令但它们是多人协作项目能长期健康运转的基础。4. 本周学习笔记文件权限与进程管理4.1 文件权限的本质与 umask 的作用这一周的入门组内容回到了最基础但也最容易被忽视的文件权限。很多人在 Linux 上操作文件时只关心自己能不能读写等到部署项目才发现权限问题无处不在脚本无法执行、日志无法写入、服务无法启动。Linux 的权限模型可以概括为三个角色属主、属组、其他人和三种操作读、写、执行。这本身不难理解难的是与umask的配合。umask决定新建文件默认权限的上限它表示的是“要屏蔽掉的权限”而不是“要赋予的权限”。比如默认umask 022的情况下新建文件权限是 644目录权限是 755。因为普通文件默认不应该带上执行位所以文件的起始值是 666减去 umask 中对应的写权限得到 644目录的起始值是 777减去 022得到 755。理解了这一点就能解释很多“诡异”现象为什么用脚本创建的文件有时不可执行为什么在一个目录下新创建的文件却不能被同组的人修改。前者大概率是 umask 包含了 111后者大概率是目录的组写权限缺失。4.2 实操让部署脚本变得可执行这周 D 同学把一个部署脚本从 Windows 传输到服务器后发现一直报“权限不足”第一反应是给脚本加权限chmod 777。这个操作能解决问题但属于最不推荐的做法。我们现场演示了一遍正确流程先用ls -l deploy.sh查看当前权限再用file deploy.sh检查文件类型。结果发现问题不只是权限脚本是 CRLF 换行格式bash 解释执行时会在行尾多出一个回车符导致报错。这个坑非常典型Windows 上写脚本然后传服务器是最容易遇到的。处理方式是先转换换行符sed -i s/\r$// deploy.sh然后给脚本加执行权限chmod 755 deploy.sh755的含义是属主具备读写执行权限属组和其他人只有读和执行权限。对部署脚本来说执行权限通常是必要的但没必要给到777。给脚本赋予过多权限反而可能成为安全隐患尤其当服务器上还有其他成员时。权限管理有一个基本原则只给完成任务所需的最小权限而不是图方便把门全部敞开。4.3 为什么说 kill -9 要慎用另一个被反复提起的话题是进程管理。小组在实验环境里模拟过服务卡死的情况很多人的第一反应是kill -9强制杀死进程但这是最粗暴也最危险的方式。kill -9发给进程的是 SIGKILL 信号这个信号不能被捕获也不能被忽略内核会直接终止进程。问题在于进程没有机会做清理工作保存中的数据可能丢失、临时文件可能残留、依赖这个进程的其他服务会突然失去连接。数据库或者消息队列这类有状态服务被 kill -9 后甚至可能发生数据不一致。规范的流程是先尝试kill pid发送默认的 SIGTERM 信号给进程一个优雅退出的机会。如果进程还活着再考虑升级手段比如kill -1重新读取配置、kill -2模拟 CtrlC 中断最后才是kill -9。我在实际维护服务时坚持一个原则能不用 -9 就不用 -9除非进程已经处于无法响应且确认无状态的情况下。这个原则帮我们避免过至少两次数据丢失的严重事故值得写进小组的运维手册里。很多人对信号的印象停留在“杀进程”上其实不同信号代表的含义和进程的配合程度完全不同。4.4 实操演示用 ps 和 top 排查 CPU 异常周报的记录部分D 同学分享了一个完整的 CPU 异常排查过程。场景是测试环境里某个服务占用 CPU 接近 100%导致整个实例响应变慢。排查第一步是确认哪个进程在消耗 CPU使用top然后按 CPU 排序直接就能看到异常进程的 PID。第二步是需要进一步定位到线程和业务逻辑这是新手最容易卡住的地方。过程中用到的命令值得记录一下ps -L -p pid -o pid,tid,pcpu,comm可以列出进程内所有线程的 CPU 占用情况找出最耗费 CPU 的线程号。然后把这个线程号转换成十六进制用线程栈工具去查看该线程正在执行的代码位置。整个排查链路就是进程 → 线程 → 代码栈 → 业务代码。这种排查方式不只适用于特定语言的服务任何多线程程序都可以用类似思路定位。核心方法论是“先找到热点线程再通过线程栈找到问题代码”比盲目地看日志、重启服务有效得多。日志当然要看但 CPU 异常这类问题日志往往没有直接线索进程和线程的实时状态才是第一手现场。5. 本周问题速查表与排查思路为了让大家在遇到类似问题时能快速对照我把这周讨论过的问题整理成了一张速查表可以收藏起来。问题现象排查方向常用工具 / 命令SSH 连接慢等待十几秒才提示输入密码服务端是否开启 DNS 反向解析查看/etc/ssh/sshd_config的UseDNS磁盘写入报空间不足df -h却显示有大量空闲是否有进程持有已删除的文件lsof L1查找被占用的已删除文件本地与远端文件同步耗时严重使用增量同步替代全量打包传输rsync -avz --progress脚本执行报奇怪的格式错误检查换行符是否为 CRLFfile 脚本文件必要时sed -i s/\r$//crontab 任务没有按预期执行检查绝对路径、权限、重定向日志crontab -l查看对应日志文件5.1 SSH 连接慢的原因与解决这周不止一位成员反映同一台服务器连接速度时快时慢等待十几秒才能出现密码输入提示。这个问题在内网环境里出现得比较多排查下来发现大部分原因是 SSH 服务端默认开启了 DNS 反向解析。原因在于OpenSSH 的UseDNS参数默认是开启的客户端连接时服务端会尝试把客户端的 IP 反查成主机名。在 DNS 解析较慢的网络环境里这个反查过程会大大拖慢连接速度。提示在确认测试环境安全的前提下把/etc/ssh/sshd_config里的UseDNS设为no重启sshd服务连接速度基本会恢复到秒开。这个问题的排查思路比答案更有价值遇到“延迟类”网络问题先看服务端有没有做额外的解析或校验而不是直接怀疑带宽。很多“慢”的场景都是这种非业务逻辑造成的找到原理以后解决起来非常快。5.2 文件系统报满但 df 却显示空闲另一个真实发生过的问题应用写入文件时报磁盘空间不足但执行df -h显示磁盘还有大量空闲。让人摸不着头脑其实原因是文件已被删除但仍被进程持有。表象是磁盘一直在增长实际是某个进程打开了已被删除的日志文件删除操作只是把文件名从目录里解除了链接文件内容仍然被持有它的进程占用直到进程关闭才算真正释放。磁盘空间显示的大小是统计目录里的文件而这个“幽灵文件”已经不在任何目录里但占用的块还没有归还。排查命令是lsof L1它会列出所有处于“已删除但仍被打开”状态的文件找到对应的进程 PID重启或让该进程重新打开文件磁盘空间就会被真正释放。这类问题在服务器日志轮转配置不当时非常常见记录在周报里可以防止后续的人重复踩坑。5.3 本地与远端文件同步的可靠做法写完周报后要让成员之间共享文件有人问能不能用打包压缩的方式每次传全量。答案是可以但效率太低而且全量压缩传输在小带宽场景下非常浪费时间。可靠做法是用rsync做增量同步。只需要一行命令rsync -avz --progress ./local_dir/ userhost:/remote_dir/-a是归档模式保留权限、时间戳等信息-v输出过程-z开启压缩。增量同步的原理是 rsync 只传输文件中有变化的部分而不是整个文件重新传。提示在rsync对大量小文件比如源码目录同步时第一次会稍慢后续同步速度会快很多这也是它适合日常协作的重要原因。6. 写在后面给想组织周报的人一些建议如果你也在带一个技术小组或者想让自己单打独斗式的学习更有章法我的建议是从明天就开始写周报。不用准备什么复杂的基础设施一个目录加一个 Markdown 文件就足够了。先坚持一个月不要因为某一周内容少就中断哪怕只有三行也值得写上。我们小组坚持下来之后最大的收获反而不是技术本身而是每个成员养成了“做完一件事之后回头看一眼到底是怎么完成的”的习惯。最后再分享一个实际运营中的小技巧周报发布时在文档末尾附上“本周最值得讨论的一个问题”。这个问题往往不是最难的技术问题而是那些大家讨论过却没有定论的权衡。把它单独列出来下一周例会直接从这个问题开始比每次从“大家有什么问题吗”的沉默开场要高效得多。Linux 学习是一场漫长的修行一个人可以走得快但一群人一起复盘、一起踩坑、一起把经验沉淀下来真的可以走得更远。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑