Linux命令学习

本文最后更新于:2023年12月17日 下午

任务挂起和恢复

我想大家应该都知道ctrl+c是终止任务/进程, ctrl+z是任务挂起(将一个正在前台执行的命令放到后台,并且处于暂停状态),那么任务挂起后该如何恢复呢?经过查阅[1],可以参考使用如下命令:

  1. jobs 显示当前暂停的进程
  2. bg %N 使第N个任务在后台运行(%前有空格)
  3. fg %N 使第N个任务在前台运行

    注意:默认 bg 和 fg 不带%N时表示对最后一个进程操作


此外与任务/进程控制相关的命令还有 & 和 nohup[2]

Commod + & 在一个命令最后加上一个 &,可以将这个命令放到后台执行;

如果让程序始终在后台执行,即使关闭当前的终端也执行(之前的&做不到),这时候需要nohup。该命令可以在你退出帐户/关闭终端之后继续运行相应的进程。
关闭终端后,在另一个终端jobs已经无法看到后台跑得程序了,此时利用ps(进程查看命令)

验证JSON格式正确性

1
cat a.json | python -m json.tool | wc -l 

使用上述命令,可以检查一个文件是否符合json格式,其实现原理如下:

  • 要验证的文件 a.json;
  • 如果返回结果一行数字,则表示 a.json 文件格式正确;
  • 否则返回 a.json 文件中错误的行号及错误信息。

一旦 JSON 文件格式不对,或者文件内容缺失或者其他问题,就会导致 python -m 命令无法格式化,正是利用这一点,我们可以做一个 JSON 的验证。[3]


为了简化命令,可以利用alias设置命令别名,但是因为需要命令行参数传入文件名,而alias不支持命令行参数。在查阅资料后[4],找到一种方法,就是通过定义函数的方式来实现。

1
alias isjson='isjson(){cat "$1" | python -m json.tool | wc -l}; isjson'

GREP、SED、AWK命令

GREP

grep 指令用于查找内容包含指定的范本样式的文件,如果发现某文件的内容符合所指定的范本样式,预设 grep 指令会把含有范本样式的那一列显示出来。[3]

  • grep默认是忽略二进制数据的,可以加上 -a--text 来表示不忽略二进制文件。
1
2
3
grep -a file_name

grep --text file_name
  • -E : 使用正则表达式,匹配了才输出
1
2
grep -E "word1|word2|word3" file.txt
#满足任意条件(word1、word2和word3之一)将匹配。
1
2
grep word1 file.txt | grep word2 |grep word3
#必须同时满足三个条件(word1、word2和word3)才匹配。
  • -r :递归搜索目录
1
grep -r word directory
  • -v : 显示不包含匹配文本的所有行。
1
2
grep -v 'abc\|efg' log.txt
#排除 log.txt 中的 abc efg 关键字

SED

sed 可依照脚本的指令来处理、编辑文本文件。sed 主要用来自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等。

对文件进行文本替换操作:

1
2
sed -i 's/原字符串/新字符串/' filename
sed -i 's/原字符串/新字符串/g' filename

-i 表示直接修改读取的文件内容,而不是输出到终端。

最后带 g 进行了一个全局的搜索;不带g的话,只是匹配每行的第一个字段,后面的匹配则会忽略。


示例:

  • sed 文件首尾添加引号
1
sed -i 's/^/"/;s/$/"/'  log.txt
  • sed 文件尾添加逗号
1
sed -i 's/$/,/'  txt

注意上述命令在Mac系统的终端里会报错,需要在"-i" 后加上 ""

AWK

AWK 是一种处理文本文件的语言,是一个强大的文本分析工具。

  • -F :指定输入文件折分隔符
  • -v : 赋值一个用户定义变量。

使用示例:

1
2
3
4
5
6
7
8
9
# 每行按空格或TAB分割,输出文本中的1、4项
awk '{print $1,$4}' log.txt
# 格式化输出
awk '{printf "%-8s %-10s\n",$1,$4}' log.txt
# 使用","分割
awk -F , '{print $1,$2}' log.txt
# 使用自定义变量
awk -v a=1 '{print $1,$1+a}' log.txt # 数值加
awk -v a=1 '{print $1,$1a}' log.txt # 字符加

压缩和解压

zip

  • 压缩文件: zip 压缩文件名 源文件
  • 压缩目录: zip -r 压缩文件名 源目录
  • 解压: unzip 压缩文件名

示例:

1
2
3
4
5
mkdir book
touch book/1.txt
touch book/2.txt
zip -r book.zip book
unzip book.zip

gzip

命令示例含义
gzip 源文件gzip a.txt压缩为.gz格式的压缩文件,源文件会消失
gzip -c 源文件 > 压缩文件gzip -c yum.txt > yum.txt.gz压缩为.gz格式的压缩文件,源文件不会消失
gzip -r 目录gzip -r xx压缩目录下的所有子文件,但是不压缩目录
gzip -d 压缩文件名gzip -d yum.txt.gz解压缩文件,不保留压缩包
gunzip 压缩文件gunzip yum.txt.gz解压缩文件,不保留压缩包

tar

  • tar -cvf 打包文件名 源文件[5]
    • -c 打包
    • -v 显示过程
    • -f 指定打包后的文件名
    • -x 解打包

示例:

1
2
tar -cvf book.tar book
tar -xvf book.tar

更多压缩命令:

1
2
3
4
5
6
7
8
9
10
11
tar –cvf jpg.tar *.jpg #将目录里所有jpg文件打包成tar.jpg 

tar –czf jpg.tar.gz *.jpg #将目录里所有jpg文件打包成jpg.tar后,并且将其用gzip压缩,生成一个gzip压缩过的包,命名为jpg.tar.gz

tar –cjf jpg.tar.bz2 *.jpg #将目录里所有jpg文件打包成jpg.tar后,并且将其用bzip2压缩,生成一个bzip2压缩过的包,命名为jpg.tar.bz2

tar –cZf jpg.tar.Z *.jpg #将目录里所有jpg文件打包成jpg.tar后,并且将其用compress压缩,生成一个umcompress压缩过的包,命名为jpg.tar.Z

rar a jpg.rar *.jpg #rar格式的压缩,需要先下载rar for linux

zip jpg.zip *.jpg #zip格式的压缩,需要先下载zip for linux

更多解压命令:

1
2
3
4
5
6
7
8
9
10
11
tar –xvf file.tar #解压 tar包 

tar -xzvf file.tar.gz #解压tar.gz

tar -xjvf file.tar.bz2 #解压 tar.bz2

tar –xZvf file.tar.Z #解压tar.Z

unrar e file.rar #解压rar

unzip file.zip #解压zip

硬链接和软链接

参考:软链接和硬链接的区别[6]

我们知道文件都有文件名与数据,这在 Linux 上被分成两个部分:用户数据 (user data) 与元数据 (metadata)。用户数据,即文件数据块 (data block),数据块是记录文件真实内容的地方;而元数据则是文件的附加属性,如文件大小、创建时间、所有者等信息。在 Linux 中,元数据中的 inode 号(inode 是文件元数据的一部分但其并不包含文件名,inode 号即索引节点号)才是文件的唯一标识而非文件名。文件名仅是为了方便人们的记忆和使用,系统或程序通过 inode 号寻找正确的文件数据块。而有一种方法可以快速的寻找到数据元,那就是软硬链接,链接实际上就是一种文件共享的方式。

那么软链接和硬链接的区别在哪呢?[7]

  1. 首先,两者作用的对象不同:
  • 硬链接,只能应用于文件,而不能应用于目录,而且不能跨文件系统(即分区);
  • 软(符号)链接,可以应用于文件,而且可以应用于目录和可跨文件系统(分区)。
  1. 其次,两者的作用原理不同:
  • 硬链接中,假如说A文件是B文件的硬连接文件,那么A和B的inode节点号相同,即一个inode节点对应两个不同的文件名,两个文件名指向同一个文件,A和B对文件系统来说是完全平等的,硬链接中一个inode号可以对应多个文件。如果删除其中任何一个文件,另外一个文件还能连接数据块,还是有效的文件,只是对应的inode节点号减少,其它并无影响。只有inode节点号减少到0,数据块才会被系统回收。
  • 而在软链接中,假如说A文件是B文件的软连接文件,则A和B的inode节点号不同,每创建一个新的软链接,就会有一个新的节点号。而A的数据块中存放的只是B的路径名(可以根据这个找到B的目录项)。A和B之间是“主从”关系,如果B被删除了,A仍然存在(因为两个是不同的文件),但指向的是一个无效的链接。
  1. 语法不同:
  • 硬链接的语法:ln filename [linkname ]
  • 软链接的语法:ln -s filename [linkname]

最后总结一下:

  • 硬链接:与普通文件没什么不同,inode 都指向同一个文件在硬盘中的区块;
  • 软链接: 保存了其代表的文件的绝对路径,是另外一种文件,在硬盘上有独立的区块,访问数据时,将用数据块中指向的文件路径进行替换。

其它shell技巧

输入相似文件名

用花括号括起来的字符串之间再用逗号连接,可以实现自动扩展,非常有用。花括号中的每个字符都可以和之后(或之前)的字符串进行组合拼接,注意花括号和其中的逗号不可以用空格分隔,否则会被认为是普通的字符串对待。示例如下:

1
2
3
4
5
$ echo {one,two,three}file
onefile twofile threefile

$ echo {one,two,three}{1,2,3}
one1 one2 one3 two1 two2 two3 three1 three2 three3

这个技巧有什么实际用处呢?最简单实用的就是给 cp,mv,rm 等命令扩展参数:

1
2
3
4
5
6
7
8
$ cp /search/code/file{,.bak}
# 给 file 复制一个叫做 file.bak 的副本

$ rm file{1,3,5}.txt
# 删除 file1.txt file3.txt file5.txt

$ mv *.{c,cpp} src/
# 将所有 .c 和 .cpp 为后缀的文件移入 src 文件夹

命令快捷键

命令含义
ctrl+c强制终止当前命令
ctrl+l清屏
ctrl+a光标移动到命令行首
ctrl+e光标移动到命令行尾
ctrl+u从光标所在的位置删除到行首
ctrl+z把命令放入后台
ctrl+r在历史命令中搜索
!n替换成第n条历史命令
!!替换成上一条命令
!字符替换成最后一条以该字符串开头的命令

命令连接符

  1. ; 分号:没有任何逻辑关系的连接符。当多个命令用分号连接时,各命令之间的执行成功与否彼此没有任何影响,都会一条一条执行下去。

  2. || 逻辑或:当用此连接符连接多个命令时,前面的命令执行成功,则后面的命令不会执行。前面的命令执行失败,后面的命令才会执行。

  3. && 逻辑与:当用此连接符连接多个命令时,前面的命令执行成功,才会执行后面的命令,前面的命令执行失败,后面的命令不会执行,与 || 正好相反。

  4. | 管道符:当用此连接符连接多个命令时,前面命令执行的正确输出,会交给后面的命令继续处理。若前面的命令执行失败,则会报错,若后面的命令无法处理前面命令的输出,也会报错

复制文本内容

有时候不好在终端界面里,用鼠标操作选中并复制文件里的文本内容,可以用下面的命令来复制文件里的内容:

1
2
3
4
5
# 方法1,利用重定向
$ pbcopy < file.txt

# 方法2,利用管道
$ cat file.txt | pbcopy

Bonus: 系统启动过程

参考阮一峰大佬的这篇博客:计算机是如何启动的[8]

1.BIOS

  • 计算机通电后,第一件事就是读取刷入ROM芯片的开机程序,这个程序叫做(Basic Input/Output System)

2.硬件自检

  • BIOS程序首先检查,计算机硬件能否满足运行的基本条件,这叫做”硬件自检”(Power-On Self-Test)
  • 如果硬件出现问题,主板会发出不同含义的蜂鸣,启动中止。如果没有问题,屏幕就会显示出CPU、内存、硬盘等信息。

3. 启动顺序

  • 硬件自检完成后,BIOS把控制权转交给下一阶段的启动程序。
  • 这时,BIOS需要知道,”下一阶段的启动程序”具体存放在哪一个设备
  • BIOS需要有一个外部储存设备的排序,排在前面的设备就是优先转交控制权的设备。这种排序叫做”启动顺序”(Boot Sequence)
  • BIOS按照”启动顺序”,把控制权转交给排在第一位的储存设备。
  • 这时,计算机读取该设备的第一个扇区,也就是读取最前面的512个字节。如果这512个字节的最后两个字节是0x55和0xAA,表明这个设备可以用于启动;如果不是,表明设备不能用于启动,控制权于是被转交给”启动顺序”中的下一个设备。
  • 这最前面的512个字节,就叫做”主引导记录”(Master boot record,缩写为MBR)

4. 主引导记录的结构

  • “主引导记录”只有512个字节,放不了太多东西。它的主要作用是,告诉计算机到硬盘的哪一个位置去找操作系统。

    • (1) 第1-446字节:是用来记录系统的启动信息的,调用操作系统的机器码

    • (2) 第447-510字节(64个字节):分区表(Partition table),分区表的作用,是将硬盘分成若干个区

    • (3) 第511-512字节:主引导记录签名(0x55和0xAA)

5. 分区表

  • 磁盘分区是使用分区编辑器在磁盘上划分几个逻辑部分
  • 磁盘一旦划分成多个分区,不同类的目录与文件可以存储进不同的分区内
  • “主引导记录”因此必须知道将控制权转交给哪个区
  • 分区表的长度只有64个字节,里面又分成四项,每项16个字节。所以,一个硬盘最多只能分四个一级分区,又叫做”主分区”
    • (1) 第1个字节:如果为0x80,就表示该主分区是激活分区,控制权要转交给这个分区。四个主分区里面只能有一个是激活的。
    • (2) 第2-4个字节:主分区第一个扇区的物理位置(柱面、磁头、扇区号等等)。
    • (3) 第5个字节:主分区类型,比如FAT32、NTFS等。
    • (4) 第6-8个字节:主分区最后一个扇区的物理位置。
    • (5) 第9-12字节:该主分区第一个扇区的逻辑地址。
    • (6) 第13-16字节:主分区的扇区总数。

6. 硬盘启动

  • 计算机的控制权就要转交给硬盘的某个分区了
  • 四个主分区里面,只有一个是激活的。计算机会读取激活分区的第一个扇区,叫做”卷引导记录”(Volume boot record,缩写为VBR)
  • “卷引导记录”的主要作用是,告诉计算机,操作系统在这个分区里的位置。然后,计算机就会加载操作系统了。

7. 操作系统

  • 控制权转交给操作系统后,操作系统的内核首先被载入内存。
  • 以Linux系统为例,先载入/boot目录下面的kernel。内核加载成功后,第一个运行的程序是/sbin/init。它根据配置文件(Debian系统是/etc/initab)产生init进程。这是Linux启动后的第一个进程,pid进程编号为1,其他进程都是它的后代
  • 然后,init线程加载系统的各个模块,比如窗口程序和网络程序,直至执行/bin/login程序,跳出登录界面,等待用户输入用户名和密码。

备注/参考


Linux命令学习
https://2017zhangyuxuan.github.io/2022/02/01/2022-02/2022-02-01 Linux命令/
作者
Zhang Yuxuan
发布于
2022年2月1日
许可协议