#!/bin/bash
# 生产环境磁盘格式化与挂载脚本
# 功能:安全地格式化磁盘为XFS,创建挂载点,配置自动挂载
set -euo pipefail # 启用严格模式
SCRIPT_NAME=$(basename "$0")
LOG_FILE="/var/log/disk_init.log"
# 日志函数
log() {
local level=$1
shift
local message="$*"
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] [$level] $message" | tee -a "$LOG_FILE"
}
# 错误处理函数
error_exit() {
log "ERROR" "$1"
exit "${2:-1}"
}
# 使用说明
usage() {
cat << EOF
Usage: $SCRIPT_NAME <disk_device>
Example: $SCRIPT_NAME /dev/vdb
安全注意事项:
1. 此脚本会永久擦除指定磁盘上的所有数据
2. 请确认磁盘设备路径正确,避免误操作系统盘
3. 建议在生产环境使用前在测试环境验证
EOF
}
# 参数验证
validate_parameters() {
if [ $# -ne 1 ]; then
usage
error_exit "参数错误:需要且只能指定一个磁盘设备参数" 1
fi
local disk=$1
# 检查磁盘设备是否存在且为块设备
if [ ! -b "$disk" ]; then
error_exit "磁盘设备 $disk 不存在或不是块设备" 2
fi
# 防止误操作系统盘或其他关键磁盘
local critical_disks=("/dev/sda" "/dev/vda" "/dev/nvme0n1" "/dev/mmcblk0")
for critical_disk in "${critical_disks[@]}"; do
if [[ "$disk" == "$critical_disk"* ]]; then
error_exit "安全警告:$disk 可能是系统盘,禁止操作!" 3
fi
done
# 检查磁盘是否已被挂载
if mount | grep -q "^$disk"; then
log "WARNING" "磁盘 $disk 当前已被挂载,尝试卸载..."
safe_umount "$disk"
fi
}
# 安全卸载函数
safe_umount() {
local disk=$1
local mount_point=$(mount | grep "^$disk" | awk '{print $3}')
if [ -n "$mount_point" ]; then
log "INFO" "卸载磁盘 $disk (挂载点: $mount_point)"
# 检查是否有进程正在使用挂载点
if lsof "$mount_point" &>/dev/null; then
log "WARNING" "有进程正在使用 $mount_point,尝试终止相关进程..."
fuser -km "$mount_point" # 终止使用该挂载点的进程
sleep 2
fi
if ! umount "$disk"; then
error_exit "无法卸载磁盘 $disk" 4
fi
log "INFO" "卸载成功"
fi
}
# 检查必要工具
check_dependencies() {
local dependencies=("blkid" "mkfs.xfs" "lsof" "fuser")
for cmd in "${dependencies[@]}"; do
if ! command -v "$cmd" &>/dev/null; then
error_exit "缺少必要工具: $cmd,请先安装" 5
fi
done
}
# 确认操作
confirm_operation() {
local disk=$1
cat << EOF
!!! 安全警告 !!!
您即将执行以下操作:
1. 磁盘设备: $disk
2. 操作: 格式化磁盘为XFS文件系统
3. 挂载点: /export
4. 数据: 该磁盘上的所有数据将被永久删除!
请确认:
- 您已备份重要数据
- 磁盘设备路径正确
- 这不是系统盘
EOF
read -p "确认继续操作?(输入 'YES' 继续): " confirmation
if [ "$confirmation" != "YES" ]; then
log "INFO" "用户取消操作"
exit 0
fi
}
# 格式化磁盘
format_disk() {
local disk=$1
log "INFO" "开始格式化磁盘 $disk 为 XFS 文件系统"
# 检查磁盘是否已被使用
if blkid "$disk" &>/dev/null; then
local current_fs=$(blkid -s TYPE -o value "$disk" 2>/dev/null || echo "unknown")
log "WARNING" "磁盘 $disk 已有文件系统: $current_fs"
fi
# 使用更安全的格式化选项
if ! mkfs.xfs -f -i size=512 -l size=128m -d su=64k,sw=4 "$disk"; then
error_exit "磁盘格式化失败" 6
fi
log "INFO" "磁盘格式化成功"
}
# 准备挂载点
prepare_mountpoint() {
local mount_point="/export"
# 检查挂载点是否已被使用
if mount | grep -q " $mount_point "; then
local mounted_device=$(mount | grep " $mount_point " | awk '{print $1}')
log "WARNING" "挂载点 $mount_point 已被 $mounted_device 使用"
if ! umount "$mount_point"; then
error_exit "无法卸载现有的挂载点 $mount_point" 7
fi
fi
# 创建挂载点目录
mkdir -p "$mount_point"
if [ $? -ne 0 ]; then
error_exit "创建挂载点目录失败" 8
fi
log "INFO" "挂载点准备完成: $mount_point"
}
# 挂载磁盘
mount_disk() {
local disk=$1
local mount_point="/export"
log "INFO" "挂载磁盘 $disk 到 $mount_point"
if ! mount "$disk" "$mount_point"; then
error_exit "磁盘挂载失败" 9
fi
# 验证挂载是否成功
if ! mountpoint -q "$mount_point"; then
error_exit "挂载验证失败" 10
fi
log "INFO" "挂载成功"
}
# 配置自动挂载
configure_fstab() {
local disk=$1
local mount_point="/export"
log "INFO" "配置自动挂载"
# 获取UUID
local uuid=$(blkid -s UUID -o value "$disk")
if [ -z "$uuid" ]; then
error_exit "获取磁盘UUID失败" 11
fi
local fstab_entry="UUID=$uuid $mount_point xfs defaults,noatime,nodiratime 0 0"
# 备份fstab文件
cp /etc/fstab "/etc/fstab.backup.$(date +%Y%m%d_%H%M%S)"
# 移除已有的相关条目
sed -i.bak "\|$mount_point|d" /etc/fstab
sed -i.bak "\|^UUID=$uuid|d" /etc/fstab
# 添加新条目
echo "$fstab_entry" >> /etc/fstab
# 验证fstab语法
if ! mount -a &>/dev/null; then
# 恢复备份
cp /etc/fstab.bak /etc/fstab
error_exit "fstab 配置错误,已恢复备份" 12
fi
log "INFO" "自动挂载配置完成 (UUID: $uuid)"
}
# 创建数据目录
create_data_directory() {
local data_dir="/export/Data"
mkdir -p "$data_dir"
chmod 755 "$data_dir"
# 设置合适的权限
if [ ! -d "$data_dir" ]; then
error_exit "创建数据目录失败" 13
fi
log "INFO" "数据目录创建完成: $data_dir"
}
# 显示摘要信息
show_summary() {
local disk=$1
local mount_point="/export"
cat << EOF
操作完成摘要:
==============
磁盘设备: $disk
文件系统: $(blkid -s TYPE -o value "$disk")
UUID: $(blkid -s UUID -o value "$disk")
挂载点: $mount_point
数据目录: $mount_point/Data
挂载状态: $(mount | grep "^$disk" && echo "已挂载" || echo "未挂载")
磁盘空间信息:
==============
$(df -h "$mount_point")
EOF
}
# 主函数
main() {
log "INFO" "脚本开始执行: $SCRIPT_NAME $*"
# 检查依赖
check_dependencies
# 验证参数
validate_parameters "$@"
local disk=$1
# 用户确认
confirm_operation "$disk"
# 执行操作序列
format_disk "$disk"
prepare_mountpoint
mount_disk "$disk"
configure_fstab "$disk"
create_data_directory
# 显示结果
show_summary "$disk"
log "INFO" "脚本执行完成"
}
# 信号处理
trap 'error_exit "脚本被用户中断" 130' INT TERM
# 执行主函数
main "$@"
split 命令是 Linux 系统中一个非常有用的工具,用于将大文件分割成多个较小的文件。这种方法在处理大文件时非常有用,特别是在需要传输大文件或在磁盘空间有限的情况下下面是 split 命令的详细解释,包括其选项和用法。
基本用法
split 命令的基本语法如下:
split [选项] [输入文件] [输出文件前缀]
输入文件:要分割的文件。如果省略,则从标准输入读取。
输出文件前缀:分割后的文件将以此前缀命名,后跟一个字母或数字后缀(默认情况下,后缀从 aa 开始,依次递增)。
常用选项
-l, --lines=行数:按行数分割文件。例如,-l 1000 表示每 1000 行分割一次。
-b, --bytes=大小:按字节大小分割文件。例如,-b 10M 表示每 10MB 分割一次。
-C, --line-bytes=大小:按行分割文件,但每个输出文件的大小不超过指定的字节数。
-a, --suffix-length=长度:指定后缀的长度,默认为 2。
-d, --numeric-suffixes:使用数字后缀而不是字母后缀。
–additional-suffix=后缀:为每个输出文件添加额外的后缀。
–filter=命令:在写入输出文件之前,通过指定的命令过滤输入。
示例
按行数分割文件
split -l 1000 largefile.txt split_file_
这将 largefile.txt 按每 1000 行分割成多个文件,文件名从 split_file_aa 开始,依次递增。
按字节大小分割文件
split -b 10M largefile.txt split_file_
这将 largefile.txt 按每 10MB 分割成多个文件,文件名从 split_file_aa 开始,依次递增。
使用数字后缀
split -d -l 1000 largefile.txt split_file_
这将 largefile.txt 按每 1000 行分割成多个文件,文件名从 split_file_00 开始,依次递增。
添加额外的后缀
split -l 1000 --additional-suffix=.txt largefile.txt split_file_
这将 largefile.txt 按每 1000 行分割成多个文件,文件名从 split_file_aa.txt 开始,依次递增。
合并分割的文件
使用 cat 命令可以轻松地将分割的文件合并回原文件:
cat split_file_* > largefile.txt
注意事项
文件名冲突:确保输出文件的前缀不会与现有文件名冲突,以避免覆盖重要数据。
文件顺序:当合并文件时,确保按正确的顺序合并文件,特别是当使用字母后缀时。
性能考虑:分割大文件可能会消耗大量的磁盘 I/O 和 CPU 资源,特别是在按行分割时,因为需要读取和处理每一行。
通过 split 命令,你可以有效地管理大文件,特别是在需要传输或存储大文件时。了解和使用 split 的各种选项,可以根据不同的需求灵活地分割文件。
connection
在使用网络应用程序时,遇到 Connection refused 和 Connection timed out 错误是比较常见的。这两个错误通常指示不同类型的问题。以下是它们可能的原因和一些解决方案:
Connection Refused
原因:
服务未运行:目标服务器上的服务(如 SSH、HTTP 等)未启动。
端口未开放:请求连接的端口在目标服务器上没有监听服务。
防火墙阻止:防火墙配置阻止了连接请求。
错误的 IP 地址或端口:连接请求使用了错误的 IP 地址或端口。
服务器配置错误:服务器配置不正确,导致服务无法正确响应连接请求。
解决方案:
检查目标服务器上的服务是否正在运行。例如,使用 systemctl status <service> 检查服务状态。
确认服务正在监听正确的端口。使用 netstat -tuln 或 ss -tuln 查看监听的端口。
检查防火墙设置,确保允许所需的端口通过。使用 iptables 或 firewalld 进行配置。
确认使用的 IP 地址和端口是正确的。
查看服务器日志文件以获取更多错误信息。
Connection Timed Out
原因:
网络不通:网络连接中断或网络路径不通。
服务器过载:服务器负载过高,无法及时响应请求。
防火墙配置:防火墙规则可能导致连接被丢弃而不是拒绝。
网络延迟:网络延迟过高,导致连接请求超时。
路由问题:网络路由配置错误或不稳定。
解决方案:
使用 ping 或 traceroute 检查网络连通性和路径。
检查服务器负载,使用 top 或 htop 查看服务器资源使用情况。
检查防火墙配置,确保规则不会无意中丢弃合法流量。
如果网络延迟是问题的根源,考虑优化网络路径或使用更快的网络连接。
检查路由配置,确保没有错误或不稳定的路由。
总结
Connection Refused 通常意味着你的请求成功到达了目标服务器,但由于某种原因被服务器拒绝。
Connection Timed Out 通常意味着请求无法在规定的时间内到达目标服务器,可能是由于网络问题或服务器未响应。
通过这些检查和调整,你应该能够诊断并解决大多数 Connection refused 和 Connection timed out 问题。
在 Linux 中,去除字符串首尾的空白字符(包括空格、制表符、换行符等)可以通过多种方法实现。这里介绍几种常用的方法,包括使用 bash 内置命令、awk、sed 和 xargs 等工具。
- 使用 xargs
xargs 是一个非常方便的工具,用于构建和执行命令行。它可以用来去除字符串的首尾空白字符。
echo " 这是一个测试字符串 " | xargs
这将输出:
这是一个测试字符串
- 使用 awk
awk 是一个强大的文本处理工具,可以用来处理和格式化文本数据。
echo " 这是一个测试字符串 " | awk '{print $0}'
这也会输出:
这是一个测试字符串
- 使用 sed
sed 是一个流编辑器,可以用来过滤和转换文本。
echo " 这是一个测试字符串 " | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
这将去除字符串首尾的所有空白字符,输出:
这是一个测试字符串
- 使用 bash 参数扩展
在 bash 脚本中,可以使用参数扩展来去除变量值的首尾空白字符。
str=" 这是一个测试字符串 "
str="${str#"${str%%[![:space:]]*}"}" # 去除前导空白
str="${str%"${str##*[![:space:]]}"}" # 去除尾随空白
echo "$str"
这也会输出:
这是一个测试字符串
- 使用 tr 命令
tr 命令可以用来删除或替换字符。
echo " 这是一个测试字符串 " | tr -d '[:space:]'
但是,这个命令会删除字符串中的所有空白字符,包括中间的空格。如果你只想去除首尾的空白字符,上述 xargs、awk、sed 或 bash 参数扩展的方法会更合适。
选择合适的方法
xargs 是最简单直接的方法,适合快速去除字符串首尾的空白字符。
awk 和 sed 提供了更灵活的文本处理能力,适合需要进行更复杂文本处理的场景。
bash 参数扩展 适合在 bash 脚本中使用,提供了一种内置的方式来处理字符串。
tr 适合删除或替换特定字符,但不适合仅去除首尾空白。
根据你的具体需求和使用场景选择最合适的方法。对于大多数简单的去除首尾空白字符的需求,xargs 是一个非常方便的选择。