工作中遇到的问题,方便自己记录
文章目录
前言
最近甲方服务器内存不足,在转移了2022年以前的数据之后,web 端页面的头像和培训课件试题的签名图片都报404。一是甲方不会扩容要求我们帮忙,二是领导给了个治标不治本的方法(缺啥补啥,主要还是他们拖着不给钱…)。本篇以 Linux 界面的 cp 和 rsync 命令解决页面存在绝对路径但资源服务器为空的情况,需要复制备份的文件夹至对应的文件夹。
一、Linux的复制命令
(一)cp 命令是用于复制目录和文件的命令,它的一般语法如下:
cp [选项] 源文件 目标文件
常用的 cp 命令选项包括:
- -r 或 --recursive: 递归地复制目录及其内容。
- -p 或 --preserve: 保留文件的元数据(例如权限、所有者、时间戳等)。
- -u 或 --update: 只复制源文件中较新的文件到目标文件,不覆盖已存在的较新文件。
- -v 或 --verbose: 显示复制的详细信息。
- -i 或 --interactive: 在复制前提示用户是否覆盖已存在的目标文件。
以下是一些常见的 cp 命令用法示例:
- 复制文件到目标目录:
cp file.txt /path/to/destination/
- 复制目录及其内容到目标目录:
cp -r directory /path/to/destination/
- 保留文件元数据并显示详细信息:
cp -pv file.txt /path/to/destination/
- 只复制较新的文件到目标目录:
cp -u file.txt /path/to/destination/
- 提示是否覆盖已存在的目标文件:
cp -i file.txt /path/to/destination/
特别提醒:cp 命令的使用可能会受到用户权限和目标文件系统的限制。
(二)rsync 是一个强大的文件同步和备份工具,用于在本地或远程系统之间进行文件的同步、复制和备份。它的一般语法如下:
rsync [选项] 源文件 目标文件
常用的 rsync 命令选项包括:
- -a 或 --archive:启用归档模式,该模式将递归复制目录、保持文件属性和权限,并保留符号链接、设备文件等。
- -v 或 --verbose:显示详细的输出信息,包括复制的文件列表和详细的进度信息。
- -z 或 --compress:在传输过程中启用数据压缩,减少传输的数据量,提高传输速度。
- -r 或 --recursive:递归复制目录及其内容,包括子目录和文件。
- -u 或 --update:仅复制源目录中更新或更改的文件,跳过已存在且未发生更改的文件。
- -l 或 --links:保留符号链接,即复制符号链接所指向的文件或目录,而不是复制符号链接本身。
- -p 或 --perms:保留源文件的权限设置,包括所有者、组和权限。
- -t 或 --times:保留源文件的时间戳,包括访问时间和修改时间。
- -P 或 --partial --progress:支持断点续传,复制过程中断后,可以从中断点继续复制,并显示复制的进度信息。
以下是一些常见的 rsync 命令用法示例:
- 复制本地文件或目录到远程服务器:
rsync -avz /home/backup username@remote:/path/to/destination
- 从远程服务器复制文件或目录到本地:
rsync -avz username@remote:/home/backup /path/to/destination
- 通过 SSH 连接复制文件或目录:
rsync -avz -e ssh /home/backup username@remote:/path/to/destination
- 仅复制更新或新增的文件:
rsync -avz --update /home/backup /path/to/destination
- 同步两个目录,使目标目录与源目录保持一致:
rsync -avz --delete /home/backup /path/to/destination
- 复制时显示详细输出:
rsync -avz --progress /home/backup /path/to/destination
二、使用步骤
(一)直接了当
cp -r /home/backup/7782 /path/to/destination/
cp -r /home/backup/3709 /path/to/destination/
【真】缺啥补啥...不仅要点击页面的签名照找对应文件夹,还要在命令行界面一条一条执行 cp 命令,等待复制过程。
(二)编写shell脚本
1、touch 一个 shell 脚本直接存放一条一条 cp 命令。在测试其他项目期间,无意中发现 Fiddler 抓包抓到了404错误。好家伙,直接省去了我在页面一个一个点(只能说经验都是攒出来的)。
F12没有输出指定的错误。
2、直接 sh 执行脚本
3、完善了一下“傻瓜式”复制,直接用循环搞定(主要还是手酸…)
#!/bin/bash
folders=(7782 7783 7784 500 652)
for folder in "${folders[@]}"; do
cp -r "/home/backup/$folder" "/path/to/destination/"
done
代码逻辑如下:
- 遍历 folders 数组中的每个元素,并将其与路径组合后执行复制操作。
4、针对纯数字文件夹的范围完善脚本
貌似比之前方便很多,省去了页面寻找对应文件夹和逐个等待复制时间。但甲方反馈基本所有账号都有问题(意料之中),且发现一些文件夹名称都是连续的。比如7882 7883 7884 7885,bash 中的数组又不支持直接使用 7882-7885 这种范围表示法。 索性多加个循环:
#!/bin/bash
folders=()
# 添加连续的数字范围
for ((i = 7882; i <= 7885; i++)); do
folders+=("$i")
done
# 添加不连续的数字
folders+=(500 652)
for folder in "${folders[@]}"; do
cp -r "/home/backup/$folder" "/path/to/destination/"
done
代码逻辑如下:
- 首先通过循环将连续的数字范围(从 7882 到 7885)添加到 folders 数组中。
- 其次将不连续的数字(500、652)追加到数组中。
- 最后遍历 folders 数组中的每个元素,并将每个文件夹复制到目标目录中。
特别提醒:这里就出现了两个问题,一个是没法直接往 folders 数组输入数字,对于分企业出现的用户对应不同的文件夹,还要筛选完填入到循环中。第二个是如果多个范围数字,则需要嵌套多个循环,再加入到数组中复制。
5、针对该情况使用 rsync 命令实现
(1)目标文件夹及文件存在,跳过
(2)给定的文件夹不存在,打印不存在信息
(3)目标文件夹不是最新的,仅复制文件最新(根据时间戳)
此处虽然 cp 命令再加检测代码可以做,但是另一个复制的命令 rsync 含有这个(1)和(3)功能,索性直接用 rsync 命令
#!/bin/bash
folders=(7782-7785 500 652)
source_directory="/home/backup/"
destination_directory="/path/to/destination/"
# 函数:复制文件夹及其内容
copy_directory() {
local folder_path="$1"
local destination="$2"
if [ -d "$folder_path" ]; then
rsync -aur "$folder_path" "$destination"
echo "已更新文件夹 $folder_path"
else
echo "文件夹 $folder_path 不存在"
fi
}
# 复制文件夹
for folder in "${folders[@]}"; do
if [[ $folder =~ ^[0-9]+-[0-9]+$ ]]; then
start=$(echo "$folder" | cut -d'-' -f1)
end=$(echo "$folder" | cut -d'-' -f2)
if [[ $start -gt 0 && $end -ge $start ]]; then
for ((i = start; i <= end; i++)); do
folder_path="$source_directory/$i"
copy_directory "$folder_path" "$destination_directory"
done
else
echo "无效的数字范围: $folder"
fi
else
folder_path="$source_directory/$folder"
copy_directory "$folder_path" "$destination_directory"
fi
done
代码逻辑如下:
- copy_directory 函数用于复制文件夹及其内容。它接受源文件夹路径和目标文件夹路径作为参数,检查源文件夹是否存在,如果存在则使用 rsync 命令复制文件夹及其内容到目标文件夹,并输出相应的消息。
- 主循环部分遍历了 folders 数组中的每个元素。如果元素是一个范围,根据范围的起始和结束值遍历对应的文件夹。如果元素不是范围,直接处理单个文件夹。
- 对于每个文件夹,使用 copy_directory 函数复制文件夹及其内容到目标文件夹。如果文件夹不存在,输出相应的错误消息。
特别提醒:在运行脚本之前,要确保目标文件夹 /path/to/destination/ 已经存在,并且有写入权限。此外,还要确保源文件夹 /home/backup/ 中包含要复制的文件夹。
可能遇到的问题
(一)数组的元素用双引号单独隔开
#!/bin/bash
folders=("7782" "7783" "7784" "500" "652")
for folder in "${folders[@]}"; do
cp -r "/home/backup/$folder" "/path/to/destination/"
done
特别提醒:一些文件夹不是纯数字的,比如 My Folder会被识别为 2 个元素,故需使用双引号隔开避免
(二)由于我 tomcat 用户没有权限创建文件,申请 sudo 权限创建 shell 脚本(前提是有给你 sudo 权限…)
(三)如果本章没有符合问题的选项,可以运行 man cp 或 man rsync 命令查看更多详细信息。
总结
以上是自己针对工作中遇到的 cp 和 rsync 命令常用的用法,因为工作量大不得不使用 shell 脚本处理,目的是为了后续迁移做准备(前提是甲方自己扩容了,难啊…)