“包”治百病,归档和压缩(TAR&JAR)

「这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战」。

我发现我自己和我的同学们总是记不住很多工具命令,尤其是tar和jar命令,要用的时候都是面向Google编程。

归档命令-tar

tar是一个古老的Linux命令,了解基本功能可对付80%的备份需求,了解更细节的用法则可得心应手。

基本功能

基本功能就是 归档和提取。

归档和提取

tar基本功能就是将多个文件火目录归档到一个归档文件里,并且以后可以从归档文件里提取出原来的文件内容。 如下:

tar3.png

  • 当我们将多个文件火目录归档到一个归档文件时,需要使用-c功能,tar -cf archive.tar foo bar将foo bar归档到archive.tar里面。
  • 当我们从归档文件里提取出原来的文件内容时,需要使用-x功能,tar -xf archive.tar提取archive.tar里的文件到当前目录。

我们可以发现基本功能后面都使用了f选项,去掉f选项将不能正常工作,这是为什么呢?

因为在tar的设计里面-f 后面接归档的文件名字,比如这里就是archive.tar;不论是归档还是提取,这个f后面都是接归档的文件名字。

我们需要知道归档文件的内容才好提取文件到目录(不然可能存在安全的问题),那tar也提供了查询归档文件内容的功能。

Table列出

tar2.png

t(table)表示列出包里面的内容,-v显示功能动作具体的执行过程,如下:

扫描二维码关注公众号,回复: 13211363 查看本文章
# tar tvf archive.tar 
-rwxr-xr-x root/root       106 2021-11-15 21:48 hello
-rw-r--r-- root/root         0 2021-11-15 23:18 hello2
复制代码

tar的使用风格比较古老,tar tvf archive.tar tar -tvf archive.tar 等价。

更多功能-细节&高效

tar还提供很多细节功能:

  • 追加内容
  • 提取部分内容
  • 创建过程,可以排除文件
  • 压缩和解压缩
    • -j 支持bg2压缩格式
    • -z 支持gz压缩

添加上额外功能后,整个tar的功能图变得生动起来了:

tar4.png

  • -r 追加,使用tar -rvf archive.tar /zhangsan可以将 /zhangsan目录加到archive.tar 里面
  • 还可以只提取某一个文件,并且指定提取到目录,这里tar -xf archive.tar file1 -C /tmp/提取file1到指定目录/tmp/
  • -p 后面不跟参数,归档时文件权限保留
  • -z和-j都表示归档文件是压缩文件,只是格式不一样
  • 对于tar.gz 格式的归档文件,归档和压缩时都加-z,tar.bzip一样
  • tar -cvzf backup.tar.gz ... 创建tar.gz的归档文件,对于这样的文件,t和x操作的时候可以不加z选项。

Java打包-jar包

jar和tar非常的类似,jar(Java Archive)能够将多个源码、资源等文件打包并压缩到一个归档文件中。也支持更新、查看、提取。 更重要的是,jar包可以按照各种java程序运行的约定去打包。

基本功能

  • 基本功能也是c x t,这几个选项基本和tar的对应的用法一模一样
  • u 更新文件,相当于tar的r
  • v:显示详细过程
  • f:指明jar文件的名字

具体如下图所示

jar2.png

可以看出,功能上jar和tar非常的类似,甚至在提取和查看时,直接用tar命令也是可以的。

但是JAR 创建包的时候会默认加上一个 META-INF/MANIFEST.MF,如下演示:

# jar cvf doc.jar A.md
# jar tf doc.jar
META-INF/
META-INF/MANIFEST.MF
A.md
# jar xf doc.jar  META-INF/MANIFEST.MF
# cat META-INF/MANIFEST.MF
Manifest-Version: 1.0
Created-By: 12.0.2 (Oracle Corporation)
复制代码

也可以使用unzip -p控制台查看:

# unzip -p doc.jar  META-INF/MANIFEST.MF
Manifest-Version: 1.0
Created-By: 12.0.2 (Oracle Corporation)
复制代码

jar包运行:清单文件

那什么是META-INF/MANIFEST.MF? 为什么要加META-INF/MANIFEST.MF

即使什么都不做,查看MANIFEST.MF文件的内容可以知道它记录着jar包的版本信息、创建时间。 最重要的是java将jar包作为可运行的程序,指定程序入口,便可以直接java -jar的方式运行程序了。

如下图所示:

jar2.png

  • -e选项:可以指定main方法所在的类,清单文件中就会多一行Main-Class: com.ywz.Main
  • -m选项:创建自己的清单文件 写入Main-Class: com.ywz.Main ;

演示: 只用了简单的一个java类:

//$ cat com/ywz/Main.java
package com.ywz;
public class Main{
 public static void main(String[] args) {
    System.out.println("Hello,My Reader!");
 }
}
复制代码

操作演示:

$ javac com/ywz/Main.java#编译
$ jar cvf example.jar com/ywz/Main.class
已添加清单
正在添加: com/ywz/Main.class(输入 = 426) (输出 = 298)(压缩了 30%)
$ jar tf example.jar #list jar包的内容
META-INF/
META-INF/MANIFEST.MF
com/ywz/Main.class
$ unzip -p example.jar META-INF/MANIFEST.MF #基本信息
Manifest-Version: 1.0
Created-By: 12.0.2 (Oracle Corporation)

##cp指定Class-Path是example.jar ,java程序的候默认class loader会从 example.jar来搜索class
$ java -cp example.jar com.ywz.Main #指定jar包资源的运行,com/ywz/Main和com.ywz.Main都可以
Hello,My Reader!
##不指定cp的时候就是当前路径
$ java com/ywz/Main #当前路径的运行,com/ywz/Main和com.ywz.Main都可以
Hello,My Reader!

## -e 指定Main-Class: com.ywz.Main
$ jar cvfe example.jar com.ywz.Main  com/ywz/Main.class 
已添加清单
正在添加: com/ywz/Main.class(输入 = 426) (输出 = 298)(压缩了 30%)
$ unzip -p example.jar META-INF/MANIFEST.MF #验证加了Main-Class
Manifest-Version: 1.0
Created-By: 12.0.2 (Oracle Corporation)
Main-Class: com.ywz.Main 
$ java -jar example.jar #-jar运行
Hello,My Reader!

## -m 指定Main-Class: com.ywz.Main
$ echo "Main-Class: com.ywz.Main" > example_manifest.txt
$ jar cvfm example.jar example_manifest.txt  com/ywz/Main.class
已添加清单
正在添加: com/ywz/Main.class(输入 = 426) (输出 = 298)(压缩了 30%)
$ unzip -p example.jar META-INF/MANIFEST.MF #验证加了Main-Class
Manifest-Version: 1.0
Main-Class: com.ywz.Main
Created-By: 12.0.2 (Oracle Corporation)
$ java -jar example.jar #-jar运行
Hello,My Reader!
复制代码
  • javac编译java文件

  • cp指定Class-Path是example.jar ,java程序的候默认class loader会从 example.jar来搜索class,所以运行的时候需要知道哪个类是main类,需要指定,因此运行的命令写法还比较麻烦。

  • -e或-m 指定Main-Class: com.ywz.Main,打包好便可以直接java -jar example.jar运行

maven打包

上面描述的是jar的低级功能,现在一般都使用更高级的工具maven来帮助构建和打包java程序。 程序目录结构:

$ tree
.
├── pom.xml
├── src
│   └── main
│       └── java
│           └── Main.java
$ cat pom.xml
复制代码

因为代码简单,就没有上传github源码了

  • Main.java和上面描述的一样
  • pom文件配置:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.ywz</groupId>
    <artifactId>test</artifactId>
    <version>1.0</version>
    <properties>
        <argLine>-Dfile.encoding=UTF-8</argLine>
        <java.version>1.8</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>com.ywz.Main</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
复制代码
  • 使用插件maven-jar-plugin,指定archive manifest的mainClass是com.ywz.Main
  • 生成的jar包和之前用jar命令生成的差不多,运行也是同样的效果。如下:
$ tar tf target/test-1.0.jar #只多了META-INF/maven的信息
META-INF/
META-INF/MANIFEST.MF
com/
com/ywz/
com/ywz/Main.class
META-INF/maven/
META-INF/maven/com.ywz/
META-INF/maven/com.ywz/test/
META-INF/maven/com.ywz/test/pom.xml
META-INF/maven/com.ywz/test/pom.properties
$ unzip -p target/test-1.0.jar META-INF/MANIFEST.MF #标记是被Apache Maven 3.6.1创建
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven 3.6.1
Main-Class: com.ywz.Main
$ java -jar target/test-1.0.jar#运行
Hello,My Reader!
复制代码

可以看出:

  • jar包里只多了META-INF/maven的信息
  • META-INF/MANIFEST.MF标记是被Apache Maven 3.6.1创建的.

清楚jar的用法之后,我们就不会被maven各种各样的插件功能遮挡视线,而且发现jar打包和插件逻辑也是很简单的!

猜你喜欢

转载自juejin.im/post/7031716728702926884