# 拷贝文件

  • 在本机上拷贝文件时:
    • 通常使用 cp 命令。
    • 跨磁盘拷贝文件时,两个磁盘分别承受读、写负载。在同一磁盘拷贝文件时,读、写负载同时作用于该磁盘,拷贝速度慢很多,不如创建硬链接。
  • 跨主机拷贝文件时:
    • 通常使用 scp、rsync 命令。
    • 跨主机拷贝文件时,磁盘 IO 速度可能比网络 IO 速度快多倍,比如 100MB/s 对 10MB/s 。建议先制作文件的压缩包,拷贝到目标主机之后再解压,使得总耗时更少,只是压缩、解压需要占用一些时间和 CPU 。
    • 拷贝大量小文件时,也建议制作压缩包。因为每个文件都需要拷贝一次文件元数据,增加了耗时。

# cp

$ cp <src_path> <dst_path>  # 将文件从源路径拷贝到目标路径
     -a       # 相当于-dpr
     -d       # 若源文件为 link file ,则复制 link file 的属性(而非文件本身)
     -p       # 将源文件的权限、属性也拷贝过去(否则会使用默认属性)
     -r       # 递归操作(用于复制目录)

     -f       # 若目标文件已存在,则删除它再尝试拷贝
     -i       # 若目标文件已存在,则提示用户是否进行覆盖
     -n       # 若目标文件已存在,则不覆盖
     -u       # --update ,当目标文件不存在,或源文件比目标文件更新时,才执行拷贝
     -v       # 显示执行过程的详细信息
  • Linux 发行版一般设置了 alias cp='cp -i' ,所以 -f 选项无效。
  • 例:
    cp f1 f2
    cp f1 f2 /tmp
    cp -r *  /tmp   # 源路径中包含通配符 * 时,不会拷贝隐藏文件
    cp -r .  /tmp
    cp -a *  /tmp
    
  • 执行 cp f1 f2 时:
    • 如果 f2 不存在,则会先创建一个空的 f2 文件,再将 f1 的内容拷贝过去。
    • 如果 f2 已存在,则会先将 f2 的内容清空,再将 f1 的内容拷贝过去,因此目标文件依然使用 f2 的 inode 号。
      • 如果该过程中有其它进程也在修改 f2 ,则会导致 cp 出错。

# ln

:用于创建文件的链接,并不会实际拷贝文件。

  • 命令:
    $ ln <src_path> <dst_path>  # 创建文件的硬链接
        -s    # 创建文件的软链接
        -f    # 若目标文件已存在,则覆盖它
    
    • 创建链接时,源路径、目标路径都必须是绝对路径。
    • 不支持给目录创建硬链接,不支持跨磁盘分区创建硬链接。
    • 可以给目录创建软链接,可以跨磁盘分区创建软链接。
  • 例:
    [root@CentOS ~]# ln -s /tmp tmp
    [root@CentOS ~]# ls -lh
    total 0
    lrwxrwxrwx 1 root root 4 Jan  8 14:21 tmp -> /tmp
    [root@CentOS ~]# rm -f tmp/       # 如果软链接文件指向一个目录,删除时不能加上 / 后缀,否则会被视作删除目标目录
    rm: cannot remove ‘tmp/’: Is a directory
    [root@CentOS ~]# rm -f tmp
    

# dd

:用于在本机上拷贝文件,还支持转换文件格式。不支持拷贝目录。

  • 命令:
    $ dd
          if=<file>          # 源文件,默认为 stdin
          of=<file>          # 目标文件,默认为 stdout
    
          count=<blocks>     # 拷贝多少个块(默认为拷贝全部数据)
          bs=<bytes>         # 读写数据时,内存缓冲区的大小。默认为 512 。取值过小会减慢速度,取值过大会占用大量内存
          ibs=<bytes>        # 每次读取多少字节的数据,默认为 512
          obs=<bytes>        # 每次写入多少字节的数据,默认为 512
    
    • dd 拷贝文件时,会以 ibs 为单位读取数据,放入内存缓冲区 bs ,然后以 obs 为单位写入目标文件。
  • 例:
    dd if=/dev/sda1 of=/dev/sda2    # 从 if 设备拷贝数据到 of 设备
    dd if=/dev/cdrom of=cd.iso      # 拷贝文件并转换成 iso 文件
    
  • 例:
    [root@CentOS ~]# dd if=/dev/urandom of=f1 bs=1M count=1024    # 拷贝生成一个指定大小、随机内容的文件
    1024+0 records in
    1024+0 records out
    1073741824 bytes (1.1 GB) copied, 74.6221 s, 14.4 MB/s
    [root@CentOS ~]# dd if=f1 of=f2 bs=1M                         # 拷贝文件,这也能测试磁盘的顺序读写速度
    1024+0 records in
    1024+0 records out
    1073741824 bytes (1.1 GB) copied, 7.92427 s, 136 MB/s
    

# scp

:安全拷贝协议(Secure copy protocol),用于在主机之间拷贝文件,基于 SSH 协议加密通信。

  • 命令:
    $ scp
          <file>... [email protected]:/root  # 将本机的文件拷贝到其它主机(需要通过 SSH 认证)
          [email protected]:/root/f1 /root   # 将其它主机的文件拷贝到本机的指定目录
          -C      # 传输数据流时启用压缩
          -P 22   # 指定 SSH 的端口
          -r      # 递归操作(用于拷贝目录)
    

# rsync

:用于在本机拷贝文件、目录,或跨主机拷贝。

  • 与 scp 相比:
    • rsync 将每个文件分成多个文件块传输,如果目标文件中已包含 md5 值相同的块,则不拷贝。因此支持断点续传、增量备份。
    • rsync 跨主机拷贝时,需要源主机、目标主机都安装了 rsync 。
  • 命令:
    $ rsync
            SRC... DEST             # 在本机拷贝文件(此时相当于 cp 命令)
            SRC... [USER@]HOST:DEST # 将本机的文件拷贝到其它主机
            [USER@]HOST:SRC... DEST # 将其它主机的文件拷贝到本机
            -e "ssh -p 1022"        # 修改 SSH 协议的配置参数
            -z                      # 传输数据流时启用压缩(不管是本机拷贝,还是跨主机拷贝)
    
            -a                      # 保留文件属性,且递归处理目录
            -P                      # 保留未完全拷贝的文件,并显示传输进度
            -q                      # --quite ,隐藏拷贝过程的信息,除非是报错
    
            --exclude=log/*         # 排除某些文件,不拷贝它们
            --ignore-existing       # 如果目标文件已存在,则不拷贝
            -u                      # --update ,如果目标文件已存在,且修改时间比源文件更新,则不拷贝
            --delete                # 删除目标目录比源目录多出的文件
            --inplace
            --append
    
    • 当 SRC 是目录时,如果以 / 结尾,则相当于 cp SRC/* DEST ,否则相当于 cp SRC DEST/SRC
    • 如果 DEST 目录不存在,则会自动创建。
  • 例:
    rsync -aP /tmp /data
    rsync -aP --inplace -e ssh  /root/f1 10.0.0.1:/root
    
  • rsync 将 src_file 拷贝文件到 dst_file 时:
    • 如果 dst_file 不存在(即目标文件路径未被占用),则从头拷贝 src_file 。
      • 拷贝时,默认先暂存到 DEST 目录下一个临时文件。比如拷贝 f1 文件时会暂存为 .f1.GRds8g 文件,等拷贝完才将它重命名为 f1 。如果拷贝中断,则删除该文件。
      • 启用 -P 选项时,即使未完全拷贝文件,rsync 就中断,也会将临时文件重命名为 dst_file 。此时该文件是不完整的, modify time 为 1970-01-01 。
    • 如果 dst_file 已存在,则检查其 md5 值、文件属性是否与 src_file 一致。
      • 如果相同,则不拷贝该文件。
      • 如果不同,则默认会从头拷贝 src_file 。
        • 例如事先用 cp 命令等其它方式拷贝该文件,即使已经拷贝完,也会因为文件的 modify time 与 src_file 不一致,导致 rsync 从头拷贝该文件。
        • 以下情况不会创建临时文件,而是直接保存到 dst_file 。
          • 启用 --inplace 选项时,会检查 dst_file 中各个文件块的 md5 值,如果与 src_file 不同,则拷贝该文件块。如果文件属性不同,则单独拷贝文件属性。
          • 启用 --append 选项时,会检查 dst_file 的长度,如果比 src_file 短,则拷贝缺少的字节到 dst_file 的末尾。因此不保证 dst_file 与 src_file 的长度、内容、文件属性一致。
        • 综上,如果想实现断点续传,避免从头拷贝文件,建议启用 -P 和 --inplace 选项。

# dump

dump、restore 命令用于备份本机的文件或目录,适用于 etx2、etx3、etx4 文件系统。

已淘汰不用
$ dump [option] <path>  # 备份指定的文件或目录
       -f <file>        # 保存为指定文件
       -[0-9]           # 设置备份级别
       -j               # 压缩为 bzip2 格式
  • 备份级别有 0~9 十种,0 是完全备份,1~9 都是增量备份。
    • 在备份整个分区或磁盘时才能使用增量备份。比如用 0 完全备份一次之后,可用 1 增量备份。下一次备份时,用 2 就是增量备份(级别加一),用 1 就是差异备份(覆盖之前的同级数据)。
  • dump 生成的备份文件并不是普通的压缩文件,还包含了一些备份信息,不能直接解压,只能被 restore 命令使用。
  • 例:
    dump -j -0f root.back.bz2 /root/
    
$ restore
         -f <file> # 指定备份文件(会根据其中的备份信息,还原到原路径)
         -r        # 用备份文件进行还原
         -t        # 显示备份文件的内容
         -C        # 比较当前文件与备份文件的差异(比如旧文件被修改、删除,但是增加新文件时不算差异)
  • restore 会生成一个 restoresymtable 文件,便于在增量备份时传递信息,可以删除。
  • 例:
    restore -tf root.back.bz2