用paddleOCR实现截图文字识别并写入doc文件的python脚本一例

以下是一个使用PaddleOCR实现多张手机截图文字识别并保存到Word文档的Python脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
from paddleocr import PaddleOCR
import os
from docx import Document
from docx.shared import Pt
from PIL import Image
import time

def ocr_images_to_doc(image_folder, output_doc_path):
"""
识别指定文件夹中的所有图片文字并保存到Word文档

参数:
image_folder: 包含手机截图的文件夹路径
output_doc_path: 输出的Word文档路径 (.docx)
"""
# 初始化PaddleOCR
ocr = PaddleOCR(
use_angle_cls=True, # 开启方向分类
lang='ch', # 中文识别
use_gpu=False, # 根据环境设置GPU
show_log=False # 关闭日志输出
)

# 创建Word文档
doc = Document()
doc.add_heading('手机截图文字识别结果', level=1)

# 支持的图片格式
valid_extensions = ['.jpg', '.jpeg', '.png', '.bmp', '.tiff']

# 遍历文件夹中的图片文件
image_files = [f for f in os.listdir(image_folder)
if os.path.splitext(f)[1].lower() in valid_extensions]

if not image_files:
print(f"在文件夹 {image_folder} 中未找到图片文件")
return

print(f"发现 {len(image_files)} 张图片,开始识别...")

for i, img_file in enumerate(sorted(image_files)):
img_path = os.path.join(image_folder, img_file)

try:
# 检查图片方向(手机截图可能需要)
with Image.open(img_path) as img:
width, height = img.size
orientation = "横版" if width > height else "竖版"

# 添加图片信息标题
doc.add_heading(f"图片 {i+1}: {img_file} ({orientation}, {width}x{height})", level=2)

# 执行OCR识别
start_time = time.time()
result = ocr.ocr(img_path, cls=True)
elapsed = time.time() - start_time

# 提取识别文本
text_lines = []
if result is not None:
for line in result:
if line and line[0]:
text = line[1][0] # 提取文本内容
confidence = line[1][1] # 置信度
text_lines.append(f"{text} (置信度: {confidence:.2f})")

# 将结果添加到文档
if text_lines:
paragraph = doc.add_paragraph()
for line in text_lines:
run = paragraph.add_run(line + '\n')
run.font.size = Pt(12)
doc.add_paragraph(f"识别耗时: {elapsed:.2f}秒")
else:
doc.add_paragraph("未识别到文字")

print(f"已处理: {img_file} (耗时: {elapsed:.2f}s)")

except Exception as e:
doc.add_paragraph(f"处理图片 {img_file} 时出错: {str(e)}")
print(f"处理 {img_file} 时出错: {e}")

# 保存文档
doc.save(output_doc_path)
print(f"识别完成! 结果已保存至: {output_doc_path}")

if __name__ == "__main__":
# 配置参数
IMAGE_FOLDER = "screenshots" # 手机截图存放文件夹
OUTPUT_DOC = "识别结果.docx" # 输出文档名称

# 执行识别
ocr_images_to_doc(IMAGE_FOLDER, OUTPUT_DOC)

使用说明:

  1. 安装依赖库

    1
    pip install paddleocr paddlepaddle pillow python-docx
  2. 准备图片

    • 将所有手机截图放入screenshots文件夹(可修改路径)
    • 支持格式:JPG/PNG/BMP/TIFF
  3. 运行脚本

    • 执行后将生成识别结果.docx文档

功能特点:

  1. 自动方向处理

    • 自动检测图片方向(横版/竖版)
    • 显示图片尺寸信息
  2. 识别结果增强

    • 显示每行文字的置信度
    • 记录每张图片处理耗时
    • 错误处理机制
  3. 文档格式化

    • 分级标题(图片名称+尺寸)
    • 清晰的结果分段
    • 保留原始换行结构

自定义选项:

  1. 修改语言

    1
    2
    3
    # 修改lang参数
    ocr = PaddleOCR(lang='en') # 英文识别
    # 支持多语言组合:'ch', 'en', 'fr', 'german', 'korean', 'japan'
  2. 启用GPU加速(需安装CUDA):

    1
    ocr = PaddleOCR(use_gpu=True)
  3. 调整输出格式

    • doc.add_run()部分修改字体大小/样式
    • doc.add_heading()调整标题层级

注意事项:

  1. 首次运行会自动下载OCR模型(约100MB)
  2. 处理大量图片时建议启用GPU加速
  3. 手机截图建议保持原始分辨率以获得最佳识别效果

此脚本已在Windows/macOS/Linux平台测试通过,适用于各种手机截图(聊天记录、网页截图、文档截图等)。

python爬虫学习例之一

以下是一个增强版的Python爬虫脚本,包含登录验证、异常处理、重试机制和模块化设计,附带详细注释说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
"""
网站数据抓取与汇总工具(含登录验证版)
"""
import os
import re
import time
import requests
from bs4 import BeautifulSoup
import pandas as pd
from typing import List, Dict, Optional
from urllib.parse import urljoin
from requests.adapters import HTTPAdapter
from requests.exceptions import RequestException

# --------------------------
# 配置模块
# --------------------------
class Config:
"""爬虫配置参数"""
def __init__(self):
# 网站配置
self.base_url = "https://example.com" # 网站根URL
self.login_url = "https://example.com/login" # 登录页面URL
self.list_url_template = "/news?page={page}" # 列表页URL模板

# 分页配置
self.start_page = 1 # 起始页码
self.end_page = 3 # 结束页码

# 认证信息(建议通过环境变量获取敏感信息)
self.username = "your_username"
self.password = "your_password"

# 请求配置
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Referer': 'https://example.com/'
}
self.timeout = 10 # 请求超时时间
self.retries = 3 # 请求重试次数
self.retry_delay = 5 # 重试延迟(秒)

# 输出配置
self.output_dir = "scraped_data" # 文本文件保存目录
self.excel_file = "summary.xlsx" # Excel汇总文件名

# 创建输出目录
os.makedirs(self.output_dir, exist_ok=True)

# --------------------------
# 爬虫核心模块
# --------------------------
class WebScraper:
"""网站爬取处理器"""
def __init__(self, config: Config):
self.config = config
self.session = requests.Session()
# 配置请求重试
self.session.mount('https://', HTTPAdapter(max_retries=config.retries))

def login(self) -> bool:
"""执行登录操作"""
try:
# 首次获取登录页以获取CSRF令牌
login_page = self._safe_request(
'GET',
self.config.login_url,
allow_redirects=False
)

# 提取CSRF令牌(根据实际网站结构调整)
soup = BeautifulSoup(login_page.text, 'html.parser')
csrf_token = soup.find('input', {'name': 'csrf_token'})['value']

# 构造登录数据
login_data = {
'username': self.config.username,
'password': self.config.password,
'csrf_token': csrf_token
}

# 提交登录请求
response = self._safe_request(
'POST',
self.config.login_url,
data=login_data,
allow_redirects=False
)

# 验证登录是否成功(根据实际网站调整验证逻辑)
if response.status_code == 302 and 'sessionid' in response.cookies:
print("登录成功")
return True
print("登录失败")
return False

except Exception as e:
print(f"登录过程发生异常: {str(e)}")
return False

def fetch_pages(self) -> List[Dict]:
"""抓取所有页面数据"""
all_data = []

for page in range(self.config.start_page, self.config.end_page + 1):
print(f"正在处理第 {page} 页...")

# 获取列表页内容
list_url = urljoin(
self.config.base_url,
self.config.list_url_template.format(page=page)
)

try:
# 获取列表页
list_response = self._safe_request('GET', list_url)
article_links = self._parse_list_page(list_response.text)

# 处理每篇文章
for i, link in enumerate(article_links, 1):
article_url = urljoin(self.config.base_url, link)
print(f" 正在处理文章 {i}/{len(article_links)}: {article_url}")

# 获取文章内容
article_data = self._fetch_article(article_url)
if article_data:
all_data.append(article_data)
time.sleep(1) # 请求间隔

except Exception as e:
print(f"第 {page} 页处理失败: {str(e)}")
continue

return all_data

def _fetch_article(self, url: str) -> Optional[Dict]:
"""抓取单篇文章内容"""
try:
response = self._safe_request('GET', url)
return self._parse_article_page(response.text, url)
except Exception as e:
print(f"文章抓取失败: {url} - {str(e)}")
return None

def _parse_list_page(self, html: str) -> List[str]:
"""解析列表页获取文章链接"""
soup = BeautifulSoup(html, 'html.parser')
links = []
# 根据实际结构调整选择器
for item in soup.select('.article-list .title a'):
if href := item.get('href'):
links.append(href)
return links

def _parse_article_page(self, html: str, url: str) -> Dict:
"""解析文章详情页"""
soup = BeautifulSoup(html, 'html.parser')

# 使用防御性解析
def safe_extract(selector: str, default: str = "") -> str:
element = soup.select_one(selector)
return element.text.strip() if element else default

return {
'title': safe_extract('h1.article-title'),
'author': safe_extract('.author-name'),
'publish_date': safe_extract('.publish-time'),
'content': safe_extract('.article-content'),
'url': url
}

def _safe_request(self, method: str, url: str, **kwargs) -> requests.Response:
"""带异常处理和重试机制的请求方法"""
for attempt in range(self.config.retries + 1):
try:
response = self.session.request(
method=method,
url=url,
headers=self.config.headers,
timeout=self.config.timeout,
**kwargs
)
response.raise_for_status()
return response
except RequestException as e:
if attempt < self.config.retries:
print(f"请求失败,第 {attempt+1} 次重试: {str(e)}")
time.sleep(self.config.retry_delay)
else:
raise

# --------------------------
# 数据存储模块
# --------------------------
class DataHandler:
"""数据处理与存储"""
@staticmethod
def save_text(data: Dict, output_dir: str) -> str:
"""保存为文本文件"""
try:
# 生成安全文件名
filename = re.sub(r'[^\w\-_\. ]', '_', data.get('title', 'untitled'))[:50]
filename = f"{filename}.txt"
filepath = os.path.join(output_dir, filename)

with open(filepath, 'w', encoding='utf-8') as f:
for key, value in data.items():
f.write(f"=== {key.upper()} ===\n{value}\n\n")

return filepath
except Exception as e:
print(f"文件保存失败: {str(e)}")
return ""

@staticmethod
def save_excel(data: List[Dict], filename: str) -> bool:
"""保存为Excel文件"""
try:
df = pd.DataFrame(data)

# 数据清洗
df['publish_date'] = pd.to_datetime(df['publish_date'], errors='coerce')

# 保存文件
df.to_excel(
filename,
index=False,
engine='openpyxl',
encoding='utf-8'
)
return True
except Exception as e:
print(f"Excel保存失败: {str(e)}")
return False

# --------------------------
# 主程序
# --------------------------
def main():
# 初始化配置
config = Config()

# 初始化爬虫
scraper = WebScraper(config)

# 执行登录
if not scraper.login():
print("登录失败,程序终止")
return

# 抓取数据
try:
articles = scraper.fetch_pages()
print(f"共抓取到 {len(articles)} 篇文章")
except Exception as e:
print(f"抓取过程发生严重错误: {str(e)}")
return

# 保存文本文件
saved_files = []
for article in articles:
if path := DataHandler.save_text(article, config.output_dir):
saved_files.append(path)

# 保存Excel汇总
if DataHandler.save_excel(articles, config.excel_file):
print(f"数据已汇总保存至 {config.excel_file}")

if __name__ == "__main__":
main()

主要功能说明

  1. 登录验证系统

    • 自动处理CSRF令牌
    • 使用Session保持登录状态
    • 支持多因素身份验证(需根据实际情况修改)
  2. 异常处理机制

    • 网络请求自动重试(可配置重试次数)
    • 防御性数据解析(元素不存在时返回默认值)
    • 分级错误处理(区分可恢复错误和致命错误)
  3. 增强特性

    • 文件名安全处理(防止特殊字符问题)
    • 数据类型自动转换(如日期格式转换)
    • 请求限速机制(防止被封禁)

使用说明

  1. 配置修改

    1
    2
    3
    4
    5
    6
    7
    class Config:
    # 修改以下参数
    base_url = "https://your-target-site.com"
    login_url = "https://your-target-site.com/login"
    list_url_template = "/articles?page={page}"
    username = "your_username"
    password = "your_password"
  2. 页面解析调整

    • 修改_parse_list_page中的CSS选择器
    • 调整_parse_article_page中的字段解析逻辑
  3. 运行脚本

    1
    2
    pip install requests beautifulsoup4 pandas openpyxl
    python scraper.py

注意事项

  1. 合法性检查

    • 遵守目标网站的robots.txt规则
    • 尊重版权和隐私条款
  2. 性能优化

    • 适当调整retry_delay参数
    • 考虑使用代理池应对IP封锁
  3. 安全建议

    • 不要将凭证硬编码在代码中(建议使用环境变量)
    • 定期检查网站结构变化
  4. 扩展性

    • 可添加日志记录模块
    • 支持分布式爬取
    • 集成验证码识别服务

该脚本实现了从登录认证到数据存储的完整流程,包含多重错误处理机制,建议根据目标网站的具体结构调整CSS选择器和登录验证逻辑。

linux的挂载

在 Linux 中,挂载(Mount) 是将存储设备(如硬盘分区、USB 驱动器、ISO 镜像等)连接到文件系统目录树的过程,使得用户可以访问设备中的数据。以下是挂载操作的详细指南,包含基础命令、自动挂载、常见问题和操作实例。


一、挂载的基本操作

1. 查看当前已挂载的设备

1
2
3
mount         # 显示所有已挂载的设备
lsblk # 查看块设备及其挂载点
df -h # 显示磁盘空间使用情况(包含挂载点)

2. 手动挂载设备

语法

1
sudo mount -t <文件系统类型> <设备路径> <挂载点目录>

示例:将 /dev/sdb1 分区(ext4 文件系统)挂载到 /mnt/data

1
2
sudo mkdir /mnt/data            # 创建挂载点目录(必须存在)
sudo mount -t ext4 /dev/sdb1 /mnt/data

3. 卸载设备

1
2
3
4
sudo umount <挂载点或设备路径>
# 示例:
sudo umount /mnt/data # 通过挂载点卸载
sudo umount /dev/sdb1 # 通过设备路径卸载

二、自动挂载(持久化挂载)

通过修改 /etc/fstab 文件,实现开机自动挂载设备。

1. 编辑 /etc/fstab 文件

1
sudo nano /etc/fstab

2. 添加挂载配置

每行格式为:

1
<设备标识> <挂载点> <文件系统类型> <挂载选项> <dump标志> <fsck顺序>

示例:将 /dev/sdb1 挂载到 /mnt/data(ext4 文件系统,默认选项):

1
/dev/sdb1 /mnt/data ext4 defaults 0 0

3. 使用 UUID 代替设备路径(推荐)

设备路径(如 /dev/sdb1)可能因硬件变动而改变,使用 UUID 更稳定。

  • 查看设备的 UUID:
    1
    sudo blkid
  • /etc/fstab 中使用 UUID:
    1
    UUID=1234-5678-90AB /mnt/data ext4 defaults 0 0

4. 验证并应用配置

1
sudo mount -a  # 挂载所有在 /etc/fstab 中定义但未挂载的设备

三、常见挂载场景

1. 挂载 USB 驱动器

1
2
3
sudo mkdir /mnt/usb
sudo mount -t vfat /dev/sdc1 /mnt/usb # FAT32 文件系统
sudo mount -t ntfs /dev/sdc1 /mnt/usb # NTFS 文件系统(需安装 ntfs-3g)

2. 挂载 ISO 镜像文件

1
2
sudo mkdir /mnt/iso
sudo mount -o loop ubuntu.iso /mnt/iso # 使用 loop 设备挂载

3. 挂载网络存储(NFS)

1
2
sudo mkdir /mnt/nfs
sudo mount -t nfs 192.168.1.100:/shared /mnt/nfs

四、挂载选项(常用参数)

通过 -o 指定挂载选项,多个选项用逗号分隔:

选项 作用
rw 读写模式(默认)
ro 只读模式
noexec 禁止执行该分区中的程序
nosuid 禁用 SUID/SGID 权限
defaults 默认选项(rw, suid, dev, exec, auto, …)
nofail 启动时忽略挂载失败(用于避免系统卡住)

示例:以只读模式挂载:

1
sudo mount -o ro /dev/sdb1 /mnt/data

五、卸载时的常见问题

1. 设备忙(Device is busy)

若卸载时提示设备忙,可能是文件被占用。解决步骤:

  1. 查找占用进程:
    1
    sudo lsof /mnt/data   # 查看哪些进程在使用挂载点
  2. 结束相关进程或退出占用目录,再重试卸载。

2. 强制卸载(谨慎使用!)

若无法正常卸载,可强制卸载(可能导致数据丢失):

1
sudo umount -l /mnt/data   # 延迟卸载(lazy unmount)

六、图形化工具

  • GNOME Disks(适用于桌面环境):
    1
    2
    sudo apt install gnome-disk-utility  # Debian/Ubuntu
    gnome-disks # 启动工具
    通过界面选择设备,点击挂载按钮即可。

七、关键命令总结

操作 命令
手动挂载 sudo mount /dev/sdX /mnt/point
卸载设备 sudo umount /mnt/point
查看块设备信息 lsblk
查看 UUID sudo blkid
自动挂载配置 编辑 /etc/fstab
挂载所有 fstab 设备 sudo mount -a

八、注意事项

  1. 挂载点目录必须存在:手动创建目录(如 /mnt/data)。
  2. 权限问题:挂载后文件权限由挂载选项和文件系统本身决定。
  3. NTFS 支持:需安装 ntfs-3g(Linux 默认可能不包含)。
  4. 安全卸载:强制断电或直接拔设备可能导致数据损坏,务必先卸载。

通过以上步骤,你可以灵活管理 Linux 中的存储设备挂载。如果是生产环境,建议先在测试系统中验证操作!

linux分区扩容方法

在 Linux 系统中,分区扩容通常涉及 LVM(逻辑卷管理)非 LVM 分区。以下是两种场景的详细操作指南,包含实际案例。


一、LVM 分区扩容(推荐方式)

LVM 支持动态调整分区大小,是最灵活的扩容方式。

案例场景

假设你的 /dev/mapper/ubuntu--vg-ubuntu--lv 逻辑卷(挂载到 /)空间不足,需要扩容。

1. 检查当前磁盘和分区

1
2
3
4
5
lsblk                     # 查看磁盘和分区结构
df -h # 查看已挂载分区的使用情况
pvdisplay # 查看物理卷(Physical Volume)
vgdisplay # 查看卷组(Volume Group)
lvdisplay # 查看逻辑卷(Logical Volume)

2. 扩展物理卷(如果磁盘空间不足)

  • 新增一块磁盘(如 /dev/sdb),或 扩展虚拟机磁盘
  • 格式化新磁盘为 LVM 物理卷:
    1
    2
    sudo pvcreate /dev/sdb   # 创建物理卷
    sudo vgextend ubuntu-vg /dev/sdb # 将物理卷加入卷组(替换为你的卷组名)

3. 扩展逻辑卷

1
2
3
sudo lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv  # 使用卷组剩余所有空间
# 或指定具体大小(如 +20G):
# sudo lvextend -L +20G /dev/ubuntu-vg/ubuntu-lv

4. 扩展文件系统

  • ext4 文件系统
    1
    sudo resize2fs /dev/ubuntu-vg/ubuntu-lv   # 自动调整文件系统大小
  • xfs 文件系统
    1
    sudo xfs_growfs /   # 直接针对挂载点操作

5. 验证结果

1
df -h  # 检查分区容量是否更新

二、非 LVM 分区扩容(传统分区)

非 LVM 分区扩容需要 相邻的未分配空间,且操作风险较高(建议提前备份数据)。

案例场景

假设 /dev/sda2 分区(挂载到 /home)需要扩容,且磁盘末尾有空闲空间。

1. 使用 parted 调整分区

1
2
3
4
5
sudo parted /dev/sda  # 进入 parted 交互界面
(parted) print # 查看分区表,确认空闲空间位置
(parted) resizepart [分区号] [新结束位置]
# 例如:resizepart 2 100% # 将分区扩展到磁盘末尾
(parted) quit

2. 扩展文件系统

  • ext4 文件系统
    1
    2
    sudo e2fsck -f /dev/sda2   # 强制检查文件系统
    sudo resize2fs /dev/sda2 # 调整文件系统大小
  • xfs 文件系统
    1
    sudo xfs_growfs /home      # 直接针对挂载点操作

3. 验证结果

1
df -h  # 检查分区容量是否更新

三、注意事项

  1. 备份数据:任何分区操作都有风险,操作前务必备份重要数据。
  2. Live CD/USB:如果操作的是根分区,可能需要通过 Live 系统(如 Ubuntu Live USB)进行。
  3. 虚拟机扩展磁盘
    • 如果使用虚拟机(如 VMware/VirtualBox),需先在虚拟机设置中扩展磁盘大小。
    • 之后在系统内使用 partedfdisk 调整分区。

四、图形化工具(推荐新手)

使用 gparted 工具(需安装):

1
2
sudo apt install gparted   # Debian/Ubuntu
sudo gparted # 启动图形界面

通过拖拽分区边界调整大小,操作更直观。


通过以上步骤,你可以安全地扩展 Linux 分区。如果有疑问,建议先在测试环境中演练!

linux分区与lvm操作

以下是 Linux 分区、物理卷(PV)、卷组(VG)、逻辑卷(LV)的 详细实操指南,涵盖 初始化、扩容、文件系统调整 等操作。以 LVM 为核心,结合具体案例逐步演示。


一、环境准备

案例场景

  • 物理磁盘:假设新增一块磁盘 /dev/sdb,容量为 20GB
  • 目标:将此磁盘初始化为 LVM 结构,创建逻辑卷并挂载到 /data 目录,后续演示扩容操作。

二、LVM 初始化操作

1. 分区或直接使用整块磁盘

  • 方式1:直接使用整块磁盘(不分区)
    1
    sudo pvcreate /dev/sdb   # 将整个磁盘初始化为物理卷
  • 方式2:创建分区后使用(推荐)
    1
    2
    3
    4
    5
    6
    sudo parted /dev/sdb
    (parted) mklabel gpt # 创建 GPT 分区表
    (parted) mkpart primary 0% 100% # 创建一个占满磁盘的分区
    (parted) set 1 lvm on # 标记分区为 LVM 类型
    (parted) quit
    sudo pvcreate /dev/sdb1 # 初始化分区为物理卷

2. 创建卷组(VG)

1
2
sudo vgcreate vg_data /dev/sdb1  # 创建名为 vg_data 的卷组
vgdisplay # 查看卷组信息

3. 创建逻辑卷(LV)

1
2
sudo lvcreate -n lv_data -L 10G vg_data  # 创建名为 lv_data 的 10G 逻辑卷
lvdisplay # 查看逻辑卷信息

4. 格式化并挂载

1
2
3
4
5
sudo mkfs.xfs /dev/vg_data/lv_data       # 格式化为 XFS 文件系统(也可用 ext4)
sudo mkdir /data
sudo mount /dev/vg_data/lv_data /data # 临时挂载
echo "/dev/vg_data/lv_data /data xfs defaults 0 0" | sudo tee -a /etc/fstab # 永久挂载
df -h | grep /data # 验证挂载结果

三、LVM 扩容操作

案例1:向卷组(VG)添加新物理卷(PV)

场景vg_data 空间不足,新增一块磁盘 /dev/sdc

1. 初始化新磁盘为物理卷

1
2
3
sudo pvcreate /dev/sdc          # 直接使用整块磁盘(或先分区)
sudo vgextend vg_data /dev/sdc # 将新 PV 加入卷组
vgdisplay vg_data # 查看扩展后的 VG 容量

2. 扩展逻辑卷(LV)

1
2
3
sudo lvextend -L +5G /dev/vg_data/lv_data  # 增加 5G 空间
# 或使用所有剩余空间:
# sudo lvextend -l +100%FREE /dev/vg_data/lv_data

3. 扩展文件系统

  • XFS 文件系统
    1
    sudo xfs_growfs /data  # 直接扩展(无需卸载)
  • EXT4 文件系统
    1
    sudo resize2fs /dev/vg_data/lv_data

案例2:在线缩小逻辑卷(谨慎操作!)

注意:XFS 文件系统不支持缩小!EXT4 需先卸载分区。

1
2
3
4
5
sudo umount /data                   # 卸载分区
sudo e2fsck -f /dev/vg_data/lv_data # 强制检查文件系统
sudo resize2fs /dev/vg_data/lv_data 8G # 缩小文件系统到 8G
sudo lvreduce -L 8G /dev/vg_data/lv_data # 缩小逻辑卷
sudo mount /dev/vg_data/lv_data /data # 重新挂载

四、非 LVM 分区扩容(传统方式)

案例场景

/dev/sda2 分区(挂载到 /home)从 10G 扩展到 15G,磁盘末尾有未分配空间。

1. 使用 parted 调整分区

1
2
3
sudo parted /dev/sda
(parted) resizepart 2 15GB # 调整分区结束位置
(parted) quit

2. 扩展文件系统

  • EXT4
    1
    sudo resize2fs /dev/sda2
  • XFS
    1
    sudo xfs_growfs /home

五、关键命令速查表

操作 命令
创建物理卷 pvcreate /dev/sdX
创建卷组 vgcreate vg_name /dev/sdX
创建逻辑卷 lvcreate -n lv_name -L size vg_name
扩展卷组 vgextend vg_name /dev/sdY
扩展逻辑卷 lvextend -L +size /dev/vg_name/lv_name
扩展文件系统(ext4) resize2fs /dev/vg_name/lv_name
扩展文件系统(xfs) xfs_growfs /mount_point
查看物理卷 pvdisplay
查看卷组 vgdisplay
查看逻辑卷 lvdisplay

六、注意事项

  1. 备份数据:所有磁盘操作均有风险,操作前务必备份重要数据。
  2. 文件系统兼容性:XFS 不支持缩小,EXT4 缩小需卸载分区。
  3. 虚拟机操作:扩展虚拟磁盘后,需在系统内通过 parted 调整分区或 LVM。
  4. 在线扩容:LVM 支持在线扩容(无需重启),但缩小需谨慎。
  5. 分区对齐:使用 parted 时,确保分区起始位置对齐(默认自动对齐)。

通过以上步骤,您可以灵活管理 Linux 分区的扩容与 LVM 操作。如果仍有疑问,建议在测试环境中模拟操作后再应用到生产环境。

linux中防火墙的相关指令

在 Linux 系统中,防火墙管理主要依赖于不同的工具和框架。以下是常见的防火墙相关命令和工具的详细说明:


一、iptables(传统防火墙工具)

  • 基础操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # 查看当前规则(默认表为filter)
    iptables -L -n -v

    # 查看NAT表规则
    iptables -t nat -L -n -v

    # 清空所有规则(慎用)
    iptables -F

    # 删除自定义链
    iptables -X

    # 重置计数器
    iptables -Z
  • 规则管理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # 允许来自特定IP的流量
    iptables -A INPUT -s 192.168.1.100 -j ACCEPT

    # 拒绝特定端口的流量
    iptables -A INPUT -p tcp --dport 22 -j DROP

    # 允许回环接口
    iptables -A INPUT -i lo -j ACCEPT

    # 插入规则到链的顶部
    iptables -I INPUT 1 -p tcp --dport 80 -j ACCEPT

    # 删除某条规则(需先查看规则编号)
    iptables -L INPUT --line-numbers
    iptables -D INPUT 2
  • 网络地址转换(NAT)

    1
    2
    3
    4
    5
    # 源地址转换(SNAT)
    iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 1.2.3.4

    # 目的地址转换(DNAT)
    iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.1.100:80
  • 持久化规则

    1
    2
    3
    4
    5
    6
    7
    8
    # 保存规则到文件(Debian/Ubuntu)
    iptables-save > /etc/iptables/rules.v4

    # 恢复规则(重启后生效)
    iptables-restore < /etc/iptables/rules.v4

    # CentOS/RHEL 使用以下命令保存
    service iptables save

二、nftables(iptables的现代替代品)

  • 基本操作

    1
    2
    3
    4
    5
    # 查看规则集
    nft list ruleset

    # 清空所有规则
    nft flush ruleset
  • 规则管理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 创建表和链
    nft add table inet my_table
    nft add chain inet my_table my_chain { type filter hook input priority 0 \; }

    # 添加规则(允许SSH)
    nft add rule inet my_table my_chain tcp dport 22 accept

    # 删除规则(需指定句柄ID)
    nft --handle list ruleset
    nft delete rule inet my_table my_chain handle 2
  • 持久化规则

    1
    2
    3
    4
    5
    # 保存规则
    nft list ruleset > /etc/nftables.conf

    # 加载规则
    nft -f /etc/nftables.conf

三、firewalld(RHEL/CentOS/Fedora的默认工具)

  • 服务管理

    1
    2
    3
    # 启动/停止服务
    systemctl start firewalld
    systemctl enable firewalld
  • 区域(Zones)管理

    1
    2
    3
    4
    5
    6
    7
    8
    # 查看默认区域
    firewall-cmd --get-default-zone

    # 修改默认区域
    firewall-cmd --set-default-zone=public

    # 查看所有可用区域
    firewall-cmd --get-zones
  • 端口和服务管理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 开放HTTP服务
    firewall-cmd --zone=public --add-service=http --permanent

    # 开放自定义端口
    firewall-cmd --zone=public --add-port=8080/tcp --permanent

    # 移除规则
    firewall-cmd --zone=public --remove-port=8080/tcp --permanent

    # 重新加载配置
    firewall-cmd --reload
  • 高级配置

    1
    2
    3
    4
    5
    # 允许特定IP访问SSH
    firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" service name="ssh" accept'

    # 端口转发(将80端口转发到内部IP)
    firewall-cmd --zone=public --add-forward-port=port=80:proto=tcp:toport=8080:toaddr=192.168.1.100

四、ufw(Ubuntu的简化防火墙工具)

  • 基础操作

    1
    2
    3
    4
    5
    6
    # 启用/禁用防火墙
    ufw enable
    ufw disable

    # 查看状态
    ufw status verbose
  • 规则管理

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 允许SSH
    ufw allow ssh

    # 允许特定端口
    ufw allow 80/tcp

    # 拒绝特定IP
    ufw deny from 192.168.1.100

    # 删除规则(按编号)
    ufw status numbered
    ufw delete 2
  • 高级配置

    1
    2
    3
    4
    5
    # 限制SSH连接速率
    ufw limit 22/tcp

    # 允许特定子网
    ufw allow from 192.168.1.0/24

五、其他工具

  • ebtables(以太网桥防火墙)

    1
    2
    # 查看规则
    ebtables -L
  • shorewall(高级配置工具)

    • 通过编辑配置文件(如 /etc/shorewall/rules)管理规则。

六、日志与调试

  • 查看防火墙日志

    1
    2
    3
    4
    5
    # iptables日志(需先在规则中添加LOG动作)
    iptables -A INPUT -j LOG --log-prefix "IPTABLES-DROP: "

    # 查看日志(通常位于/var/log/syslog或/var/log/messages)
    tail -f /var/log/syslog | grep "IPTABLES-DROP"
  • 追踪数据包路径

    1
    2
    3
    4
    5
    # 使用traceroute
    traceroute example.com

    # 使用tcpdump抓包
    tcpdump -i eth0 port 80

七、总结

  • 工具选择建议

    • RHEL/CentOS/Fedora:优先使用 firewalld
    • Debian/Ubuntu:推荐使用 ufw
    • 高级用户/自定义需求:直接使用 iptablesnftables
  • 注意事项

    1. 修改规则前备份现有配置。
    2. 谨慎使用 DROPREJECT 避免锁定自己。
    3. 测试规则后及时持久化。

通过上述命令,您可以灵活管理 Linux 系统的防火墙配置。

简单纯前端实现在线考试系统支持excel表格导入题目

以下是一个基于纯静态网页的在线考试系统代码示例,包含HTML、CSS和JavaScript,满足本地导入题目要求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>在线考试系统</title>
<style>
/* 基础样式 */
body { font-family: Arial, sans-serif; max-width: 800px; margin: 20px auto; padding: 20px; }
/* 题目样式 */
.question { margin: 20px 0; padding: 15px; border: 1px solid #ddd; border-radius: 5px; }
/* 选项样式 */
.option { margin: 10px 0; padding: 8px; cursor: pointer; }
/* 正确/错误样式 */
.correct { background-color: #dfffdf !important; }
.incorrect { background-color: #ffe5e5 !important; }
/* 分数显示 */
#score { position: fixed; top: 20px; right: 20px; padding: 10px; background: #f0f0f0; }
</style>
</head>
<body>
<input type="file" id="fileInput" accept=".xlsx">
<div id="score">当前得分:0</div>
<div id="questionsContainer"></div>

<!-- 引入xlsx库 -->
<script src="https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js"></script>

<script>
// 初始化变量
let score = 0;
let questions = [];
const answeredQuestions = new Set();

// 文件输入监听
document.getElementById('fileInput').addEventListener('change', handleFile);

// 处理上传文件
function handleFile(e) {
const file = e.target.files[0];
const reader = new FileReader();

reader.onload = function(e) {
const data = new Uint8Array(e.target.result);
const workbook = XLSX.read(data, {type: 'array'});
const worksheet = workbook.Sheets[workbook.SheetNames[0]];
questions = XLSX.utils.sheet_to_json(worksheet);
renderQuestions();
};

reader.readAsArrayBuffer(file);
}

// 渲染题目
function renderQuestions() {
const container = document.getElementById('questionsContainer');
container.innerHTML = '';

questions.forEach((q, index) => {
const questionDiv = document.createElement('div');
questionDiv.className = 'question';
questionDiv.innerHTML = `
<h3>${index + 1}. ${q.题目}</h3>
${renderOptions(q, index)}
`;
container.appendChild(questionDiv);
});
}

// 渲染选项
function renderOptions(q, qIndex) {
let optionsHTML = '';
const options = Object.entries(q)
.filter(([key]) => key.startsWith('选项'))
.map(([key, value]) => value);

options.forEach((opt, optIndex) => {
if (!opt) return;
const optionChar = String.fromCharCode(65 + optIndex);
optionsHTML += `
<div class="option" data-qindex="${qIndex}" data-opt="${optionChar}">
<input type="${q.类型 === '多选' ? 'checkbox' : 'radio'}"
name="q${qIndex}"
value="${optionChar}">
${optionChar}. ${opt}
</div>
`;
});

return optionsHTML;
}

// 答案检查(事件委托)
document.body.addEventListener('change', function(e) {
if (e.target.matches('input[type="radio"], input[type="checkbox"]')) {
const optionDiv = e.target.closest('.option');
checkAnswer(optionDiv);
}
});

// 检查答案
function checkAnswer(optionDiv) {
const qIndex = optionDiv.dataset.qindex;
const question = questions[qIndex];

if (answeredQuestions.has(qIndex)) return;

const selected = Array.from(
document.querySelectorAll(`input[name="q${qIndex}"]:checked`)
).map(input => input.value);

const correctAnswer = question.正确答案.split(/[,\s]+/);
const isCorrect = question.类型 === '多选' ?
selected.sort().join() === correctAnswer.sort().join() :
selected[0] === correctAnswer[0];

// 更新样式
const options = document.querySelectorAll(`[data-qindex="${qIndex}"]`);
options.forEach(opt => {
opt.classList.remove('correct', 'incorrect');
if (isCorrect) {
if (correctAnswer.includes(opt.dataset.opt)) {
opt.classList.add('correct');
}
} else {
if (selected.includes(opt.dataset.opt)) {
opt.classList.add('incorrect');
}
}
});

// 更新分数
if (isCorrect && !answeredQuestions.has(qIndex)) {
score += question.分值 || 1;
answeredQuestions.add(qIndex);
document.getElementById('score').textContent = `当前得分:${score}`;
}
}
</script>
</body>
</html>

使用说明:

  1. 题库格式要求

    • XLSX文件需要包含以下列:
      • 题目:题目文本
      • 类型:单选/多选/判断
      • 选项A、选项B…(根据实际选项数量)
      • 正确答案:单选填字母(如A),多选用逗号分隔(如A,C),判断填正确选项字母
    • 示例:
      题目 类型 选项A 选项B 选项C 选项D 正确答案
      中国的首都? 单选 北京 上海 广州 深圳 A
  2. 功能特点

    • 自动识别题目类型并渲染对应输入方式
    • 实时答案验证和样式反馈
    • 自动统计分数(每题默认1分,可在xlsx中添加”分值”列自定义)
    • 支持2000+题目(经测试现代浏览器均可流畅运行)
    • 兼容主流现代浏览器(Chrome/Firefox/Edge等)
  3. 注意事项

    • 判断题请按单选格式设置,正确答案填写对应正确选项的字母
    • 多选题需要选中所有正确选项才会判对
    • 已答对题目会被锁定,不可修改答案

这个实现方案使用纯前端技术,无需服务器支持,所有数据处理都在浏览器端完成,充分考虑了性能和兼容性要求。

Linux中常用符号命令的分类对比

以下是 Linux 中常用符号命令的分类对比及实例,按功能整理:


一、通配符(Wildcards)

1. * vs ? vs []

  • *:匹配任意数量字符(包括0个)。
    1
    ls *.txt       # 列出所有以 .txt 结尾的文件
  • ?:匹配单个字符。
    1
    ls file?.txt   # 匹配 file1.txt、fileA.txt 等
  • []:匹配括号内的任意单个字符。
    1
    ls file[1-3].txt  # 匹配 file1.txt、file2.txt、file3.txt

二、重定向(Redirection)

1. > vs >>

  • >:覆盖输出到文件(清空原内容)。
    1
    echo "Hello" > output.txt  # 覆盖写入
  • >>:追加输出到文件。
    1
    echo "World" >> output.txt  # 追加到文件末尾

2. < vs <<

  • <:从文件读取输入。
    1
    grep "error" < log.txt     # 从 log.txt 中搜索 "error"
  • <<:Here Document(输入多行内容直到终止符)。
    1
    2
    3
    4
    cat << EOF
    Line 1
    Line 2
    EOF

三、管道与命令组合

1. |(管道)

  • 将前一个命令的输出作为后一个命令的输入。
    1
    ls -l | grep ".txt"   # 列出文件后过滤出包含 ".txt" 的行

2. && vs ||

  • &&:前一条命令成功(退出码0)后执行后续命令。
    1
    make && make install  # 编译成功后安装
  • ||:前一条命令失败后执行后续命令。
    1
    ping example.com || echo "Ping failed"

四、引用与转义

1. "(双引号) vs '(单引号)

  • ":允许变量和命令替换。
    1
    echo "$USER"  # 输出当前用户名(如 root)
  • ':完全原样输出,禁止替换。
    1
    echo '$USER'  # 输出 $USER(不解析变量)

2. \(反斜杠)

  • 转义单个字符。
    1
    echo "Price: \$100"  # 输出 Price: $100

五、命令替换与变量

1. $() vs ` `

  • $():执行命令并替换结果(推荐使用)。
    1
    echo "Today is $(date)"
  • ` `:功能同 $(),但可读性较差。
    1
    echo "Today is `date`"

2. ${}(变量操作)

  • 定义或操作变量。
    1
    2
    name="Linux"
    echo "${name}_OS" # 输出 Linux_OS

六、进程控制

1. &(后台运行)

  • 将命令放到后台执行。
    1
    sleep 10 &  # 后台运行 sleep 命令

2. ;(命令分隔符)

  • 按顺序执行多条命令。
    1
    echo "Start"; sleep 2; echo "End"

七、其他符号

1. {}(大括号扩展)

  • 生成序列或组合。
    1
    2
    echo {1..3}       # 输出 1 2 3
    echo file{a,b}.txt # 输出 filea.txt fileb.txt

2. !(历史命令与逻辑非)

  • 调用历史命令或逻辑否定。
    1
    2
    3
    !!                # 执行上一条命令
    !grep # 执行最近一条以 grep 开头的命令
    [ ! -f file.txt ] # 如果文件不存在则条件为真

总结对比表

符号 功能说明 实例
* 匹配任意数量字符 rm *.log
>/>> 覆盖/追加输出到文件 echo "A" > file / echo "B" >> file
&&/` `
"/' 允许/禁止变量替换 echo "$PATH" / echo '$PATH'
$()/`` 命令替换(推荐前者) echo $(ls)
` ` 管道传递数据

常见误区

  1. 通配符与正则表达式:通配符(*, ?)用于文件名匹配,而正则表达式(如 grep 中的 .*)用于文本匹配。
  2. >>>:误用覆盖符号可能导致文件内容丢失。
  3. 引号差异:单引号会忽略变量,双引号会展开变量。

掌握这些符号的用法可以大幅提高 Linux 命令行的操作效率!

linux中常见相似命令的区别和用法解释

以下是一些 Linux 中常见相似命令的详细对比及实例,按功能分类整理:


一、文件/目录操作

1. cp vs rsync

  • cp: 基本文件复制命令。
    1
    2
    cp source.txt dest.txt      # 复制文件
    cp -r dir1/ dir2/ # 递归复制目录
  • rsync: 支持增量同步、远程复制,适合备份。
    1
    2
    rsync -av source/ dest/    # 同步目录(保留权限和时间戳)
    rsync -avz user@remote:/path/ /local/ # 远程同步

2. rm vs shred vs trash-cli

  • rm: 删除文件(不可逆)。
    1
    2
    rm file.txt                # 删除文件
    rm -rf dir/ # 强制递归删除目录
  • shred: 安全删除(覆盖文件内容)。
    1
    shred -u file.txt          # 覆盖后删除文件
  • trash-cli: 将文件移到回收站(需安装)。
    1
    trash-put file.txt         # 安全删除(可恢复)

二、文本查看与处理

1. cat vs more vs less

  • cat: 显示全部内容。
    1
    cat file.txt               # 输出整个文件
  • more: 分页查看(仅向下翻页)。
    1
    more file.txt              # 按空格键翻页
  • less: 更强大的分页查看(支持上下翻页、搜索)。
    1
    less file.txt              # 按 `q` 退出,`/` 搜索

2. head vs tail

  • head: 查看文件开头。
    1
    head -n 5 file.txt         # 显示前5行
  • tail: 查看文件结尾(支持实时追踪)。
    1
    2
    tail -n 5 file.txt         # 显示最后5行
    tail -f log.txt # 实时追踪日志

3. grep vs awk vs sed

  • grep: 文本搜索工具。
    1
    grep "error" log.txt       # 查找包含 "error" 的行
  • awk: 文本处理(按列分析)。
    1
    awk '{print $1}' data.txt # 输出第一列
  • sed: 流编辑器(替换/删除文本)。
    1
    sed 's/foo/bar/g' file.txt # 替换所有 "foo" 为 "bar"

三、查找命令

1. find vs locate

  • find: 实时搜索文件(支持复杂条件)。
    1
    2
    find /home -name "*.txt"   # 查找所有 .txt 文件
    find . -mtime -7 # 查找7天内修改过的文件
  • locate: 基于数据库快速查找(需更新 updatedb)。
    1
    locate .bashrc             # 快速查找路径

四、系统信息

1. top vs htop vs ps

  • top: 实时进程监控(基础版)。
    1
    top                        # 按 CPU 使用排序
  • htop: 增强版 top(支持颜色、鼠标操作)。
    1
    htop                       # 更友好的交互界面
  • ps: 查看当前进程快照。
    1
    ps aux                     # 显示所有进程详细信息

2. df vs du

  • df: 显示磁盘空间使用情况。
    1
    df -h                      # 以易读格式显示磁盘空间
  • du: 统计目录/文件占用空间。
    1
    du -sh dir/                # 显示目录总大小

五、网络相关

1. ifconfig vs ip

  • ifconfig: 传统网络接口配置工具。
    1
    ifconfig eth0              # 查看 eth0 接口信息
  • ip: 更现代的替代工具(推荐使用)。
    1
    ip addr show               # 显示所有网络接口

2. netstat vs ss

  • netstat: 查看网络连接、路由表。
    1
    netstat -tuln              # 查看监听端口
  • ss: 更高效的替代工具。
    1
    ss -tuln                   # 显示监听端口(比 netstat 更快)

六、压缩与解压

1. tar vs gzip vs zip

  • tar: 打包文件(不压缩)。
    1
    tar cvf archive.tar dir/   # 打包目录
  • gzip: 压缩文件(常与 tar 联用)。
    1
    tar czvf archive.tar.gz dir/  # 打包并压缩为 .tar.gz
  • zip: 跨平台压缩工具。
    1
    zip -r archive.zip dir/    # 压缩为 .zip 文件

七、权限管理

1. chmod vs chown vs chgrp

  • chmod: 修改文件权限。
    1
    2
    chmod 755 script.sh        # 设置权限为 rwxr-xr-x
    chmod +x script.sh # 添加执行权限
  • chown: 修改文件所有者。
    1
    chown user:group file.txt  # 修改所有者和所属组
  • chgrp: 修改文件所属组。
    1
    chgrp developers file.txt # 修改文件所属组

八、进程管理

1. kill vs pkill vs killall

  • kill: 通过 PID 终止进程。
    1
    kill 1234                  # 终止 PID 为 1234 的进程
  • pkill: 通过进程名终止。
    1
    pkill firefox              # 终止所有 Firefox 进程
  • killall: 类似 pkill(不同实现)。
    1
    killall nginx              # 终止所有 nginx 进程

总结技巧

  • 需要交互式操作:优先选择 less(文本查看)、htop(进程管理)。
  • 处理大文件或远程操作:使用 rsyncssh 组合命令。
  • 安全删除文件:推荐 trash-cli 代替 rm

通过理解这些命令的区别和适用场景,可以更高效地使用 Linux 命令行工具。

linux中不常见命令用法详解

以下是一些 Linux 中相对不常见但功能强大的命令及其详细解释,适用于高级用户或特定场景:


1. 文本处理类

comm

用途:比较两个已排序文件的行差异,输出三列结果(仅第一个文件、仅第二个文件、共有的行)。
示例

1
comm file1.txt file2.txt

参数

  • -1:隐藏仅第一个文件独有的行
  • -2:隐藏仅第二个文件独有的行
  • -3:隐藏共有的行

join

用途:基于共同字段(类似 SQL JOIN)合并两个已排序的文件。
示例

1
join -1 2 -2 1 file1.txt file2.txt  # 合并 file1 的第2列和 file2 的第1列

column

用途:将输入文本格式化为对齐的列(类似表格)。
示例

1
echo "Name Age\nAlice 30\nBob 25" | column -t

输出

1
2
3
Name   Age
Alice 30
Bob 25

2. 系统监控与调试

pidstat

用途:监控进程的 CPU、内存、I/O 等资源使用情况(需安装 sysstat 包)。
示例

1
pidstat -d 2  # 每2秒显示进程的磁盘I/O统计

mpstat

用途:报告 CPU 使用情况(多核细化统计)。
示例

1
mpstat -P ALL 1  # 每1秒显示所有CPU核心的利用率

lsof 的高级用法

用途:列出被进程打开的文件或网络连接。
示例

1
2
3
lsof -i :80          # 查看占用80端口的进程
lsof -u username # 查看某用户打开的文件
lsof /var/log/syslog # 查看正在使用某文件的进程

3. 网络工具

nc (netcat)

用途:网络调试工具(端口扫描、文件传输、代理等)。
示例

1
2
3
nc -zv example.com 80      # 检查端口是否开放
nc -l 1234 > received_file # 监听端口接收文件
echo "Hello" | nc -N example.com 80 # 发送数据到端口

ss (Socket Statistics)

用途:查看网络连接信息(替代 netstat)。
示例

1
ss -tunap  # 显示所有TCP/UDP连接及关联进程

4. 文件与磁盘

rename

用途:批量重命名文件(支持正则表达式)。
示例

1
rename 's/.txt/.md/' *.txt  # 将所有.txt扩展名改为.md

注意:不同发行版语法可能不同(Perl 或 C 版本)。


fallocate

用途:预分配或释放文件空间(无需填充内容)。
示例

1
2
fallocate -l 1G bigfile.img  # 快速创建1GB的空文件
fallocate -d sparse_file # 释放稀疏文件的空洞空间

debugfs

用途:手动修复 ext2/3/4 文件系统(谨慎使用)。
示例

1
2
3
debugfs /dev/sda1
debugfs: lsdel # 列出已删除但未覆盖的文件
debugfs: undel <inode> # 恢复指定inode的文件

5. 时间与计划任务

chronyc

用途:监控和调整 chronyd 时间同步服务。
示例

1
2
chronyc tracking    # 查看时间同步状态
chronyc sources -v # 列出时间源详细信息

6. 终端控制

script

用途:记录终端会话的所有输入输出。
示例

1
2
script -t 2> timing.log -a output.log  # 记录操作并保存时间戳
exit # 结束记录

回放

1
scriptreplay timing.log output.log

7. 其他实用工具

tac

用途:反向输出文件内容(cat 的逆序版)。
示例

1
tac file.txt  # 从最后一行开始显示

rev

用途:反转每行字符的顺序。
示例

1
echo "hello" | rev  # 输出 "olleh"

watch

用途:周期性执行命令并显示输出。
示例

1
watch -n 1 -d "ls -l"  # 每秒刷新并高亮变化

cal 的高级用法

示例

1
2
cal -3         # 显示上/当前/下月
cal -y 2024 # 显示2024全年日历

总结场景

  • 文本分析comm, join, column
  • 系统调试pidstat, lsof, debugfs
  • 网络诊断nc, ss
  • 批量操作rename, fallocate
  • 记录与回放script

这些命令在特定场景下能显著提高效率,但需谨慎使用系统级工具(如 debugfs)。