Linux
使用过一段时间Linux服务器,一般都是遇到一些问题再查找,这种方式效率较低且并没有从源头上解决问题,所以对Linux的部分要点进行一些记录。
Linux基础指令
Shell的通配符
*
匹配任意长字符串,?
匹配一个字符,[]
用于匹配所有出现在方括号内的字符,可使用-
指定某个范围。
1 | ls *.cpp |
ls
指令
ls -a
会列举出隐含文件,即以.
开头的文件与文件夹。ls -F
在列举时可以区分可执行文件、文件夹、链接文件等。ls -l
可以查看文件属性,共包含8个不同的信息栏:- 文件的权限标志
- 文件的链接个数
- 文件所有者用户名
- 用户所在的用户组组名
- 文件大小
- 最后一次被修改的日期
- 最后一次被修改的时间
- 文件名
1
drwxr-xr-x 2 root root 4096 2003-01-26 21:25 conf.d
cat
指令与less
指令
用于直接在命令行打印出文件内容,如
1 | cat test.txt |
使用-n
可进一步显示行号。
less
可实现与cat
类似的功能,且还支持更多功能,底部有:
等待输入命令
- 按下空格键向下翻一页
- 按下B键向上翻页
- 支持光标键
- 使用
/
加上搜索内容进行搜索,查找相同内容再输入/
即可向下跳转。
grep
指令
实现找到文件中包含指定信息的一行。grep
指令实际上是通过基础正则表达式进行搜索的。
1 | grep [OPTIONS] PATTERN [FILE...] |
如果需要找包含空格的关键词,必须加单引号:
1 | grep 'Red Hat' test.txt |
egrep
可进一步使用扩展的正则表达式。
find
指令与locate
指令
实现文件搜索。
1 | find [OPTION] [path...] [expression] |
例如,
1 | find /usr/bin -name *.cpp -print |
find
会依据给定的地址进行向下搜索,同时通过-name
可使用通配符进行文件搜索。
此外还可以通过-type
参数指定查找的文件形式:
参数 | 含义 |
---|---|
b | 块设备文件 |
f | 普通文件 |
c | 字符设备文件 |
p | 命名管道 |
d | 目录文件 |
l | 符号链接 |
locate
指令相比find
指令执行更迅速,因为其基于检索文件名数据库来确定文件的位置,可以使用updatedb
命令更新数据库文件的最新版本。
终端运行程序
类似上述指令实际上都是调用了程序,在shell中调用程序只需要键入程序名称(可执行文件名称)即可,在其后加上&
可使其启动程序后在后台运行。
1 | code & |
whereis
指令
可用于查找特定程序,并提供该文件的二进制可执行文件、源代码文件和使用手册存放位置。
1 | whereis find |
需要注意的是,whereis
检索的子目录是固定在编写的程序中的。
whatis
指令与apropos
指令
whatis
可以获得指定命令的大致功能,而apropos
可以通过需求反查相关的指令。
1 | whatis uname |
文件目录管理
文件系统架构
Linux首先建立根“/”文件系统,再将其他硬盘分区挂载到上面。
mv
移动重命名
mv
可以移动文件与文件夹:
1 | mv hello bin/ |
在同一目录下面使用mv
可实现重命名。注意mv
不同目录下的同名文件会直接覆盖,建议加上-i
用于提示是否覆盖,或者使用-b
在目标文件后面自动加上~
。
cp
复制文件与目录
cp
与mv
一样会直接覆盖同名文件,也可使用-i
与-b
。同时使用-r
可以实现目录复制的递归。
文件和目录的权限
ls -l /bin/login
的输出:
1 | -rwxr-xr-x 1 root root 38096 2008-11-13 14:54 /bin/login |
- 第一个字段
-
代表文件类型 rwxr-xr-x
位3组权限位,分别代表属主、属组、其他人的权限。r
代表可读,w
代表可写,x
代表可执行,被禁用的权限使用-
代替。- 权限位之后的数字代表文件链接数目,此处表示文件只有一个硬链接。
- 第三、第四字段代表属主与属组。
- 最后四个字段代表文件大小(38096字节)、最后修改日期与时间、文件的完整路径。
chmod
改变文件权限
chmod
使用“用户组+/-权限”或“用户组=权限”的方式修改权限,也可以使用“用户组1=用户组2”将两个用户组的权限设置为相同。只有文件属主和root可以修改文件权限
文件属主u
、文件属组g
、其他人o
,可以使用a
代表3种用户。
1 | chmod u+x days |
另一种方式是将文件权限使用八进制表示:
八进制 | 二进制 | 权限 |
---|---|---|
0 | 000 | —- |
1 | 001 | —x |
2 | 010 | -w- |
3 | 011 | -wx |
4 | 100 | r— |
5 | 101 | r-x |
6 | 110 | rw- |
7 | 111 | rwx |
如
1 | chmod 711 prog |
文件类型
文件类型可以通过ls -l
的第一个字段获得,分为以下几类:
文件类型 | 符号 | 解释 |
---|---|---|
普通文件 | - | |
目录 | d | |
字符设备文件 | c | Linux能读取成字符序列的设备,如磁带、串行线路。串行顺序获取 |
块设备文件 | b | 用来存储数据并对其各部分内容提供访问权的设备,如磁带。随机位置访问 |
本地域套接口 | s | 进程通信相关 |
有名管道 | p | 进程通信相关 |
符号链接 | l | 通过别名访问另一文件 |
ln
建立链接
符号链接也即软链接,是通过名称对文件进行引用,使用带-s
参数的ln
命令创建:
1 | ln -s gcc-13.0 gcc |
使用ls -l
查看gcc
会发现软连接gcc
的文件名为gcc -> gcc-13.0
。
符号链接也适用于目录,如:
1 | ln -s /usr/local/share local_share |
硬链接用于将两个独立的文件联系在一起,属于直接引用:
1 | ln days hard_days |
查看days
和hard_days
的属性可以发现两者是完全独立的文件,但是对其中一个文件改动会反映在另一个文件中,一般情况不常用。
输入输出重定向
程序默认输出结果为标准输出(stdout),一般总是指向显示器。输出重定向用于把程序输出移动到另一个地方:
1 | ls > ~/ls_out |
会将ls
的输出结果覆盖写入到ls_out
中。如果需要保留原始文件内容,可以使用输出重定向符号>>
:
1 | uname -r >> date_out # 将uname命令的输出追加到date_out文件中 |
程序默认接收输入的地方为标准输入(stdin),一般总是指向键盘,cat
可实现类似功能,一般不常用。
另一种输入重定向的方式为立即文档,可指定代表输入结束的分隔符,如“EOF“等。
1 | cat << EOF |
这种输入重定向只会在接收到指定的分隔符时才会打印出输入的结果。
输入重定向与输出重定向可以结合使用:
1 | cat << END > hello # cat命令以立即文档的方式获取输入,然后将cat的输出重定向到hello文件 |
重定向常用的场景为需要添加新的环境变量,可以使用重定向而不需要在~/.bashrc
文件内进行修改:
1 | echo "export ENV=/env_dir" >> ~/.bashrc |
管道
通过使用管道符|
,可以将一条命令的输出连接到另一条命令的输入,如常见的在某一命令的输出中寻找包含特定字符的内容:
1 | ls | grep test |
软件包管理
dpkg
管理.deb
软件包
安装软件包:
1
dpkg -i *.deb
查看已经安装的软件包:
1
dpkg -l | grep [NAME]
卸载软件包:卸载时会删除相关的依赖库和数据文件,可能会影响其他软件运行。
1
dpkg -r [NAME]
高级软件包工具:APT
APT能有效解决软件包安装的依赖问题。
使用apt-get update
会更新apt-get
缓存内的软件包信息,再使用apt-get install
命令将安装软件包。
使用apt-cache search [NAME]
可以查找包含指定字符的软件包,apt-cache depends [NAME]
可以查看软件包的依赖项。
apt-get
的安装源存储在/etc/apt/sources.list
中。
从源代码编译软件
如果没有预先编译好的二进制软件包,则需要从源码开始编译。
Linux上所有软件都使用configure
脚本配置源代码形式的软件,可以指定--prefix
设置软件的安装位置,一般建议放在/usr/local
目录下。
1 | ./configure --prefix=/usr/local/... |
然后执行make
开始编译,最后使用make install
安装软件(会把文件复制到某些系统目录中去),不使用make install
时,可在源码编译的文件位置按照./
加上可执行二进制文件的方式调用软件。
磁盘管理
挂载文件系统
Linux下所有的设备都被映射为”设备文件“,对于上层应用,所有对设备的操作都是通过读写设备文件实现的。设备文件分为块设备文件与字符设备文件,前者可以随机读写(如磁盘),后者只能接收字符流(如打印机)。用户不能直接访问设备文件,所有存储设备必须先挂载到一个目录下。
使用mount
与umount
挂载硬盘、光盘等:
1 | mkdir -p /mnt/sda |
df
查看磁盘使用情况
df
可以输出挂载设备名、挂载点已经磁盘使用情况,可使用-t
指定特定的文件系统:
1 | df -t ext4 |
fsck
检查和修复文件系统
使用fsck
可对文件系统的小异常进行修复,并将日志文件回滚到上一次正常状态,可以接收分区编号指定需要检查的文件系统:
1 | sudo fsck /dev/sda1 |
fsck
修复存在一定风险,务必注意提前备份。
mkfs
在磁盘上建立文件系统
mkfs
可以实现未挂载的磁盘的格式化并建立文件系统,通过-t
参数指定文件系统,可以使用-c
检测指定设备上损坏的块:
1 | sudo mkfs -t ext3 /dev/sdb1 # 格式化/dev/sdb1 |
存档工具
tar
可以读取多个文件和目录,实现文件打包:
1 | tar -cvf shell.tar shell1/ shell2/ |
参数:
-c
:指导tar
创建归档文件-x
:指导tar
解开归档文件-v
:显示命令执行过程-f
:指定归档文件的文件名-z
:自动调用gzip程序实现压缩解压-j
:自动调用bzip2程序实现压缩解压
进程管理
进程的属性
- PID:Linux通过PID确定进程。
- PPID:在Linux中,所有进程都必须由另一个进程创建,PPID即指向当前进程的父进程。
ps
监视进程
使用ps
命令会输出创建进程的用户、PID、资源占用率以及时间等,可以配合grep
寻找特定名称的进程。
1 | ps aux | grep python |
top
即时跟踪进程
使用top
可以实时输出当前系统中的进程情况,默认10s更新一次,CPU使用率最多的程序会排在最前面。
lsof
查看占用文件的进程
lsof
会根据给定的文件找出占用该文件的进程:
1 | lsof database.doc |
kill
向进程发送信号
kill
命令会向指定PID发送信号:
1 | kill [-signal] pid |
部分常用的信号编号如下:
信号编号 | 信号名 |
---|---|
0 | EXIT(程序退出时受到该信号) |
1 | HUP(挂起) |
2 | INT(中断) |
3 | QUIT(退出) |
9 | KILL(杀死) |
11 | SEGV(段错误) |
15 | TERM(软件终止) |
除了KILL
信号可以在内核级别杀死进程以外,其他信号可以被程序捕捉,如部分软件使用Ctrl+C
(对应INT
信号)会被捕捉,不会直接退出程序。
/proc
文件系统
/proc
目录下存放着内核有关系统状态的信息,内核随时向这个目录写入数据。如查询CPU信息:
1 | cat /proc/cpuinfo |
Linux编程
Vim编辑器
使用
1 | vim file |
编辑file文件,如果文件不存在则直接新建一个文件。
Vim严格区分按键的大小写。启动Vim时自动处于命令模式,按下I
键进入插入模式,会在当前光标出插入字符,之后可以使用Esc
键回到命令模式,使用H
、J
、K
、L
四个键移动光标,分别代表左、上、下、右。
使用o
键在光标所在行的下方插入一行,O
键则在上方插入一行。
组合使用:wq
保存文件并退出Vim,使用:q!
将强制退出并不保留未保存的内容。
使用
1 | /string |
可以搜索字符串,使用n
会跳转到下一个出现该字符串的位置。/
是从头到尾寻找,而?
方向相反。
使用下面的命令可以设置是否注意字符串的大小写:
1 | :set ignorecase # 忽视大小写 |
替换字符串的命令如下:
1 | :[range]s/pattern/string/[c,e,g,i] |
这条命令将pattern
替换为string
,开头的range
代表替换的范围,如1,4
代表第1行到第4行,1,$
表示第1行到最后一行,全文也可以使用%
表示。最后的字符的含义如下:
标志 | 含义 |
---|---|
c | 每次替换前询问 |
e | 不显示错误消息 |
g | 替换一行中的所有匹配项 |
i | 不区分大小写 |
gcc、g++
1 | gcc -o sum summary.c |
Shell编程
正则表达式
字符与单词
在正则表达式中,.
用于匹配除换行符外的任意一个字符。如
1 | .at |
可以匹配像cat
、bat
这样的字符串,注意匹配.
本身需要使用\
进行转义。
如果需要限制匹配的字符为字母,则可以使用
1 | [a-zA-Z]at |
注意[]
只能匹配一个字符,如[abc]
只能匹配a
或b
或c
。
[a-z]at
也会匹配如locate
这样的字符串,为了让[a-z]at
严格匹配一个单词,需要加上一对分隔符\<
与\>
:
1 | \<[a-z]at\> |
注意分隔符对于非单词字符(字母、数字、下划线以外的任何字符)也会进行匹配,所以上述正则表达式会匹配如a#bat$
的字符串。
位置匹配
^
和$
分别匹配行首和行尾,如匹配所有以a
开头、以t
结尾、a
和t
之间包含一个小写字母的行:
1 | ^a[a-z]t$ |