躬行笔记 - 运维知识
type: channel
link: https://fuzhoupyy.work/index.php/category/yw/
items: 别再瞎折腾了！这些Web渗透靶场让你从菜鸟变大神
items: 告别curl！这个命令行工具让API调试变得超简单
items: 全面掌控Windows服务器安全：审计策略配置与日志管理完全指南
items: 运维老司机必备！5个Python脚本让你的工作效率翻倍
items: 告别命令行配置地狱！这个可视化反向代理神器让运维工作轻松10倍
items: Windows服务器出问题？别慌！教你几招日志排查绝技，让故障无处遁形
items: Jenkins 从0基础到有点基础——如何安装
items: 网络攻击套路大揭秘！这些年我见过的各种"妖魔鬼怪"
items: Python sh库：让运维脚本告别subprocess的痛苦，一行代码搞定系统命令
items: 从JumpServer安装脚本看Shell编程：一个运维人员的实战解析

别再瞎折腾了！这些Web渗透靶场让你从菜鸟变大神
type: item
date: 2025-11-16T13:56:28+00:00
description: 最近有朋友问我，想学Web渗透测试但不知道从哪里下手，网上的教程看了一堆，理论倒是懂了不少，可一到实际操作就抓瞎。说实话，这种情况我见得太多了，就像学游泳一样，光看视频是永远学不会的，必须得下水扑腾几下才行。Web渗透测试这个领域，实践比理论重要得多。你可以把SQL注入的原理背得滚瓜烂熟，但如果没有在真实环境中操作过，遇到实际情况还是会懵圈。这时候靶场就显得特别重要了，它们提供了一个安全的练习环境，让你可以放心大胆地去"搞破坏"。我自己这些年也折腾过不少靶场，有些确实不错，有些就比较坑了。今天就跟大家分享一下我用过的那些靶场，包括详细的搭建过程，希望能帮到想入门或者提升技能的朋友们。DVWA - 我的启蒙老师说到Web渗透靶场，DVWA（Damn Vulnerable Web Application）绝对是绕不开的。这个靶场我第一次接触是在大学时期，当时对网络安全一窍不通，就是觉得黑客很酷想学学。DVWA最大的优点就是简单直接，而且搭建起来也不复杂。它把常见的Web漏洞都集中在一个应用里，包括SQL注入、XSS、CSRF、文件上传漏洞等等。更贴心的是，每个漏洞都有四个难度级别：Low、Medium、High和Impossible。DVWA搭建教程搭建DVWA有好几种方式，我推荐用Docker，简单粗暴。方法一：Docker部署（推荐）# 拉取镜像 docker pull vulnerables/web-dvwa # 运行容器 docker run --rm -it -p 80:80 vulnerables/web-dvwa就这么简单，打开浏览器访问http://localhost就能看到DVWA了。默认用户名是admin，密码是password。点击create database，创建靶场方法二：传统部署如果你不想用Docker，也可以手动搭建：先准备LAMP环境（Linux + Apache + MySQL + PHP）从GitHub下载DVWA源码：git clone https://github.com/digininja/DVWA.git把代码放到Apache的web目录下修改配置文件config/config.inc.php.dist，重命名为config.inc.php创建数据库，访问setup页面初始化说实话，第二种方法比较麻烦，特别是在Windows上搭建，各种环境问题能把人搞疯。我当年就是这么过来的，踩了无数坑。我记得当时第一次成功执行SQL注入的时候，那种兴奋感真的无法形容。在Low级别下，你甚至可以直接在输入框里输入1' or '1'='1这种最基础的payload就能成功，虽然现在看来很幼稚，但对新手来说这种成就感是很重要的。WebGoat - 教学式的好帮手WebGoat是OWASP项目下的一个靶场，说实话刚开始我对它印象一般，觉得太"教学化"了。但后来发现，正是这种教学化的设计让它变得很有价值。WebGoat搭建过程WebGoat基于Java开发，搭建相对简单：方法一：直接运行JAR包# 下载最新版本的jar包 wget https://github.com/WebGoat/WebGoat/releases/download/v8.2.2/webgoat-server-8.2.2.jar # 运行 java -jar webgoat-server-8.2.2.jar --server.port=8080访问http://localhost:8080/WebGoat就可以了，需要先注册一个账号。方法二：Docker部署docker run -p 8080:8080 -t webgoat/goatandwolf这个镜像同时包含了WebGoat和WebWolf，WebWolf是一个辅助工具，可以帮你接收邮件、查看请求等。这个靶场最大的特点就是每个漏洞都有详细的说明和提示，就像有个老师在旁边指导你一样。比如在练习SQL注入的时候，它会告诉你应该关注哪些地方，可能的注入点在哪里，甚至会给出一些提示让你思考。我特别喜欢WebGoat的一点是它会跟踪你的学习进度，完成一个挑战后会有明确的反馈。这种游戏化的设计让学习过程不那么枯燥。bWAPP - 漏洞的百科全书bWAPP（buggy Web Application）这个靶场我是在工作后才接触到的，当时公司要做安全培训，同事推荐的。这个靶场最大的特点就是漏洞种类多，号称包含了100多种Web漏洞。bWAPP搭建指南bWAPP基于PHP开发，搭建过程：使用Docker（最简单）docker run -d -p 80:80 raesene/bwapp手动搭建下载源码：git clone https://github.com/ethicalhack3r/bWAPP.git…

告别curl！这个命令行工具让API调试变得超简单
type: item
date: 2025-11-11T14:58:32+00:00
description: 最近在调试接口的时候，突然想起来之前一个粉丝朋友推荐过的工具——HTTPie。说实话，当时我还挺不以为然的（再次感谢粉丝大哥的分享），毕竟curl用了这么多年，已经形成肌肉记忆了。但是前几天遇到一个复杂的POST请求，需要传JSON数据还要带各种header，curl命令写得我头都大了，这才想起来试试HTTPie。不试不知道，一试吓一跳！这玩意儿确实比curl好用太多了。今天就来跟大家分享一下我这段时间使用HTTPie的心得体验。什么是HTTPie官方文档地址：https://httpie.io/docs/desktopHTTPie是一个用Python写的命令行HTTP客户端，专门用来测试、调试和与HTTP服务器交互。它的设计理念就是简单易用，语法直观，输出美观。相比curl那一堆参数，HTTPie的语法更接近自然语言。我记得第一次用curl的时候，光是记住那些参数就花了好长时间。-X指定方法，-H添加header，-d传数据...每次都要翻文档。HTTPie就不一样了，基本上看一眼就能明白什么意思。安装HTTPie安装过程很简单，支持多种方式：# 使用pip安装 pip install httpie # macOS用户可以用brew brew install httpie # Ubuntu/Debian sudo apt install httpie # CentOS/RHEL sudo yum install httpie我一般习惯用apt装，因为可以装到最新版本。装完之后就可以用http命令了，注意不是httpie。基本语法和使用HTTPie的基本语法格式是这样的：http [方法] URL [项目]最简单的GET请求：http httpbin.org/get就这么简单！不需要指定GET方法，因为默认就是GET。输出结果还是彩色的，JSON格式也会自动美化，看起来特别舒服。如果要发POST请求：http POST httpbin.org/post name=张三 age:=25注意这里的语法，name=张三表示发送表单数据，age:=25表示发送JSON数据（注意冒号）。这比curl的-d参数直观多了。处理不同类型的数据JSON数据发送JSON数据超级简单：http POST api.example.com/users name=john email=john@example.com age:=30 active:=true这会自动生成JSON格式：{ "name": "john", "email": "john@example.com", "age": 30, "active": true }如果你已经有现成的JSON文件，也可以直接读取：http POST api.example.com/users < user.json表单数据发送表单数据用等号：http --form POST httpbin.org/post name=张三 password=123456或者简写：http -f POST httpbin.org/post name=张三 password=123456文件上传上传文件也很方便：http --form POST httpbin.org/post file@/path/to/file.txt我之前用curl上传文件，总是记不住那个-F参数的格式，HTTPie这种方式就很直观。设置请求头添加请求头用冒号：http GET api.example.com/data Authorization:"Bearer token123" Content-Type:application/json常用的认证方式HTTPie也有简化写法：# Basic认证 http -a username:password GET api.example.com/protected # Bearer token http GET api.example.com/data Authorization:"Bearer $(cat token.txt)"我经常需要调试需要认证的API，这个功能真的很实用。会话管理HTTPie有个很棒的功能叫会话（Session），可以在多个请求之间保持状态。比如登录后的cookie、认证信息等。创建一个会话：http --session=mysession POST api.example.com/login username=admin password=secret然后在后续请求中使用这个会话：http --session=mysession GET api.example.com/profile这样就不用每次都重新输入认证信息了。会话文件默认保存在~/.httpie/sessions/目录下。输出…

全面掌控Windows服务器安全：审计策略配置与日志管理完全指南
type: item
date: 2025-11-10T14:43:35+00:00
description: 最近客户又出了安全事故，一些服务器上一些数据文件莫名丢失。说实话，做了这么多年运维，每次出事故都是这样，平时不重视，出了问题就开始各种要求。今天就跟大家聊聊Windows Server安全加固中的审计配置，这个话题可能有点枯燥，但真的很重要。我记得去年有个朋友的公司被黑了，事后调查发现连基本的登录审计都没开，想查都查不到什么有用信息，最后只能重装系统了事。基础审计策略配置Windows Server的审计策略分为两个层面：本地安全策略和组策略。对于单台服务器，我们可以通过本地安全策略来配置；如果是域环境，建议通过组策略统一管理。打开本地安全策略的方法很简单，运行secpol.msc就行了。在安全设置下面有个本地策略，里面就是审计策略。不过这里有个坑，Windows Server 2008以后的版本，微软把审计策略分成了基本审计和高级审计两套体系。基本审计策略比较粗糙，只有9个大类：审计账户登录事件审计账户管理审计目录服务访问审计登录事件审计对象访问审计策略更改审计特权使用审计进程跟踪审计系统事件这些看起来挺全面，但实际使用中你会发现粒度太粗了。比如说账户管理，它包括了用户创建、删除、密码修改等等操作，你没法单独控制某一种操作的审计。开启审计功能第一步：在运行或者CMD中输入gpedit.msc第二步：在组策略中定位到日志策略第三步：开启全部审计日志开启审计功能结束配置审计空间第一步：在运行/CMD窗口中输入compmgmt.msc打开计算机管理第二步：如图打开属性界面（理论上应用/系统和安全模块都需要配置，这里以安全为例子）第三步：配置空间大小，根据C盘来，可以先配置1GB。如果这篇文章对你有帮助，别忘了点赞转发支持一下！想了解更多运维实战经验和技术干货，记得关注微信公众号@运维躬行录，领取学习大礼包！！！我会持续分享更多接地气的运维知识和踩坑经验。让我们一起在运维这条路上互相学习，共同进步！公众号：运维躬行录个人博客：躬行笔记

运维老司机必备！5个Python脚本让你的工作效率翻倍
type: item
date: 2025-11-02T15:20:27+00:00
description: 最近在整理自己的脚本库，发现这些年积累下来的Python脚本真是不少。想起刚入行那会儿，每天都在重复做一些机械性的工作，后来慢慢学会了用Python来解决这些问题，工作效率确实提升了不少。今天就分享5个我平时用得最多的Python运维脚本，都是在Debian 13环境下测试过的，基本上覆盖了日常运维工作的方方面面。这些脚本不算复杂，但真的很实用，希望能帮到正在做运维的朋友们。1. 系统资源监控脚本这个脚本我几乎每天都在用，可以实时监控CPU、内存、磁盘使用情况。比那些复杂的监控系统轻量多了，而且可以根据自己的需求随时调整。#!/usr/bin/env python3 import psutil import time import datetime def get_system_info(): # CPU使用率 cpu_percent = psutil.cpu_percent(interval=1) # 内存信息 memory = psutil.virtual_memory() memory_percent = memory.percent memory_used = round(memory.used / 1024 / 1024 / 1024, 2) memory_total = round(memory.total / 1024 / 1024 / 1024, 2) # 磁盘信息 disk = psutil.disk_usage('/') disk_percent = round((disk.used / disk.total) * 100, 2) disk_used = round(disk.used / 1024 / 1024 / 1024, 2) disk_total = round(disk.total / 1024 / 1024 / 1024, 2) # 网络IO net_io = psutil.net_io_counters() return { 'timestamp': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'cpu_percent': cpu_percent, 'memory_percent': memory_percent, 'memory_used': memory_used, 'memory_total': memory_total, 'disk_percent': disk_percent, 'disk_used': disk_used, 'disk_total': disk_total, 'bytes_sent': round(net_io.bytes_sent / 1024 / 1024, 2), 'bytes_recv': round(net_io.bytes_recv / 1024 / 1024, 2) } def monitor_system(): while True: info = get_system_info() print(f"[{info['timestamp']}]") print(f"CPU使用率: {info['cpu_percent']}%") print(f"内存使用: {info['memory_used']}GB/{info['memory_total']}GB ({info['memory_percent']}%)") print(f"磁盘使用: {info['disk_used']}GB/{info['disk_total']}GB ({info['disk_percent']}%)") print(f"网络IO: 发送 {info['bytes_sent']}MB, 接收 {info['bytes_recv']}MB") print("-" * 50) # 如果资源使用率过高，可以在这里添加告警逻辑 if info['cpu_percent'] > 80 or info['memory_percent'] > 85: print("⚠️ 警告：系统资源使用率过高！") time.sleep(10) if __name__ == "__main__": monitor_system()这个脚本的好处是可以持续监控，而且输出格式比较清晰。我一般会在服务器上后台运行，然后把输出重定向到日志文件里。2. 批量服务器SSH连接检测管理多台服务器的时候，经常需要检查哪些机器能正常SSH连接。手动一台台去ping太麻烦了，这个脚本可以批量检测。#!/usr/bin/env python3 import paramiko import threading import queue import time …

告别命令行配置地狱！这个可视化反向代理神器让运维工作轻松10倍
type: item
date: 2025-10-30T15:27:56+00:00
description: 最近在公司搭建测试环境的时候，又遇到了老问题——需要给十几个不同的服务配置反向代理。按照以前的做法，就是在nginx配置文件里一个个写server块，改完还得测试语法，重载服务...光是想想就头疼。正好前段时间在GitHub上看到了Nginx Proxy Manager这个项目，说是可以通过Web界面管理nginx反向代理配置。我想着反正也要重新搭环境，不如试试这个工具到底好不好用。用了一段时间后，我只能说——真香！今天就来跟大家分享一下这个让我彻底告别nginx配置文件的神器。什么是Nginx Proxy Manager官网地址：https://nginxproxymanager.com/简单来说，Nginx Proxy Manager就是给nginx套了个漂亮的Web管理界面。你不用再去编辑那些复杂的配置文件，所有的反向代理、SSL证书、访问控制都可以在浏览器里点点鼠标就搞定。这个项目是基于nginx的，但是把所有复杂的配置都封装起来了。你只需要在Web界面里填写源地址、目标地址，它就会自动生成对应的nginx配置。而且还支持自动申请Let's Encrypt证书，这个功能真的太实用了。我记得以前每次配置SSL证书都要折腾半天，现在点几下鼠标就能搞定，效率提升不是一点半点。在Debian 13上安装部署我这次用的是Debian 13系统，整个安装过程还算顺利。不过中间也踩了几个坑，一会儿会详细说。准备工作首先确保系统是最新的：sudo apt update && sudo apt upgrade -y然后安装Docker和Docker Compose，因为Nginx Proxy Manager官方推荐用Docker部署：# 安装必要的包 sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release -y # 添加Docker官方GPG密钥 curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg # 添加Docker仓库 echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # 安装Docker sudo apt update sudo apt install docker-ce docker-ce-cli containerd.io -y # 安装Docker Compose sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose安装完成后记得把当前用户加到docker组里，这样就不用每次都sudo了：sudo usermod -aG docker $USER这里需要重新登录一下才能生效。创建Docker Compose配置我在/opt目录下创建了一个专门的文件夹来存放配置：sudo mkdir -p /opt/nginx-proxy-manager cd /opt/nginx-proxy-manager然后创建docker-compose.yml文件：cat <<eof>docker-compose.yml services: app: image: 'jc21/nginx-proxy-manager:latest' restart: unless-stopped ports: - '80:80' - '81:81' - '443:443' volumes: - ./data:/data - ./letsencrypt:/etc/letsencrypt eof这个配置文件里有几个要注意的地方。端口81是管理界面的端口，80和443是实际提供服务的端口。数据库我用的是MariaDB，密码什么的在生产环境记得改成复杂一点的。启动服务配置文件准备好后就可以启动了：sudo …

Windows服务器出问题？别慌！教你几招日志排查绝技，让故障无处遁形
type: item
date: 2025-10-29T14:14:22+00:00
description: 最近客户遇到windows服务器出问题了一时半会不知道怎么办？出问题最好的办法就是看日志，但是我平常分享的都是linux系统的排查，今天就来盘盘windows服务器的！我记得刚入行那会儿，遇到服务器问题就是一顿乱操作，重启、重装，能折腾的都折腾一遍（重启能解决90%的问题）。后来被师傅骂了好几次才明白，日志才是解决问题的关键。今天就跟大家分享一下Windows Server环境下如何查看和排查日志，这些都是我这些年踩坑总结出来的经验。事件查看器 - 你的第一站Windows的事件查看器就像是服务器的"黑匣子"，记录着系统运行的方方面面。打开方式很简单，Win+R输入eventvwr.msc就行，或者在服务器管理器里也能找到。进去之后你会看到左边有个树状结构，主要分为几个大类：Windows日志这块是重点关注的地方。应用程序日志记录的是各种软件的运行情况，我经常在这里找到数据库连接失败、Web服务异常之类的问题。系统日志更多是硬件和系统级别的事件，比如磁盘错误、内存问题等等。安全日志这个就比较有意思了，记录着登录失败、权限变更这些敏感操作。有一次我们服务器被人暴力破解密码，就是通过安全日志发现的，里面密密麻麻全是登录失败的记录，IP地址还都是国外的。应用程序和服务日志这里面的内容就更丰富了，各种角色和功能都有自己的日志。比如你装了IIS，就会有IIS相关的日志；装了SQL Server，也会有对应的日志分类。看日志的时候要注意几个关键信息：时间、事件ID、来源、级别。级别分为信息、警告、错误、严重错误几种，一般我们重点关注警告和错误级别的事件。事件ID这个东西特别有用，每种错误都有固定的ID，你可以直接拿这个ID去微软官网搜索，基本都能找到详细的解释和解决方案。比如事件ID 1074表示系统重启，6005表示事件日志服务启动，这些都是有规律可循的。还可以通过事件id来查日志信息：Windows 服务器常见事件 ID 列表类别事件 ID描述系统事件1系统时间已更改 6系统启动 7系统关闭 12操作系统启动 13操作系统关闭 41系统崩溃重启 1074系统关机/重启安全事件4624账户成功登录 4625账户登录失败 4634账户注销 4648显式凭据登录 4672使用特权登录 4720创建用户账户 4724重置密码尝试 4725禁用用户账户 4728将成员添加到安全组 4732将成员添加到本地安全组 4740用户账户被锁定 4776域控制器尝试验证账户凭据应用程序事件1000应用程序错误 1001Windows 错误报告 1002应用程序挂起 1005应用程序终止服务事件7000服务无法启动 7009服务超时 7022服务正常启动 7023服务异常终止 7024服务无法启动 7031服务尝试重启 7034服务意外终止 7035服务发送控制 7036服务状态改变Active Directory 事件1644目录服务无法分配相对标识符 2886目录服务暂停 2887目录服务已恢复 5137目录服务对象创建 5141目录服务对象删除DNS 服务器事件4013DNS 服务器启动 4015DNS 服务器暂停 6702DNS 事件文件复制服务13508文件复制服务无法与主域控制器建立会话 13509文件复制服务成功与主域控制器建立会话磁盘和存储事件51磁盘错误 55文件系统结构损坏 7设备驱动程序错误PowerShell - 命令行的威力虽然图形界面看起来直观，但有时候用PowerShell查日志效率更高，特别是需要筛选大量数据的时候。Get-EventLog这个命令是基础中的基础：Get-EventLog -LogName System -Newest 100这样就能看到系统日志的最新100条记录。如果你想看特定时间段的日志：Get-EventLog -LogName Application -After "2024-01-01" -Before "2024-01-02"更强大的是Get-WinEvent命令，功能比Get-EventLog丰富多了：Get-WinEvent -FilterHashtable @{LogName='System'; Level=2,3}这里Level=2表示错误，Level=3表示警告，这样就只显示有问题的事件，不用在一堆信息级别的日志里翻来翻去。有时候我需要查找包含特定关键词的日志：Get-WinEvent -FilterHashtable @{LogName='Application'} | Where-Object {$_.Message -like "*SQL*"}这样就能找到所有消息中包含"SQL"的事件，对于定位特定应用的问题很有帮助。IIS日志 - Web服务的秘密如果你的服务器跑着Web服务（一…

Jenkins 从0基础到有点基础——如何安装
type: item
date: 2025-10-26T14:55:01+00:00
description: CICD是什么CI/CD这个词听起来很高大上，其实说白了就是让代码从开发到上线这个过程变得自动化。CI是Continuous Integration的缩写，中文叫持续集成。简单理解就是，开发人员每次提交代码后，系统会自动把所有人的代码合并在一起，然后跑一遍测试，看看有没有冲突或者bug。就像搭积木一样，每加一块都要检查一下整体结构是不是还稳固。CD有两个意思，一个是Continuous Delivery（持续交付），另一个是Continuous Deployment（持续部署）。持续交付是说代码随时都处于可发布状态，就像工厂流水线上的产品，每个环节都质检过了，随时可以出厂。持续部署更进一步，直接自动发布到生产环境，完全不需要人工干预。举个例子，以前我们部署一个网站，可能需要手动上传文件、重启服务、清缓存等等，一套流程下来半小时，还容易出错。有了CI/CD之后，开发人员只要把代码推送到Git仓库，剩下的事情全部自动完成：自动测试、自动打包、自动部署、自动重启服务，几分钟就搞定了。CI/CD的核心思想就是"小步快跑，快速反馈"。与其攒一堆功能一次性发布（风险大），不如每个小功能都快速上线，出问题也能快速定位和修复。这样既提高了开发效率，又降低了上线风险，是现代软件开发的标配。为什么选择Jenkins官方文档：https://www.jenkins.io/zh/doc/book/installing/说实话，CI/CD工具现在选择挺多的，GitLab CI、GitHub Actions、Azure DevOps什么的都不错。但是我最终还是选择了Jenkins，主要原因有几个：Jenkins的插件生态真的很丰富，基本上你能想到的功能都有对应的插件。而且它是开源的，不用担心费用问题。最重要的是，Jenkins对PHP项目的支持很好，配置起来也比较灵活。当然了，Jenkins也有它的缺点，比如界面看起来有点老旧，配置相对复杂一些。不过习惯了就好，功能强大才是硬道理。环境准备和Jenkins安装我们的服务器环境是debain13。Jenkins可以用Docker来部署，这样比较干净，也方便管理。docker run \ -u root \ --rm \ -d \ -p 8080:8080 \ -p 50000:50000 \ -v jenkins-data:/var/jenkins_home \ -v /var/run/docker.sock:/var/run/docker.sock \ jenkinsci/blueocean开始下载我镜像一直下载失败，换了直接用软件包安装（记得安装java环境），文档地址：https://www.jenkins.io/zh/doc/book/installing/#war%E6%96%87%E4%BB%B6wget -q -O - https://pkg.jenkins.io/debian/jenkins.io.key | sudo apt-key add - sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list' sudo apt-get update sudo apt-get install jenkins启动后访问http://your-server:8080，按照提示完成初始化配置。初始密码在容器日志里能找到：必要插件安装Jenkins装好后，需要安装一些必要的插件。进入"系统管理" -> "插件管理"，安装以下插件（这些插件记得装！！！）：Git plugin（代码拉取）Pipeline（流水线支持）Blue Ocean（更好看的界面）Publish Over SSH（SSH部署）Build Timestamp（构建时间戳）Email Extension（邮件通知）插件安装完成后记得重启Jenkins。有时候插件之间会有依赖关系，Jenkins会自动帮你安装依赖的插件，这点还是很贴心的。配置Git仓库连接我们的代码托管在GitLab上，需要配置Jenkins能够拉取代码。在"系统管理" -> "全局工具配置"中配置Git路径，一般Jenkins会自动检测到。然后在"系统管理" -> "系统配置"中添加Git凭据。我建议使用SSH密钥的方式，比较安全：# 在Jenkins服务器上生成SSH密钥 ssh-keygen -t rsa -b 4096 -C "jenkins@yourcompany.com" # 将公钥添加到GitLab的Deploy Keys中 cat ~/.ssh/id_rsa.pub把私钥内容添加到Jenkins的凭据管理中，类型…

网络攻击套路大揭秘！这些年我见过的各种"妖魔鬼怪"
type: item
date: 2025-10-22T16:08:47+00:00
description: 做运维这么多年，我算是见识过各种各样的网络攻击了。从最初的懵懵懂懂被攻击搞得焦头烂额，到现在能够淡定应对各种攻击手段，这中间踩过的坑真的是数不胜数。前几天有个粉丝朋友问我，现在网络攻击都有哪些类型，怎么防护？我想了想，确实有必要系统地梳理一下这些年遇到过的各种攻击手段。毕竟知己知彼，才能百战不殆嘛。今天就跟大家聊聊我这些年见过的各种网络攻击，从技术原理到防护方法，希望能帮到正在被攻击困扰的兄弟们。SQL注入攻击 - 数据库的噩梦说到网络攻击，SQL注入绝对是我遇到最多的一种。这玩意儿简直就是Web应用的头号杀手。攻击原理SQL注入的原理其实不复杂，就是利用应用程序对用户输入过滤不严，在数据库查询中插入恶意SQL代码。我记得刚工作那会儿，维护过一个老系统，登录页面的代码是这样写的：SELECT * FROM users WHERE username='$username' AND password='$password'看起来没问题对吧？但如果用户在用户名框里输入：admin' OR '1'='1' --那么实际执行的SQL就变成了：SELECT * FROM users WHERE username='admin' OR '1'='1' --' AND password='xxx'由于'1'='1'永远为真，而--会注释掉后面的密码验证，攻击者就能直接以admin身份登录了。常见的注入类型这些年我见过的SQL注入攻击大概有这几种：联合查询注入：通过UNION语句获取其他表的数据。我处理过一个案例，攻击者通过这种方式把整个用户表都下载走了，包括密码哈希。布尔盲注：通过构造真假条件来逐个猜测数据库内容。这种攻击比较隐蔽，日志里看起来都是正常请求，但实际上在一点点窃取数据。时间盲注：利用数据库的延时函数，通过响应时间来判断条件真假。我见过攻击者用这种方法花了几个小时把管理员密码给猜出来的。报错注入：故意触发数据库错误，从错误信息中获取敏感数据。有些开发为了调试方便，会把详细的错误信息显示给用户，这就给了攻击者可乘之机。防护措施防护SQL注入其实也不难，关键是要养成好习惯：参数化查询：这是最有效的防护方法。使用预编译语句，把SQL代码和数据分离。现在主流的开发框架都支持这个功能。输入验证：对所有用户输入进行严格验证，过滤掉危险字符。不过这个方法容易被绕过，不能作为唯一的防护手段。最小权限原则：数据库用户只给必要的权限，不要用root或sa这种超级用户来连接数据库。WAF防护：部署Web应用防火墙，可以识别和阻断大部分SQL注入攻击。我现在维护的系统都强制使用ORM框架，基本杜绝了SQL注入的可能性。虽然性能会有一点影响，但安全性大大提升了。XSS攻击 - 浏览器里的陷阱跨站脚本攻击（XSS）是另一个让我头疼的问题，特别是在处理用户生成内容的网站时。攻击原理XSS攻击的核心是在网页中插入恶意脚本，当其他用户访问时，这些脚本就会在他们的浏览器中执行。我印象最深的一次XSS攻击发生在一个论坛网站。攻击者在帖子里插入了这样的代码： 结果所有查看这个帖子的用户，他们的Cookie都被发送到了攻击者的服务器上。攻击者拿到Cookie后，就能冒充这些用户登录网站了。XSS的分类根据我的经验，XSS攻击主要分为三种：反射型XSS：恶意脚本通过URL参数传递，服务器直接把参数内容输出到页面上。这种攻击需要诱骗用户点击特制的链接。存储型XSS：恶意脚本被保存在服务器上（比如数据库），每次有用户访问相关页面时都会执行。这种危害最大，因为影响面广。DOM型XSS：攻击发生在客户端，通过修改页面的DOM结构来执行恶意脚本。这种攻击比较隐蔽，服务器端很难检测到。实际案例我处理过一个比较典型的存储型XSS案例。那是一个电商网站的商品评论功能，攻击者在评论中插入了恶意脚本： 这段代码看起来像是一个破损的图片，但实际上会执行JavaScript代码，把用户的Cookie编码后发送给攻击者。更可怕的是，攻击者还在脚本中加入了蠕虫功能，被感染的用户会自动发布包含恶意脚本的评论，导致攻击快速传播。防护策略防护XSS攻击需要多管齐下：输出编码：对所有输出到HTML页面的内容进行编码，把<、>、"等特殊字符转换成HTML实体。输入过滤：对用户输入进行过滤，移除或转义危险的HTML标签和JavaScript代码。CSP策略：配置内容安全策略（Content Security Policy），限制页面可以加载的资源来源。HttpOnly Cookie：设置Cookie的HttpOnly属性，防止JavaScript访问Cookie。我现在管理的网站都部署了严格的XSS防护策略，用户输入的任何内容都会经过多层过滤和编码。虽然偶尔会误杀一些正常内容，但总比被攻击强。CSRF攻击 - 身…

Python sh库：让运维脚本告别subprocess的痛苦，一行代码搞定系统命令
type: item
date: 2025-10-21T14:27:45+00:00
description: 最近在整理服务器监控脚本的时候，发现自己写的代码里到处都是subprocess.Popen()，看着就头疼。想起刚入行那会儿，为了执行个简单的ls命令，愣是写了十几行代码处理各种异常和输出，现在想想真是太蠢了。直到遇到了Python的sh库，我才发现原来执行系统命令可以这么优雅。今天就来聊聊这个让我爱不释手的库，相信看完之后你也会和我一样，再也不想碰subprocess了。为什么我会选择sh库说实话，Python标准库里的subprocess功能很强大，但用起来真的很繁琐。每次想执行个简单命令都要考虑一堆问题：怎么获取输出？怎么处理错误？怎么传参数？import subprocess # 传统的subprocess写法，光看着就累 result = subprocess.run(['ls', '-la'], capture_output=True, text=True, check=True) print(result.stdout)而用sh库呢？import sh print(sh.ls('-la'))就这么简单！一行代码搞定，看着就舒服多了。sh库的安装和基本使用安装很简单，pip一下就行：pip install sh基本使用更简单，直接把系统命令当成Python函数调用就可以了：import sh # 执行ls命令 print(sh.ls()) # 带参数的命令 print(sh.ls('-la', '/home')) # 管道操作也很简单 print(sh.grep(sh.ps('aux'), 'python'))我第一次看到这种写法的时候，真的被震撼到了。这不就是我一直想要的那种简洁的方式吗？实际项目中的应用场景在我日常运维中，sh库真的帮了大忙。比如说服务器健康检查脚本：import sh from datetime import datetime def check_server_status(): # 检查磁盘使用情况 disk_usage = sh.df('-h') print(f"磁盘使用情况：\n{disk_usage}") # 检查内存使用 memory_info = sh.free('-h') print(f"内存使用情况：\n{memory_info}") # 检查CPU负载 load_avg = sh.uptime() print(f"系统负载：{load_avg}") # 检查特定进程 try: nginx_processes = sh.pgrep('nginx') print(f"Nginx进程数：{len(nginx_processes.strip().split())}") except sh.ErrorReturnCode_1: print("警告：Nginx进程未运行！")这种写法比subprocess清爽太多了，而且代码可读性特别好。处理命令输出和错误sh库在处理命令输出方面也很贴心：import sh # 获取命令输出 output = sh.ls('/home') print(type(output)) # <class 'sh.RunningCommand'> print(str(output)) # 转换为字符串 # 实时处理输出 def process_line(line): print(f"处理行: {line.strip()}") sh.tail('-f', '/var/log/syslog', _out=process_line)错误处理也很直观：import sh try: # 执行可能失败的命令 result = sh.ls('/nonexistent') except sh.ErrorReturnCode_2 as e: print(f"命令执行失败: {e}") print(f"错误输出: {e.stderr}") print(f"标准输出: {e.stdout}") print(f"退出码: {e.exit_code}")高级功能：管道和重定向sh库对管道的支持让我印象深刻，写起来就像在shell里一样自然：import sh # 管道操作 result = sh.ps('aux') | sh.grep('python') | sh.wc('-l') print(f"Python进程数量: {result}") # 更复杂的管道 log_errors = sh.tail('-n', '1000', '/var/log/app.log') | sh.grep('ERROR') print(log_errors) # 重定向到文件 sh.dmesg(_out='/tmp/dmesg.log') # 从文件读取输入 sh.sort(_in='/tmp/unsort…

从JumpServer安装脚本看Shell编程：一个运维人员的实战解析
type: item
date: 2025-10-18T11:53:49+00:00
description: 最近在部署JumpServer的时候，仔细研究了一下它的安装脚本，发现这个脚本写得还挺有意思的。作为一个天天和Shell打交道的运维，我觉得这个脚本很适合用来讲解Shell编程的一些实用技巧。说实话，很多人觉得Shell脚本就是简单的命令堆砌，但实际上一个好的Shell脚本包含了很多编程思想和最佳实践。今天就通过这个JumpServer的jmsctl.sh脚本，来聊聊Shell编程中那些值得学习的地方。脚本结构设计：模块化思维很重要看这个脚本的整体结构，我第一眼就被它的组织方式吸引了。作者把整个脚本分成了几个清晰的部分：#!/usr/bin/env bash export SHELLOPTS PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)" cd "${PROJECT_DIR}" || exit 1 . "${PROJECT_DIR}/scripts/utils.sh"这几行代码看似简单，但包含了很多门道。#!/usr/bin/env bash这个shebang比直接写#!/bin/bash要好，因为它会在PATH中查找bash，兼容性更强。export SHELLOPTS这行我之前还真没怎么用过，查了一下发现它是用来导出Shell选项的，这样在调用子脚本时能保持一致的行为。获取脚本所在目录的那行代码写得很巧妙：PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"${BASH_SOURCE[0]}比$0更可靠，特别是在脚本被source的时候。&>/dev/null把错误输出也重定向了，避免在某些环境下出现奇怪的错误信息。参数处理：简单但实用action=${1-} target=${2-} args=("$@")这种参数处理方式很实用。${1-}的写法比直接用$1安全，当没有参数时不会报错。把所有参数存到数组里也是个好习惯，后面需要传递给其他命令时很方便。我以前写脚本经常直接用$1、$2，但在一些边界情况下容易出问题。现在我也开始用这种写法了。配置文件检查：防御性编程function check_config_file() { if [[ ! -f "${CONFIG_FILE}" ]]; then echo "$(gettext 'Configuration file not found'): ${CONFIG_FILE}" echo "$(gettext 'If you are upgrading from v1.5.x, please copy the config.txt To') ${CONFIG_FILE}" return 3 fi # ... }这个函数体现了防御性编程的思想。不仅检查配置文件是否存在，还给出了具体的解决建议。返回值用3而不是1，这样可以区分不同类型的错误。软链接的处理也很细致：if -f .env ; then if ! ls -l .env | grep "${CONFIG_FILE}" &>/dev/null; then echo ".env $(gettext 'There is a problem with the soft connection, Please update it again')" rm -f .env fi fi检查软链接是否正确指向目标文件，如果不对就重新创建。这种处理方式在实际运维中很有用，避免了因为软链接问题导致的各种奇怪错误。国际化支持：细节决定成败脚本中大量使用了$(gettext '...')来支持多语言，这个细节让我印象深刻。虽然很多人写脚本时不会考虑国际化，但对于要分发给全球用户的开源项目来说，这确实很重要。echo "$(gettext 'JumpServer Deployment Management Script')"gettext是GNU的国际化工具，通过它可以根据系统语言环境显示对应的文本。虽然在内部项目中可能用不到，但这种思维方式值得学习。帮助信息：用户体验很关键function usage() { echo "$(gettext 'JumpServer Deployment Management Script')" echo echo "Usage: " echo " ./jmsctl.sh [COMMAND] [ARGS...]" echo " ./jmsctl.sh --help" echo echo "Installation Commands: " echo " install $(gettext 'Install JumpServer'…