命令行的入门与详解
什么是命令行
操作系统都有内核的概念,内核是直接与硬件打交道的。我们通过包裹内核的一层壳( shell )来与内核打交道。
广义的命令行包括一切通过字符终端控制计算机的⽅式
- Windows - cmd/PowerShell/Git bash
- UNIX/Linux系列:sh/zsh/Terminal, etc.
为什么需要命令行
- 因为基本所有公司的服务器都运⾏在 Linux 上 ,所以不得不用
- 将工作自动化(暂时没有接触到的领域)
- 相比 GUI,命令行更容易开发维护,bug 更少
- 远程连接命令行占用资源远低于 GUI
- 命令行上的开发者工具更丰富
不同平台命令行启动方式
- Windows:cmd/PowerShell/WSL
- UNIX/Linux:⼀开机就是,不⽤找。Mac OS 对应的是终端。
命令行的全部要素
命令是由可执行程序和参数组成的。例如:git add test.txt,git 就是可执行程序,git 后面所有的都是参数,即 add test.txt
。命令行输入命令,会把参数原封不动地交给可执行程序解释。
可执行程序(Executable)
什么样的东西是可执行的呢?在 Windows 和 Linux / Unix有着不同的区别
- Windows:只要是 exe / bat / com 结尾的文件都是可执行文件
- LIunx / Unix:文件有 x 权限,表示该文件为可执行文件
可执行程序的位置
- Windows:Path 环境变量或当前⽬录
- UNIX / Linux:PATH 环境变量
可以在脚本的第一行指定解释器(shebang),假设 zzf.sh文件中有如下代码:
1 |
|
#!/usr/bin/env node
意思是在 PATH 环境变量找到 node 解释器位置,来解释 zzf.sh 文件。也可以使用 node.exe 文件的绝对路径。
1 |
|
从环境变量找解释器和使用绝对路径是等价的,但是一般都是从环境变量去找,更为灵活。
参数
UNIX 参数的约定
- 使用一个 “-“ 后面只能跟一个字符,例如:-a -f 等等。后面跟多个参数的话可以合并,例如:-a -f 合并成 -af
- 使用两个 “-“ 后面可以跟一个单词,例如:
ls -a
显示所有文件,等价于ls --all
然而,Java 并不鸟 UNIX 参数约定,例如:当我们查看当前 Java 版本,使用命令 java -version
,一个 “-“ 后面跟了一个单词,与 UNIX 参数约定不符
参数一些注意事项默认情况下 “$” 符号会进行展开。假设当前目录存在一个 main$A.class
文件,并且 export A=123
设置环境变量 A 为123, 使用 Java main$A
运行该文件,等价于 Java main123
。即,把 $A 替换成 123,如果不进行替换,就要使用单引号包裹起来,即 Java 'main$A'
。双引号包裹内容也会进行替换。
因此得出以下结论
- 单引号:不会对引号的内容做处理
- 双引号:对引号里的内容替换
- 空格:当做参数处理
环境变量(Environment variable)
- 进程(Process)
- 进程是计算机程序运⾏的最⼩单位
- 独占⾃⼰的内存空间和⽂件资源
- 每个进程都和⼀组变量相绑定
- 传递不同的环境变量可以让程序表现出不同的⾏为
- CLASSPATH/GOPATH
- 在进程的fork过程中,环境变量可以被完全继承
- 所有的操作系统/编程语⾔都⽀持环境变量
- 局部和全局的环境变量
- 局部变量:只在当前环境生效
- 全局变量:全局生效的变量
我们可以通过 export / set 设置环境变量,通过 echo 读取环境变量 。修改全局变量就需要在全部变量文件中修改,不同操作系统对应的文件不同。
工作目录(Working directory)
工作目录就是输入命令行时,所处的目录即为工作目录。绝对路径是以根目录开头的路径,相对路径是相对于当前目录的路径。
进程的输入与输出
标准输⼊ stdin ,进程将从标准输入中得到输入数据。例如使用 rm -rf *
命令,会提示是否确认删除,当我们回复y 的时候,就时一个标准输入。
输出的重定向,我们可以使用 “>” 符号来重定向输出,例如在终端输入 date +"%Y-%m-%d %H:%M:%S" > output.txt
,就是将标准输出重定向到 output.txt 文件中,若再次运行该命令,会将之前的 output.txt 文件覆盖 。使用 “>>” 可以将标准输出追加到 output.txt 文件中。
标准输出 stdout 和标准错误 stderr 相当于一个进程的两个管道。标准输出对应着文件描述符1,标准错误 对应着文件描述符2。假设我们要将一个进程的标准输出重定向到 output.txt 文件中,我们可以使用 命令 > output.txt
或者 命令 1> output.txt
。同理类推,将进程的标准错误重定向到 error.txt 文件,可以使用 命令 2> error.txt
。要让标准输出和标准错误都重定向到 output.txt 文件,使用 命令 > output.txt > 2>&1
。该命令代表的意思是,先将2(标准错误),重定向到1(标准输出),再把结果重定向到 outout.txt 文件。
/dev/null 相当于一个垃圾桶的概念,可以把标准输出或者标准输入重定向到该文件。 命令 > /dev/null
即把标准输出丢到垃圾桶里,相当于黑洞一般,把标准输出给「吞」了。
Linux 文件权限
任何一个 UNIX 文件都有9位,分成3组,分别是自己(文件创建者),同用户组的人,不同用户组的人。每一组都有 rwx,r 代表读(read),w 代表写(write),x 代表可执行。
假设有一个需求,我们要当前文件只能被当前用户读写执行。就需要把自己组的 r 设置为1,w 设置为1,x 设置为1,其他组的 rwx 都设置为0,设置完成后对应的二进制分别是 111 000 000
,对应的十进制就是 700
,因此使用 chmod 700 当前文件
即可赋予当前用户读写执行权限。
根据上面的结论,我们需要给所有用户可读可写可执行权限,就需要把所有组的 rwx 设置为1,得到的二进制就是 111 111 111
,对应的十进制为 777
,因此 chmod 777 当前文件
表示为所有用户,赋予可读可写可执行权限。
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/…
- 新建⽬录 mkdir/mkdir -p (make directory)
- 当前⽬录 pwd (print working directory)
- 显示⽂件 cat (concatenate and print files)
- 编辑⽂件 vi