命令行的入门与详解

什么是命令行

操作系统都有内核的概念,内核是直接与硬件打交道的。我们通过包裹内核的一层壳( 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
2
#!/usr/bin/env node
console.log(123)

#!/usr/bin/env node 意思是在 PATH 环境变量找到 node 解释器位置,来解释 zzf.sh 文件。也可以使用 node.exe 文件的绝对路径。

1
2
#!/d/node
console.log(123)

从环境变量找解释器和使用绝对路径是等价的,但是一般都是从环境变量去找,更为灵活。

参数

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

命令行的入门与详解
http://wszzf.top/2021/08/26/命令行的入门与详解/
作者
Greek
发布于
2021年8月26日
许可协议