入门、历史与启动
Kernal与Shell
- Kernal指的是内核,对于linux而言就是负责与计算机硬件交互的底层代码,例如cpu调度
-
广义命令行
广义命令行是指一切通过字符终端控制计算机的方式
几乎所有的公司的服务器都运行在Linux上
- 运行在Linux上可以将工作自动化,自动化是一切生产力的根源(比手工操作更有效率)
- 相比GUI,命令行更容易开发维护,bug更少
- 远程连接占用更低的资源
-
启动进程的四要素
可执行程序 Executable
可执行程序就是命令行结构中的第一个单词
- Windows系统中,会自动补全exe\bat\com等后缀名
- 操作系统检索可执行程序所在目录的方式如下
- WIndows:Path(path)环境变量 + 当前目录
- 输入命令后会在PATH环境变量中依次查找(echo $PATH),找到后(which java)启动,注意Linux不会在当前目录中进行查找,可以使用 ./main 来执行当前目录下的main程序
- linux中,每个文件都有r(read)w(write)x(executable)三种权限,如果有x权限,就被视为可执行程序,windows由其扩展名exe决定
可以在文本文件中写若干个操作,再给文件加上可执行权限,实现自动化操作,甚至可以使用脚本语言(不用shell命令),只要提前指定脚本语言解释器(shebang)即可,例如
#!/usr/bin/env node (从环境找node,推荐做法)
#!/usr/local/bin/node (通过绝对路径找node)
console.log(123)
console.log(456)
别名alias,常用较长的命令可以指定别名,以提高工作效率,别名与环境变量一样,只影响当前上下文,如果要设置为全局,与设置全局环境变量一样,在bash_profile文件配置
alias gs = 'git status'
参数(易错)
参数在终端是不被处理的,找到可执行程序后,参数全部传递给可执行程序,参数的解释由该程序负责处理
- Unix 参数约定如下(有些程序不遵守):使用单横杠 用单个字符表示一个参数(可合并),使用双横杠 后可接单词表示一个参数 例如,git push -f与git push —force相同,但java并未遵守该约定
- 通过字符串可以将参数划归为一个,实现在长参数中加空格,但是有坑,例如$符号会将环境变量展开,但写在字符串则不会,注意双引号则不行,双引号会展开$变量
- 如果要传递单引号,可以使用转义或者外面包括双引号
-
环境变量 Environment variable
计算机中最小的工作单元是一个进程,进程占用独立的内存空间和资源,每个进程都和一组变量相绑定
- 环境变量就是存在于一个环境的键值kv对,影响所有从该环境中启动的程序的行为,传递不同的环境变量可以让程序表现出不同的行为
- 进程是由父进程派生fork,对于linux,其启动时会从init进程派生出一个进程树,而环境变量是会被逐级继承的(进程树)
- 环境变量被所有操作系统以及各种程序语言编写的程序支持,常在软件工程中作为共享配置数据,在进程间相互传递,因此环境变量是一种通用的在进程中传递变量、配置的一种方式
- 所有编程语言均内置了对环境变量的访问等
- 环境变量是有作用域的,甚至可以对一个进程有效,例如 myname=1 go run main.go
- 可以配置局部和全局环境变量,例如需要一个变量在所有bash中生效,可以在bash_profile文件配置
- docker容器是一种特殊的进程,其环境变量不收外部环境的影响,需要显示的进行传递环境变量
环境变量可通过export(linux)\ set(windows)设置,通过echo读取
export AAA='$A;'
echo $AAA
工作目录 Working directory
启动命令的路径(光标闪烁的位置)
- pwd 查看当前工作目录
- 绝对路径 从根目录开始的路径
-
进程启动后影响其的三要素
-
标准输入 stdin
例如输入的操作字符
标准输出 stdout
- 文件描述符为1
标准输出采用管道1输出 java Main 1> output.txt (默认的)
标准错误 stderr
文件描述符为2
标准错误采用管道2输出 java Main 2> output.txt
输出的重定向
java Main > output.txt 当前进程标准输出覆盖到文件
- java Main >> output.txt 当前进程标准输出追加到文件
java Main > output.txt 2>&1 当前进程标准输入输出覆盖到文件,过程是先将标准错误重定向到输出,再输出(从右向左)
垃圾桶
-
常用命令
cd(change directory) 进入(改变)目录
- cd . 当前目录
- cd .. 上一级目录
- ls(list)显示当前目录中的非隐藏目录
- unix约定以点(.)开头的为隐藏目录,例如.ssh
- ll 显示文件详细信息 ls -l
- ls -alth 所有文件\详细信息\修改时间倒序\人类可读
- mv(move) 移动、重命名文件
- rm(remove) 删除文件
- rm -r 迭代删除文件(所有子树)
- rm -rf 强制删除
- cp(copy) 拷贝文件
- cp -r
- echo 输出一个内容
- 常用于显示变量(当前环境)
- 快速创建文件 echo 123 > file.txt
- export
- 导出变量(向当前环境),使得当前环境启动的后续进程均拥有该变量
- git pull\push\add\commit... git系列操作
- mkdir 新建目录
- mkdir -p a/b/c/d
- pwd (print working directory)显示当前目录全路径
- cat 显示文件
- vi 编辑文件
- source 文件生效
-
使用命令行编译运行java程序
在带有图形化界面的IDE中的操作,本质上均在拼接命令行操作
- java main函数的参数string[] args就是从命令行中读取类名后面的参数并传进来
- 系统属性可以看作是jvm中的环境变量(仅在jvm中生效),用于在启动时向jvm传递参数
- java中获取环境变量 System.getenv(“AAA”)
- java中获取预定义的系统属性System.getPropert(“java”)
- 向传递系统属性的方式 java -Dfile.encoding=UTF-8
mvn本质是一个脚本,负责启动一个jvm,所以-D也可以向mvn传递参数
mvn install -Dmaven.test.skip=true
java命令后跟的参数,以类名为分界,左侧都是传给jvm自己的参数,右侧是传给java程序的参数,例如classpath也是传递给jvm的参数,多参数值用:进行分割(windows用分号;)
// jar就是个压缩包,存放第三方类,使用classpath 传递jar包引入第三方类库
// classpath 可简写为cp,需要的类可以用冒号:分割
javac -classpath commons-lang3-3.9.jar StringIsBlank.java
java -classpath commons-lang3-3.9.jar:. StringIsBlank "" " " "*"
//测试程序
public class Main{
public static void main(String[] args){
System.out.println("args: " + java.util.Arrays.toString(args));
System.out.println("env: " + System.getenv("AAA"));
System.out.println("system property: " + System.getProperty("AAA"));
System.out.println("java version: " + System.getProperty("java.version"));
System.out.println("user.dir: " + System.getProperty("user.dir"));
}
}
Java中fork(派生)子进程
进程启动的四要素
- 可执行程序
- 参数
- 工作目录
- 环境变量
- 该方法的优点
- 用java实现自动化跑脚本
- 实现动态参数的脚本
- 完成当前进程无法做到的工作,不得不fork一个子进程 ```java package com.github.hcsp.shell;
import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Map;
public class Fork {
public static void main(String[] args) throws Exception {
// 请在这里使用Java代码fork一个子进程,将fork的子进程的标准输出重定向到指定文件:工作目录下名为output.txt的文件
// 工作目录是项目目录下的working-directory目录(可以用getWorkingDir()方法得到这个目录对应的File对象)
// 传递的命令是sh run.sh
// 环境变量是AAA=123
ProcessBuilder pb = new ProcessBuilder(“sh”, “run.sh”);
pb.directory(getWorkingDir());
Map
private static File getWorkingDir() {
Path projectDir = Paths.get(System.getProperty("user.dir"));
return projectDir.resolve("working-directory").toFile();
}
private static File getOutputFile() {
return new File(getWorkingDir(), "output.txt");
}
}
运用命令行安装Maven
- maven一个版本可在多个机型上使用,因为其本质是在使用java,包含各系统可使用的maven程序
- linux再当前环境增加环境变量 export PATH = $PATH:/c/Users/xxx/Downloads/apache-maven-3.6.1/bin,再echo $PATH查看是否成功
- 若要在bash进程永久生效,需要更改bashrc文件
-
学好命令行的路线
⾃⼰对着书敲命令
- 尽可能地在开发中使⽤命令⾏
- vi/git/mkdir, etc.
- 使⽤命令⾏的各种⼩⼯具
- 开发命令⾏的程序
- ⾃⾏在云服务器上开发部署博客
- ⾃⾏在云服务器上进⾏持续集成实战
-
shell语法
$表示展开变量
表示注释
- ./可执行文件 可以执行当前目录下的可执行程序
- ‘’单引号包括字符串表示其中内容原样输出,而双引号会展开其中变量,或者使用转义\
- *表示通配符,会被展开