tar命令

语法概述

虽然,gzip,bzip2,xz能够针对目录进行压缩,但其对目录压缩指的是”将目录内的所有文件 分别 进行压缩“。而非类似WINRAR这类软件,可以将很多文件打包成一个文件的样式。

tar不仅可以打包,还可以通过gzip/bzip2/xz打包的同时执行压缩。

打包并压缩

1
2
3
4
5
6
7
tar [-z | -j | -J] [cv] [-f tar文件名] 待打包对象           ===>tar -zcv -f  xxx.tar.gz sourcename 

#查看已经被打包并压缩的文件
tar [-z | -j | -J] [tv] [-f tar文件名] ===>tar -ztv -f xx.tar.gz

#解压缩
tar [-z | -j | -J] [xv] [-f tar文件名] [-C 目录] ===>tar -zxv -f xx.tar.gz -C /tmp

主要选项:(c,t,x三个选项不可同时出现在一条指令中,只需要记住c,t,x三个选项即可)

  • -c:建立打包文件,可搭配-v查看过程中被打包的文件名称
  • -t:tar包中包含哪些文件
  • -x:解包或解压缩,可以打包-C在特定目录中解包或解压缩

压缩选项

  • -z:通过gzip压缩和解压缩,其文件名最好指定为*.tar.gz
  • -j:通过bzip2压缩和解压缩,其文件名最好指定为*.tar.bz2
  • -J:通过xz压缩和解压缩,其文件名最好指定为*.tar.xz

其他选项

  • -v:在压缩/解压缩过程中显示详细信息
  • -f filename:-f选项后面需要立即跟上将要生成的打包压缩后的文件名称,建议-f选项单独写出来,不要跟上面的选项写在一起
  • -C 目录:用于解压缩时,在特定目录中解压缩
  • -p,--preserve-permissions:保留备份数据的原本权限和属性,常用于备份
  • -P:保留绝对完整路径,即允许备份数据中含有根目录
  • --xattrs:保留高级权限信息,例如ACL和SELinux上下问
  • --exclude=filename:在压缩过程中,不要将filename打包

tar注意事项

1.使用tar打包时,生成的打包文件的文件名如果与目标路径下的文件名冲突,tar会覆盖目标文件而且不会警告

2.在使用绝对路径打包时,将默认从文件名中删除该路径前面的/符号。

tarfile和tarball

需要指出的是,tar打包出来的文件,根据有没有进行压缩,其所产生的文件的称呼不同。
如果是tar-cv -f name.tar打包,则称为tarfile
如果还进行了压缩,则称为tarball

查看归档

1
2
3
4
5
6
7
8
9
10
# 查看归档文件中的信息
tar -ztv -f /root/etc.tar.gz
drwxr-xr-x root/root 0 2020-06-02 10:22 etc/
-rw-r--r-- root/root 546 2019-06-24 10:38 etc/fstab
-rw------- root/root 0 2019-06-05 11:37 etc/crypttab
lrwxrwxrwx root/root 0 2019-06-05 11:37 etc/mtab -> /proc/self/mounts
-rw-r--r-- root/root 53 2020-05-22 09:01 etc/resolv.conf
# 从上面可以看到,详细的文件权限属性都会被列出来,如果仅查看文件名,可以去掉-v选项,
# 另外可以发现每个文件名都没有了根目录,这是为了安全,放置解压时覆盖原始路径中的文件。
# 当然如果你确定将来解压的时候直接解压到原来的路径下,那么在打包的时候可以指定-P选项,保留完整路径信息。

打包

打包当前目录下的文件,不包含目录

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
# 首先需要cd到目标目录,然后执行
[root@vagrant ol8_19]# tar -czvp -f autoinstall_19c_on_ol8.7.tar.gz *
config/
config/install.env
config/vagrant.yml
README.md
scripts/
scripts/dbora.service
scripts/install_os_packages.sh
scripts/oracle_create_database.sh
scripts/oracle_service_setup.sh
scripts/oracle_software_installation.sh
scripts/oracle_software_patch.sh
scripts/oracle_user_environment_setup.sh
scripts/ords_software_installation.sh
scripts/prepare_disks.sh
scripts/root_setup.sh
scripts/server.xml
scripts/setup.sh
scripts/web.xml
software/
software/put_software_here.txt
software/apex_23.2_en.zip
software/ords-24.1.1.120.1228.zip
software/sqlcl-24.1.0.087.0929.zip
software/apache-tomcat-9.0.88.tar.gz
software/graalvm-jdk-17_linux-x64_bin.tar.gz
software/LINUX.X64_193000_db_home.zip
Vagrantfile

打包指定的绝对路径

情况如下:

1
2
3
4
5
6
7
[oracle@localhost ~]$ pwd
/home/oracle
[oracle@localhost ~]$ tar -czvp -f autoinstall_19c_on_ol8.7.tar.gz /vagrant
tar: Removing leading `/' from member names
/vagrant/
[oracle@localhost ~]$
# 这个warning并不影响最后执行的结果,但是十分影响美观。

tar命令会默认使用相对路径,如果使用绝对路径且不加相应参数时,就会出现此error。

其实也很简单,在tar命令的参数中加入-P参数即可。但是我们需要注意-P参数的位置,要将其放在-z和-f之间。即:

1
tar -czvpP -f autoinstall_19c_on_ol8.7.tar.gz /vagrant

备份/etc/目录(-p保留原始权限和属性信息)

1
2
3
4
5
6
7
8
9
10
11
time tar -zcvp -f /root/etc.tar.gz /etc
time tar -jcvp -f /root/etc.tar.bz2 /etc
time tar -Jcvp -f /root/etc.tar.xz /etc

[root@oradb2 ~]# du -sm /etc
38 /etc
[root@oradb2 ~]# ll -h /root/etc*
-rw-r--r-- 1 root root 9.3M Jun 4 17:07 /root/etc.tar.bz2
-rw-r--r-- 1 root root 11M Jun 4 17:03 /root/etc.tar.gz
-rw-r--r-- 1 root root 7.5M Jun 4 17:08 /root/etc.tar.xz
从上面可以看到xz默认压缩比最高,但相对的花费时间也最多

打包指定目录,但排除特定文件

1
2
# 打包/root/目录,但排除特定文件
tar -zcv -f /root/system.tar.gz --exclude=/root/*.gz --exclude=/root/system.tar.gz /root/

时间选项

仅备份比某个时刻还要新的文件
此时,--newer-mtime选项就需要用到了,其实是有两个选项,一个是--newer,另一个是--newer-mtime

当使用--newer时,表示后续的日期包含【mtimectime】,而--newer-mtime则仅是mtime而已

1
tar -zcv -f /root/newer.tar.gz --new-mtime="2020/06/03" /etc/*

解包

解压到指定目录

1
tar -zxv -f etc.tar.gz -C /tmp/test

仅解压单一文件

1
2
3
4
5
6
7
8
9
#在tar包中搜索
tar -ztv -f /root/etc.tar.gz | grep 'shadow'

#解压单一文件
[root@oradb2 ~]# tar -zxv -f etc.tar.gz etc/shadow
etc/shadow
[root@oradb2 ~]# ll etc/
total 4
---------- 1 root root 1374 Jul 31 2019 shadow

一次性解压多个tar.gz

1
$ for files in ./*.tar.gz; do tar -zxvf $files -C /tmp/; done

不包含父目录

1
2
3
4
5
6
7
8
[root@88a920042b2f httpd-2.4.54]# tar -ztvf apr-1.7.0.tar.gz
drwxr-xr-x wrowe/wrowe 0 2019-04-02 01:56 apr-1.7.0/ #解压时不要apr-1.7.0
-rw-r--r-- wrowe/wrowe 488 2004-11-25 06:51 apr-1.7.0/emacs-mode
drwxr-xr-x wrowe/wrowe 0 2019-04-02 01:56 apr-1.7.0/passwd/
-rw-r--r-- wrowe/wrowe 6930 2013-10-03 23:22 apr-1.7.0/passwd/apr_getpass.c
-rw-r--r-- wrowe/wrowe 4615 2019-03-26 14:09 apr-1.7.0/Makefile.win
-rw-r--r-- wrowe/wrowe 13369 2016-12-04 00:26 apr-1.7.0/CMakeLists.txt
[root@88a920042b2f httpd-2.4.54]# tar -zxf apr-1.7.0.tar.gz --strip-components 1 -C ./srclib/apr

不包含原目录

解压时不包含原目录:--strip-components 1 解压至下一级目录,若为2则解压至下下级目录
比如,log.tar.gz中压缩了test目录,常规解压时会自动创建test目录

1
tar -zxvf log.tar.gz --strip-components 1 -C /dir1  # 将直接在dir1下展开test目录中的内容

tar到磁带

磁带机由于是一次性读取/写入设备,因此不能够使用cp指令来复制。

如果想要将/home,/root,/etc备份到磁带机/dev/st0,则:

1
tar -cv -f /dev/st0 /home /root /etc

打包和解压进度条

tar配合pv命令实现打包和解压进度条:
压缩文件时,在targzip中间使用pv,把待压缩的文件的大小传递给pv: 测试有效

1
tar -cf - a.csv | pv -s $(du -sb a.csv | awk '{print $1}') | gzip > a.tgz

其中,横线表示把tar的结果传送到标准输出,以作为gzip的输入。

解压缩:

1
pv question.tar.gz | tar -zxf -

直接把文件传递给pvpv把文件读取到stdout,作为tar的输入。

tar和管道

1
tmp>tar -cvf - /etc | tar -xvf -

上面的指令,有点类似cp -r /etc /tmp,那么为何不直接使用cp -r /etc /tmp呢?
自然是cp -r有些麻烦,而且不想让中间文件存在,哈哈。
注意:输出文件变成了“-”,输入文件也变成“-”,这就代表打包生成的文件。

tar和selinux

通常大部分情况下,用不到使用tar的备份直接恢复系统文件,但如果你这么做,需要特别留意selinux的问题,尤其是系统文件,例如/etc目录下的文件。

虽然可以通过tar备份/etc/,并且也可以将其在其他机器上恢复,但是恢复后是无法进入系统的,虽然单人维护模式看起来一切正常。大部分原因是因为/etc/shadow文件的selinux类型在还原时被更改了。
对于上面的问题,如何处理呢?有以下几种方式:

  1. 通过各种救援方式进入系统,然后修改/etc/selinux/config文件,将selinux改为permissive模式,重启。
  2. 在第一次恢复后,不要立即重启,先使用restorecon -Rv /etc自动修复一下SElinux的类型即可
  3. 通过各种救援方式进入系统,创建/.autorelabel文件,重新启动后系统会自动修复selinux的类型,并且会自动再次重启,之后恢复正常。