Linux以 cp/rsync 命令编写 shell 脚本

工作中遇到的问题,方便自己记录

文章目录


前言

最近甲方服务器内存不足,在转移了2022年以前的数据之后,web 端页面的头像和培训课件试题的签名图片都报404。一是甲方不会扩容要求我们帮忙,二是领导给了个治标不治本的方法(缺啥补啥,主要还是他们拖着不给钱…)。本篇以 Linux 界面的 cp 和 rsync 命令解决页面存在绝对路径但资源服务器为空的情况,需要复制备份的文件夹至对应的文件夹。


一、Linux的复制命令

(一)cp 命令是用于复制目录和文件的命令,它的一般语法如下:

cp [选项] 源文件 目标文件

常用的 cp 命令选项包括:

  • -r 或 --recursive: 递归地复制目录及其内容。
  • -p 或 --preserve: 保留文件的元数据(例如权限、所有者、时间戳等)。
  • -u 或 --update: 只复制源文件中较新的文件到目标文件,不覆盖已存在的较新文件。
  • -v 或 --verbose: 显示复制的详细信息。
  • -i 或 --interactive: 在复制前提示用户是否覆盖已存在的目标文件。

以下是一些常见的 cp 命令用法示例:

  1. 复制文件到目标目录:
cp file.txt /path/to/destination/
  1. 复制目录及其内容到目标目录:
cp -r directory /path/to/destination/
  1. 保留文件元数据并显示详细信息:
cp -pv file.txt /path/to/destination/
  1. 只复制较新的文件到目标目录:
cp -u file.txt /path/to/destination/
  1. 提示是否覆盖已存在的目标文件:
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 命令用法示例:

  1. 复制本地文件或目录到远程服务器:
rsync -avz /home/backup username@remote:/path/to/destination
  1. 从远程服务器复制文件或目录到本地:
rsync -avz username@remote:/home/backup /path/to/destination
  1. 通过 SSH 连接复制文件或目录:
rsync -avz -e ssh /home/backup username@remote:/path/to/destination
  1. 仅复制更新或新增的文件:
rsync -avz --update /home/backup /path/to/destination
  1. 同步两个目录,使目标目录与源目录保持一致:
rsync -avz --delete /home/backup /path/to/destination
  1. 复制时显示详细输出:
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错误。好家伙,直接省去了我在页面一个一个点(只能说经验都是攒出来的)。

Fiddler界面

页面开发者模式
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

代码逻辑如下:

  1. 遍历 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

代码逻辑如下:

  1. 首先通过循环将连续的数字范围(从 7882 到 7885)添加到 folders 数组中。
  2. 其次将不连续的数字(500、652)追加到数组中。
  3. 最后遍历 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

代码逻辑如下:

  1. copy_directory 函数用于复制文件夹及其内容。它接受源文件夹路径和目标文件夹路径作为参数,检查源文件夹是否存在,如果存在则使用 rsync 命令复制文件夹及其内容到目标文件夹,并输出相应的消息。
  2. 主循环部分遍历了 folders 数组中的每个元素。如果元素是一个范围,根据范围的起始和结束值遍历对应的文件夹。如果元素不是范围,直接处理单个文件夹。
  3. 对于每个文件夹,使用 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 脚本处理,目的是为了后续迁移做准备(前提是甲方自己扩容了,难啊…)

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ViperSummer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值