命令行
包括一切通过字符终端控制计算机的方式
- Kernel & Shell
- 命令行 vs GUI
命令的要素
-
Executable=> 可执行程序 -
Parameter=> 参数 -
Working Directory=> 工作目录 -
Environment Variable=> 环境变量
ls -l
// ls -> 可执行程序
// -l 及后面所有的 -> 参数
可执行程序
- UNIX | Linux => 可执行权限 => x 权限 =>
- 哪里找命令 =>
PATH环境变量中查找 =>echo $PATH - 在脚本的第一行指定解释器 => shebang
#!/usr/bin/env node // node shebang
三个为一组:
-
r=>read=> 读 =>100 -
w=>write=> 写 =>010 -
x=> 可执行 =>001 - 第一组 => 当前用户权限
- 第二组 => 本用户组
- 第三组 => 其他用户组
chmod 756
- 当前用户权限 -> 7 => 二进制
111=> 可读可写可执行 - 本用户组 -> 5 => 二进制
101=> 可读可执行 - 其他用户组 -> 二进制
110=> 可读可写
权限
参数
UNIX 参数约定
ls -a -l -t -h
// 使用一个 - 后面只能跟一个字符,这代表一个参数
// 上面四个参数可以合并,等价于
ls -alth
// 使用两个 -- 后面可以跟着一个单词
ls -a // 等价于
ls --all
参数中包含空格 | 字符串
- 单引号 => 作为一个整体参数传入进去,不要将其中的变量展开 => 命令行不做任何处理
- 双引号 => 作为一个整体参数传入进去,并且将其中的变量展开 => 命令行会对里面的变量进行替换和展开
想传入进去单引号这个符号的话,可以套上一层双引号 || 使用转义
echo "'I am a boy'"
echo \'I am a boy\'
可以通过使用单引号将通配符的通配性取消,让可执行程序去解释,而不是使用命令行的传递给执行权限的值
git add * // 将所有的文件传递给 git
git add '*' // 将 ` * ` 传递给 Git,Git 自己去解释 ` * ` 的含义
Working Directory
- 启动命令的路径
- 相对路径都是相对于工作目录的路径
- 工作目录决定了程序中相对路径起始的位置
绝对路径 => 从根目录开始的路径
相对路径 => 相对于当前工作目录的路径
Environment Variable
环境变量是存在于环境中的一组键值对,会影响所有在这个环境中启动的程序的行为
- 进程 => 进程是计算机程序运行的最小单元 => 独占自己的内存空间和文件资源
- 每个进程都和一组变量相绑定 => 传递不同的环境变量可以让程序表现出不同的行为
- 在进程的 fork 过程中,环境变量可以被完全继承
- 所有的 操作系统 | 编程语言 都支持环境变量
- 通过
export设置环境变量,通过echo读取环境变量export AAAAA=12345 echo $AAAAA - 容器是有点特殊的进程,它的环境变量不会受到外面环境变量的影响
- 快速传递一个环境变量 =>
AAAAA=12345 source .file=>file中可以读取到环境变量AAAAA,值为 12345,退出后这个环境变量就没有了
输入 & 输出
-
Stdin=> standard input => 标准输入 -
Stdout=> standard output => 标准输出 -
Stderr=> standard error => 标准错误
输出重定向 >
-
>-> 将标准输出重定向到后面的文件中 =>echo 'Hello World!' > temp.txt=> 会覆盖 -
>>-> 将标准输出追加在后面的文件中
在进程中
-
Stdout=> 进程描述符为1号输出 =>1>等价于> -
Stderr=> 进程描述符为2号输出 =>2>将标准错误重定向 -
java Main > output 2>&1将标准输出和标准错误同时重定向到一个文件中
垃圾桶 /dev/null
将标准错误丢掉,丢到垃圾桶
java Main 2> /dev/null
Java & 命令行
源代码「.java文件」 --编译--> 字节码「.class文件」 --运行-->
JVM 只认识字节码「.class 文件」
jar包 => 一堆字节码的结合
javac Main.java // 编译
java Main // 运行
javac & java
System Property 系统属性
在 JVM 中有 System Property,System Property 就是 JVM 里面的环境变量
public class Main {
public static void main(String[] args) {
System.out.println("Hello World");
System.out.println("args:" + java.util.Arrays.toString(args));
System.out.println("env:" + System.getenv("AAA")); // Java 获取环境变量
System.out.println("property:" + System.getProperty("AAA")); // Java 获取系统属性,只在 JVM 中有效
System.out.println("java version:" + System.getProperty("java.version"));
System.out.println("user.dir:" + System.getProperty("user.dir"));
}
}
javac & java
java -DAAA=456 Main 1 2 3 // -D 传递系统属性
javac -classpath commons-lang3-3.9.jar XXX.java // -classpath 可以用于传递 jar 包, -classpath 等价于 -cp
java -cp commons-lang3-3.9.jar:. XXX // 启动 java,java 运行所需要的类在 jar 包中查找同时也在当前目录下查找,并启动 XXX 类
常用命令
cd // change directory
cat // 查看一个文件的内容 concatenate and print files
pwd // print working directory
ps aux // mac 查看进程列表
docker run -it ubuntu // 使用 Linux 命令行,装 docker,之后启动 ubuntu
docker run -it -e AAAAA=12345 ubuntu // 环境变量 AAAAA 值为 12345
Maven
自动化构建工具 => 划时代的包管理
- Convention over Configuration => 约定优于配置
- Maven 远远不止是包管理
- Maven 中央仓库 => 按照一定的约定存储包
- Maven 本地仓库 => 默认位于
~/.m2=> 下载的第三方包放在这里进行缓存
包
JVM 工作 => 执行一个类的字节码,这个过程中如果遇到了新的类,加载它
Classpath 类路径
-classpath | -cp => 从 Classpath 里面去寻找相关的类,之后加载它 => 每当 JVM 需要一个类时,就会在当前的 Classpath 里面找,如果碰到 jar 包,就将 jar 包解压缩,继续在解压缩的目录里面找
类的全限定类名 FQCN (目录层级)唯一确定了一个类
jar 包 == 包 => 包就是把许多类放在一起打的压缩包 => 包就是一堆类的集合
源代码中依赖的类还依赖了其他的类 => 传递性依赖
Classpath Hell 依赖地狱
- 全限定类名是类的唯一标识
- 当多个同名类同时出现在 Classpath 中,就是噩梦的开始
包管理
引用第三方库时,需要告知 JVM 去哪里找 => 包管理的本质 => 告诉 JVM 如何找到所需的第三方类库以及成功的解决其中的冲突问题
pom.xml => project object model
Maven 包
- 按照约定为所有的包编号,方便检索
-
groupId+artifactId+version -
scope=> 依赖的隔离 => 在不同的代码集合中隔离第三方的依赖-
<scope>compile</scope>=> main + test 可见 -
<scope>test</scope>=> test 可见,main 不可见 -
<scope>provided</scope>=> 只在编译 main 代码时有效,运行时无效 => 运行的时候有其他依赖提供,防止包冲突
-
- 语义化版本
- SNAPSHOT 快照版本 => 开发使用的版本
- 传递性依赖的自动管理 => 原则:绝对不允许最终的 classpath 出现同名不同版本的 jar 包
- 依赖冲突的解决 => 原则:最近的胜出,如果路径相同,先声明的胜出 => 查看依赖🌲
mvn dependency:tree
包冲突
包冲突相关错误:
- AbstractMethodError
- NoClassDefFoundError
- ClassNotFoundException
- LinkageError
解决包冲突:
- 在项目中直接引入想要依赖的包,使得依赖的包最近
- 将不想依赖的包告知 maven
// pom.xml <dependency> <groupId><groupId> <artifactId></artifactId> <version></version> <exclusions> // 取消 groupId 中的依赖 <exclusion> <groupId></groupId> <artifactId></artifactId> </exclusion> </exclusions> </dependency>
Maven 生命周期
Maven 生命周期有三种模式:default | clean | site
Maven Default Lifecycle
当运行 maven test 时,将会从开始的 validate 执行,直到 test Phase。默认情况下在这些生命周期中,什么都不会做,需要开发者通过插件 「Plugin」来指定在某个生命周期要做什么事情
Maven Plugin
- Maven Compiler Plugin => 内置,绑定到
compilePhase => 运行到compilePhase 执行 maven-complier-plugin 的工作,maven-compiler-plugin 的工作称为goal - Maven Surefire Plugin => 内置,绑定到
testPhase,测试插件 => 相关 Plugin 会自动的将 goal 绑定到相关的 Phase - Maven Checkstyle Plugin => 第三方插件 => 开发者显示声明该插件的 goal 用于哪个阶段 => 如果遇到两个插件同时绑定到同一个 Phase,运行顺序为声明顺序
// 将 Maven Checkstyle Plugin 的 goal 绑定到 compile Phase <executions> <execution> <id>compile</id> <phase>compile</phase> <goals> <goal>check</goal> </goals> </execution> </executions>
知识点
- idea 中的 run == 编译 + 运行
-
source=> 一个 Shell 内置命令,用以在当前上下文中执行某文件中的一组命令,source命令可简写为一个点(.) -
chmod=> 一条在 Unix 系统中用于控制用户对文件的权限的命令(change mode)和函数。可以使用绝对模式(八进制数字模式),符号模式指定文件的权限 -
grep=> 最初用于 Unix 操作系统的命令行工具。在给出文件列表活标准输入后,grep 会对匹配一个或多个正则表达式的文本进行搜索,并值输出匹配或者不匹配的行或文本














网友评论