ZB-016-命令行详解02

输⼊与输出

进程启动之后有三个要素,它们不和任何编程语言绑定,而且任何编程语言里都有这样的概念

  • 标准输⼊ stdin
  • 标准输出 stdout
  • 标准错误 stderr
1
2
3
4
5
6
7
8
public class Main{
public static void main(String[] args){
// 标准输出
System.out.println("output")
// 标准错误
System.err.println("error")
}
}

执行我们的 java

1
2
3
4
javac Main.java && java Main
输出
output
error

在操作系统中

  • stdout 叫做 “文件描述符1”
  • stderr 叫做 “文件描述符2”

将输出放到文件里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
java Main > output.txt
# 发现少了一行,因为输出默认会把标准输出重定向到文件里
> error

# 一个 “>” 代表重写覆盖, 两个">>"代表追加

重定向的 ">" 默认等价于 "文件描述符1"

# 执行 文件描述符2
java Main 2> output.txt
# error 写在了 文件里
> output

# 如何把 标准输出和 标准错误 同时输出到一个文件里
java Main > output 2>&1

# 顺序写反是无效的
java Main > output 1>&2
error

# 现在会同时打印 标准输出和标准错误, 此时我只想要 标准输出,不要标准错误
java Main 2> /dev/null
# 意思是把 错误输出丢到垃圾桶里
  • 输出的重定向
    • 覆盖⽂件
    • 追加⽂件
    • 改变流向
    • /dev/null

Linux常⽤命令

  • 进⼊⽬录 cd (change directory)
  • 展示⽂件 ls/ll/ls -alth (list)
  • 移动/重命名⽂件 mv (move)
  • 删除⽂件 rm/rm -r/rm -rf (remove)
  • 拷⻉⽂件 cp/cp -r (copy)
  • 显示变量 echo
  • 导出变量 export
  • Git系列操作 git pull/push/add/commit/…

Linux常⽤命令

  • 新建⽬录 mkdir/mkdir -p (make directory)
  • 当前⽬录 pwd (print working directory)
  • 显示⽂件 cat (concatenate and print files)
  • 编辑⽂件 vi

怎么才能掌握命令行?

以下方式逐级晋升

  • ⾃⼰对着书敲命令
  • 尽可能地在开发中使⽤命令⾏
  • vi/git/mkdir, etc.
  • 使⽤命令⾏的各种⼩⼯具
  • 开发命令⾏的程序
  • ⾃⾏在云服务器上开发部署博客
  • ⾃⾏在云服务器上进⾏持续集成实战
  • ⽇常使⽤Linux进⾏开发

使用命令编译java程序

1
2
3
4
5
6
7
// 环境变量 
System.getenv("aaa")

// 系统属性 只在 jvm 中有效
System.getProperty("xxx")
System.getProperty("java.version")
System.getProperty("user.dir")

Main.java

1
2
3
4
5
6
7
8
9
10
11
12
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("java version:"+System.getProperty("java.version"));
// System.getProperty("user.dir")

System.out.println("system property:"+System.getProperty("BBB"));
}
}

运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
javac Main.java && java Main 1 2 3

args:[1,2,3]
env: null
java version:1.8.0...
system property:null


# 传递 系统属性
export AAA=123
java -DBBB=789 Main

args:[]
env: 123
java version:1.8.0...
system property:789
-D 的顺序有要求
1
2
3
4
5
6
7
8
9
10
11
12
javac -DBBB=789 Main
args:[]
env: 123
java version:1.8.0...
system property:789


javac Main -DBBB=789
args:[-DBBB=789]
env: 123
java version:1.8.0...
system property:null
classpath应用

假如我们的Main.java 里 用了第三方包

1
2
3
4
5
6
7
8
9
10
11
java Main 报错 class not found

javac -classpath common-lang3-3.9.jar Main.java
java Main
// 报错,意思只在 common-lang3-3.9.jar 的目录里找不在当前目录找

还可以简写
java -cp common-lang3-3.9.jar Main

# 正确写法 除了在 common-lang3-3.9.jar 找还在 当前目录找
java -cp common-lang3-3.9.jar:. Main

在看IDEA里运行main的时候启动时的命令行

1
/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/bin/java "-javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=51272:/Applications/IntelliJ IDEA.app/Contents/bin" -Dfile.encoding=UTF-8 -classpath /Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/lib/ant-javafx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/lib/javafx-mx.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/lib/packager.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home/lib/tools.jar:/Users/huangjiaxi/Desktop/java-fork-process/target/classes com.github.hcsp.shell.Fork

java 中 fork进程

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
30
31
32
33
34
35
36
37
38
39
40
41
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

// 1. 可执行程序 2。 参数
ProcessBuilder pb = new ProcessBuilder("sh","run.sh");
// 3。 工作路径
pb.directory(getWorkingDir());
// 4。 设置环境变量
Map<String,String> envs = pb.environment();
envs.put("AAA","123");

// 把系统输入输出 继承到当前的进程中来
// pb.inheritIO();

// 将输出内容重定向到文件
pb.redirectOutput(getOutputFile());

pb.start();

}

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");
}
}

练习

  1. Linux命令
    我的pr
  2. java命令
    我的pr
  3. 使用Java代码fork子进程
    我的pr