本文旨在分类汇总Linux下常用命令及适用场景
什么是Shell?
当谈到命令行时,我们实际上指的是shell。shell是一个接收由键盘输入的命令,并将其传递给操作系统来执行的程序。几乎所有的Linux发行版都提供shell程序,该程序来自于称之为bash的GNU项目。bash是Bourne Again Shell的首字母缩写,Bourne Again Shell基于这样一个事实,即bash是sh的增强版本,而sh是最初的UNIX shell程序,由Steve Bourne编写。
当然市面上的shell种类远不止这两个,还有其它的shell,比如,ash, korn, tcsh,还有就是同事经常使用的 zsh,配合oh-my-zsh使用起来比较爽(感兴趣可以研究)。
以下均以bash为例子,所有涉及到的命令,均可以在 man 手册中详细查看。
man 的级别:(man 也可以 man 可以详细查看级别)
一般情况下,man手册会根据传入的参数,判断属于什么级别。
man的级别如下:
The table below shows the section numbers of the manual followed by the types of pages they contain.
1 Executable programs or shell commands
2 System calls (functions provided by the kernel)
3 Library calls (functions within program libraries)
4 Special files (usually found in /dev)
5 File formats and conventions, e.g. /etc/passwd
6 Games
7 Miscellaneous (including macro packages and conventions), e.g. man(7), groff(7), man-pages(7)
8 System administration commands (usually only for root)
9 Kernel routines [Non standard]
如果我们明确知道要man的内容数据以上某个级别,可以直接 man [1,2,3,4...] 内容。特别适合使用在同名命令的场景。比如,man read,默认走到了 1 这个级别,即 shell commands,read是一个bash内建的命令。但是万一想查的是系统调用read,则man 2 read
READ(2) Linux Programmer's Manual READ(2)
NAME
read - read from a file descriptor
SYNOPSIS
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
DESCRIPTION
read() attempts to read up to count bytes from file descriptor fd into the buffer starting at buf.
On files that support seeking, the read operation commences at the file offset, and the file offset is incremented by the number of bytes read. If the file offset is at or past
the end of file, no bytes are read, and read() returns zero.
If count is zero, read() may detect the errors described below. In the absence of any errors, or if read() does not check for errors, a read() with a count of 0 returns zero and
has no other effects.
According to POSIX.1, if count is greater than SSIZE_MAX, the result is implementation-defined; see NOTES for the upper limit on Linux.
RETURN VALUE ... ...
Bash 自身也是一个可执行程序,在没有GUI之前,大家均使用的是命令行的模式。在Bash下去执行命令时,Bash会解析命令和参数,并且也是启动(fork)一个子进程去执行该命令。
文件和目录操作
本章节涉及到的命令:
ls cd file less cp mv mkdir rm ln
Linux整个目录结构是一颗倒立的树状结构:
文件系统管理着其下的文件和目录结构。常见的文件系统如下:
- ext系列,ext2,3,4 扩展文件系统,支持高级日志功能
- xfs 高性能64位日志文件系统
- nfs 网络文件系统
- ntfs 支持Microsoft NT文件系统
- proc 可以访问系统信息的文件系统
- tmpfs 临时文件系统,可以使用内存或者磁盘
- ramfs 内存文件系统
文件系统之上,linux抽象出VFS层,将所有操作文件的接口统一起来。比如,可以使用read或者write系统调用读写底层各种不同种类的文件系统上的文件,包括socket。
常见的文件操作
本章节涉及到的命令:ls cd file less cp mkdir mv rm ln touch
ls 显示当前目录下的文件
-l 显示文件细节
-a 显示所有文件包括隐藏文件,在linux下以 . 开头的文件称为移仓文件
-h 文件大小以human readable的方式显示
-r 逆序排序
-t 按照时间逆序排序
常用 ls -lrth 按照时间逆序排序,很有用的参数,很方便找到最新修改的文件,尤其是看log的时候,如:
wind@bogon log]$ ls -rlth
total 0
-rw-r--r--. 1 wind wind 0 Aug 14 16:56 log1.txt
-rw-r--r--. 1 wind wind 0 Aug 14 16:56 log2.txt
-rw-r--r--. 1 wind wind 0 Aug 14 16:56 log3.txt
[wind@bogon log]$
如果不按时间排序,单凭肉眼,看不出来哪个文件是最新修改的,按时间排序之后,就可以放心地直接打开log3.txt查看最新的日志。
ls 可以列出多个目录下的内容,只需要传递多个参数即可。如
[wind@bogon ~]$ ls Videos/ Desktop/
Desktop/:
node_modules
Videos/:
[wind@bogon ~]$
cd 进入某个目录
注意,进入某个目录必须要有该目录的r+x权限,要在目录下创建文件,修改文件等,必须有该目录的写权限。
cd - 回到上一次的工作目录。
可以在终端上敲env,查看当前所有的环境变量,可以看到有一个 OLDPWD的环境变量,这里就记录的是上一次进入的目录。cd - 直接会切到该目录。(注意,如果你刚打开终端,什么目录还未进入,不会有这个环境变量。)
也是非常实用的命令之一。帮助我们在就近的两个目录间切换。
cd 或者 cd ~ 直接回到家目录
当想快速切换到家目录的时候,可以使用。同样的,可以在终端中敲env,可以看到HOME环境变量设置的就是你自己的家目录的绝对路径。
file 查看文件类型
file 也是十分有用的命令,当不知道文件是什么类型,file 文件名即可知道,尤其是那种不带类型后缀的文件就更实用了。比如:
[wind@bogon tmp]$ file tmpi2kh4wcu.png
tmpi2kh4wcu.png: PNG image data, 48 x 48, 8-bit/color RGBA, non-interlaced
[wind@bogon tmp]$ file output.log
output.log: ASCII text
[wind@bogon tmp]$ file /usr/bin/ls
/usr/bin/ls: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=db22e6c4e6b570619fcdfc0e693f5ff827666411, for GNU/Linux 3.2.0, stripped
[wind@bogon ~]$ file /usr/lib64/libGLX_mesa.so.0.0.0
/usr/lib64/libGLX_mesa.so.0.0.0: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=1012f52900c5308af9e23edd2e8dc81ca51a1f7f, stripped
wind@bogon ~]$ cat a
#!/bin/bash
echo "hello world"
[wind@bogon ~]$ file a
a: Bourne-Again shell script, ASCII text executable
[wind@bogon ~]$
less 分段查看文件
当我们要看很大的文件时,直接用vim打开是非常慢的,直接使用less可以很快打开,并且仍旧可以使用vim的快捷键,比如上下翻页,跳转文件头尾部,当然也可以 / 去查找字符串。
less的出现替代了more,"less is more" ,more是不支持内部使用vim的命令去操作的,并且只能向后翻页。所以,less起来吧。
cp 复制文件或目录
几个常用参数
-r 拷贝目录
-i 当目标位置已有相同文件时,进行提示
cp file1 file2
cp file1 file2 directory/
cp -r directory directory/
mkdir 创建目录
几个常用参数
-p 按照传入参数建目录,当目录不存在时依次创建。
如:
[wind@bogon ~]$ mkdir hello/world
mkdir: cannot create directory ‘hello/world’: No such file or directory
[wind@bogon ~]$
mkdir -p hello/world
# 这里的tree是用来显示目录树状结构的命令
[wind@bogon ~]$ tree hello/
hello/
└── world
2 directories, 0 files
[wind@bogon ~]$
mv 移除和重命名文件
mv 的参数和cp的参数大致相同,只不过mv不区分文件还是目录。
mv file1 file2 file3 directory/
mv file1 file2
Question:mv or cp?
rm 删除文件和目录
当心啊!!! 删除数据一般需要小心的,因为恢复起来不容易。
几个常用参数:
-r 删除目录,包括目录中的子目录
-f 强制删除,忽略不存在的文件,不会有交互式提示,会覆盖掉-i参数
-i 删除文件时与用户交互提示是否删除
ln 创建链接
什么是链接?用过windows的朋友都知道快捷方式,链接类似于这个概念。但在Linux中存在软连接和硬链接的概念。其中软连接就类似于快捷方式。
创建软连接又称符号链接
ln -s 源文件 目的软连接位置
创建硬链接
ln 源文件 目的连接位置
软链接是因为硬链接的不足创造的。
硬链接限制:
硬链接不能跨磁盘创建,由于硬链接底层是引用计数,引用计数只能在当前文件系统内生效,即在当前磁盘生效。
硬链接无法引用目录。
当然,硬链接可以用来备份文件而不需要两倍的空间大小。这点,软连接做不到。
touch 修改文件最后访问和修改时间
touch,摸一下,就会修改文件最后的访问时间。如果摸了一个不存在的文件,还会新建出来。
这在依据文件时间变化来进行增量编译的构建系统中是有些用途的。可以让其强制编译某个文件。
寻找命令的位置
本章节会涉及到的命令:which alias
which xx 寻找命令安装位置
which 用来获取当前传入的命令安装位置,如:
[wind@bogon ~]$ which ls
alias ls='ls --color=auto'
/usr/bin/ls
[wind@bogon ~]$
经常会遇到当系统中存在多个相同命令是,不确定当前执行的是哪一个,就可以which xx来确定当前执行的是哪一个。
alias 给命令起别名
命令别名,可以给命令起另外一个名字,比如:
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
可以把一些命令较长,较为难记的命令alias一下,构建自己的命令体系。
重定向
本章节涉及的命令如下:cat sort uniq wc grep awk sed head tail tee
标准输入、标准输出、标准错误
Linux为每个进程默认创建了3个文件流,即标准输入、标准输出、标准错误,对应 0 1 2 三个句柄。
当需要将进程打印的信息写入到文件时,就可以使用重定向。可以选择需要重定向的流,比如:
[wind@bogon ~]$ ls > ls_output.txt
[wind@bogon ~]$ cat ls_output.txt
Desktop
Documents
Downloads
Music
Pictures
Public
shellscript
Templates
Videos
[wind@bogon ~]$
> 表示重定向,就是一个大于号,大于号前可以选择重定向的流编号,如,1或者2。默认是1。
[wind@bogon ~]$ ls /tmp/wahahah > ls_output.txt
ls: cannot access '/tmp/wahahah': No such file or directory
wind@bogon ~]$ ls /tmp/wahahah 2> ls_output.txt
[wind@bogon ~]$ cat ls_output.txt
ls: cannot access '/tmp/wahahah': No such file or directory
[wind@bogon ~]$
如果既想要将标准输出重定向又想标准错误重定向可以如下:
[wind@bogon ~]$ ls /tmp/wahahah > ls_output.txt 2>&1
可以了解为,将标准错误的内如也给到标准输出,一起重定向出去了。只不过在 1 之前要加有一个&作为转义。不然就会把1当做一个文件名了。
如果说不想要标准输出的内容,或者标准错误的内容,可以直接将对应的内容给到 /dev/null 设备。比如:
[wind@bogon ~]$ ls /tmp/wahaha 2>/dev/null
[wind@bogon ~]$
在 /dev/下面有很多有趣的设备 /dev/null 就像一个垃圾箱,可以收各种输出然后扔掉。
/dev/zero 产生0的字符设备。
/dev/random 可以用来产生随机数的字符设备。比如产生8字节的浮点数(年会抽奖可以用用,现场码抽奖代码):
[root@bogon ~]# head -c 8 /dev/random | od -A n -t f8
5.41717595263032e-186
cat 显示文件内容,连接文件内容
cat 可以将传入的所有参数文件内容打印到终端上。因此,使用cat可以将多个文件拼接起来。比如:
[wind@bogon shellscript]$ echo "hello" >a
[wind@bogon shellscript]$ echo "world" >a1
[wind@bogon shellscript]$ cat a a1 > b
[wind@bogon shellscript]$ cat b
hello
world
# 也可以使用通配符
[wind@bogon shellscript]$ cat a* > b
[wind@bogon shellscript]$ cat b
hello
world
管道
管道,顾名思义,抽象起来就是一个管子,有输入有输出。比如:
[wind@bogon shellscript]$ ls /usr/bin | grep -w cd
cd
cd-create-profile
cd-drive
cd-fix-profile
cd-iccdump
cd-info
cd-it8
cd-paranoia
cd-read
[wind@bogon shellscript]$
比如上面的命令就过滤出来了/usr/bin下面的文件中,有哪些包含了 cd 这个单词的。
管道作为内容的传递媒介,实际上做的是将上个命令的输出直接给到了下个命令的输入。
可以利用管道的这一点,进行更复杂的文本处理。比如对输出的内容进行排序,去重,统计行数,再过滤等等。
uniq 报告或者忽略文本中重复的行
uniq会将临近行相同的合并只显示一行,一般会与sort配合使用。
sort 排序字符串
sort 有多个参数可以可以指定分隔符,可以指定按照第几个分隔符的内容作为主键来排序整行。
-t 分隔符
-k 使用字段
-n 按照数字大小排序
-r 逆序
举例如下:
[wind@bogon shellscript]$ cat text.log
5:a
2:c
8:f
4:p
2:c
1:e
[wind@bogon shellscript]$ sort -t':' -k1 text.log
1:e
2:c
2:c
4:p
5:a
8:f
[wind@bogon shellscript]$ sort -t':' -k2 text.log
5:a
2:c
2:c
1:e
8:f
4:p
[wind@bogon shellscript]$ sort -t':' -k2 text.log | uniq
5:a
2:c # 去重了
1:e
8:f
4:p
wc 统计行数、字节数、字数等
常用参数:
-l 统计行数
-c 统计字节数量
-w 统计单词数量
grep 打印匹配行
linux bash 三剑客之一,与sed、awk齐名。都是文本处理利器。
常用参数:
-w 整个单词严格匹配
-v 反向过滤
-n 显示匹配的字符串在文件中的行号
-E 开启正则表达式(正则表达式是另外一个话题)
-i 忽略大小写
-A 匹配到关键字行之后再打印几行
-B 匹配到关键字所在行之前先打印几行
太强大了,暂时只用到了这几个。
我们在查找代码中的函数的时候,经常会用到grep去找符号,比如:
[wind@bogon mesa]$ grep -wn "llvmpipe_draw_vbo" ./* -R
./src/gallium/drivers/llvmpipe/lp_draw_arrays.c:54:llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info,
./src/gallium/drivers/llvmpipe/lp_draw_arrays.c:191: llvmpipe->pipe.draw_vbo = llvmpipe_draw_vbo;
./tags:334214:llvmpipe_draw_vbo src/gallium/drivers/llvmpipe/lp_draw_arrays.c /^llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info,$/;" f typeref:typename:void file:
[wind@bogon mesa]$
这样麻烦的话,直接使用ag,就替代了这么一长串参数:
[wind@bogon mesa]$ ag "llvmpipe_draw_vbo"
tags
334214:llvmpipe_draw_vbo src/gallium/drivers/llvmpipe/lp_draw_arrays.c /^llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info,$/;" f typeref:typename:void file:
src/gallium/drivers/llvmpipe/lp_draw_arrays.c
54:llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info,
191: llvmpipe->pipe.draw_vbo = llvmpipe_draw_vbo;
[wind@bogon mesa]$
只是显示格式的区别,但省了很多参数。
awk
awk, linux bash 三剑客之一,与sed、grep齐名。都是文本处理利器。
过于强大,只说常用的,详细的可以参考man手册,或者网上的使用方式。
awk的语法类似于C的语法,awk可以支持流程控制,函数,定义数组、变量。
- 列处理字符串、数字
- 统计总数、平均数等
- 文本内容匹配、替换、格式化等。
举例,统计分数:
[wind@bogon shellscript]$ cat c
name age score
li 20 100
wang 22 90
zhang 23 98
[wind@bogon shellscript]$ awk 'BEGIN{sum=0;} {if(NR>1) sum+=$3;} END{print sum}' c
288
[wind@bogon shellscript]$
举例,获取用户的登录shell名称:
[wind@bogon shellscript]$ cat /etc/passwd | grep wind | awk -F':' '{print $7}'
/bin/bash
[wind@bogon shellscript]$
-F 为指定分隔符
awk 有很多内置变量可以直接引用,常用的,比如:
NR: 表示当前行号。
NF: 表示当前行的字段总数。
FS: 表示当前使用的分隔符
FILENAME: 表示当前正在处理的文件名称,awk可以一次处理多个文件。
awk 引用外部变量:
[wind@bogon shellscript]$ awk '{printf("%s\n", "'"$HOME"'");}' b
/home/wind
/home/wind
/home/wind
/home/wind
[wind@bogon shellscript]$ awk -v value=$HOME '{printf("%s\n", value);}' b
/home/wind
/home/wind
/home/wind
/home/wind
[wind@bogon shellscript]$
awk 过于强大,其他内容,有待大家自己发掘。
sed
sed, linux bash 三剑客之一,与awk、grep齐名。都是文本处理利器。
过于强大,只说常用的。
- 打印,删除指定行
[wind@bogon shellscript]$ cat b
hello
world
wahaha
[wind@bogon shellscript]$ sed -n '1,2p' b
hello
world
[wind@bogon shellscript]$ sed '1,2d' -i b
[wind@bogon shellscript]$ cat b
wahaha
[wind@bogon shellscript]$
-n 表示只显示匹配的行
-i 表示写入文件
- 字符串替换,修改,打印
格式:sed 's/pattern/replacement/flags' file
flags 可以有多个常用的:
p: 只打印,
d: 删除匹配行
g: 全局替换,即如果一行有多个,则全部替换
[wind@bogon shellscript]$ cat b
hello hello
world
hello
wahaha
[wind@bogon shellscript]$ sed -n '/hello/p' b
hello hello
hello
[wind@bogon shellscript]$ sed '/hello/d' b
world
wahaha
[wind@bogon shellscript]$ sed 's/hello/2333/' b
2333 hello
world
2333
wahaha
[wind@bogon shellscript]$ sed 's/hello/2333/g' b
2333 2333
world
2333
wahaha
[wind@bogon shellscript]$
如果想把结果写入到文件中,需要在文件前,添加 -i 。
- 指定位置插入文本内容
在指定行尾添加
[wind@bogon shellscript]$ cat b | sed "1,2 s/$/233/"
hello hello233
world233
hello
wahaha
[wind@bogon shellscript]$
在匹配的字符串后追加:
[wind@bogon shellscript]$ cat b | sed -r "s/(hello)/\1 fvck/"
hello fvck hello
world
hello fvck
wahaha
[wind@bogon shellscript]$ cat b | sed -r "s/(hello)/\1 fvck/g"
hello fvck hello fvck
world
hello fvck
wahaha
[wind@bogon shellscript]$
在匹配的字符串后添加行:
[wind@bogon shellscript]$ cat b | sed "/hello/a fvck"
hello hello
fvck
world
hello
fvck
wahaha
[wind@bogon shellscript]$
- 引用外部变量
使用bash的双引号扩展,直接将匹配字符串部分用双引号括起来,内部引用变量即可。
[wind@bogon shellscript]$ export A=hello
[wind@bogon shellscript]$ cat b
hello hello
world
hello
wahaha
[wind@bogon shellscript]$ cat b | sed -n "/$A/p"
hello hello
hello
[wind@bogon shellscript]$
sed过于强大,其他内容有待大家自己发掘。
tr 字符转换
比如大小写转换:
[wind@bogon shellscript]$ cat b
hello hello
world
hello
wahaha
[wind@bogon shellscript]$ cat b | tr a-z A-Z
HELLO HELLO
WORLD
HELLO
WAHAHA
[wind@bogon shellscript]$
head/tail 打印文件行首或者行尾
常用参数:
-n 行数,这在文件很大或者只想知道文件内部内容的格式的情况下很有用的。
tail -f 实时监控文件的改变
[wind@bogon shellscript]$ tail -f a1 │[wind@bogon ~]$ echo "wahaha" >> shellscript/a1
world │[wind@bogon ~]$
wahaha │
相当实用的命令,能够帮助我们随时看到文件的最新变化。其底层实现也是使用了文件系统提供的watch/notify机制。感兴趣可以查看 inotify 。
tee 从stdin读取,并同时输出到stdout和文件中
问题来了,如果在管道中间还想看到输出的内容而不是全部被定向到下一个,可以使用tee。比如:
[wind@bogon tmp]$ ls /usr/bin | tee command.txt | grep -w ls
ls
[wind@bogon tmp]$ head -n 3 command.txt
[
2to3
2to3-3.11
[wind@bogon tmp]$
命令行扩展
花括号扩展
当我们需要批量创建文件、目录等需求时,可以使用花括号扩展。
比如,我们要创建已 command为前缀,以数字编号为后缀的0-100个文件时,可以做如下操作:
[wind@bogon tmp]$ touch command_{1..100}.txt
[wind@bogon tmp]$ ls
command_100.txt command_19.txt command_28.txt command_37.txt command_46.txt command_55.txt command_64.txt command_73.txt command_82.txt command_91.txt
command_10.txt command_1.txt command_29.txt command_38.txt command_47.txt command_56.txt command_65.txt command_74.txt command_83.txt command_92.txt
command_11.txt command_20.txt command_2.txt command_39.txt command_48.txt command_57.txt command_66.txt command_75.txt command_84.txt command_93.txt
#... ... 这里省略剩余文件。
[wind@bogon tmp]$
Bash 在执行这条命令时,会优先展开{},相当于touch后面跟了100个参数。
当然花括号扩展还支持嵌套,比如:
[wind@bogon tmp]$ touch wahaha-{x{1..10},y{11..20}}.txt
[wind@bogon tmp]$ ls
wahaha-x10.txt wahaha-x2.txt wahaha-x4.txt wahaha-x6.txt wahaha-x8.txt wahaha-y11.txt wahaha-y13.txt wahaha-y15.txt wahaha-y17.txt wahaha-y19.txt
wahaha-x1.txt wahaha-x3.txt wahaha-x5.txt wahaha-x7.txt wahaha-x9.txt wahaha-y12.txt wahaha-y14.txt wahaha-y16.txt wahaha-y18.txt wahaha-y20.txt
参数扩展
可以在命令行中直接引用其它变量,比如:
echo $USER
echo $OLDPWD
命令扩展
如果在执行命令过程中,需要依赖其它命令的输出,可以使用参数扩展。如下:
[wind@bogon ~]$ ls -l $(which cp)
-rwxr-xr-x. 1 root root 145480 May 5 05:57 /usr/bin/cp
[wind@bogon ~]$
上述中,bash在执行时会优先执行 $() 中的内容,之后将结果,替换到对应位置,再行执行剩下的命令。
当然,$() 也可以使用 `` 两个反引号括起来,
算数扩展
可以拿 $(()) 来计算 加减乘除取余次幂,不过只是对整数而已。比如:
echo $((2**32)) 即 2 的 32 次方。
单引号和双引号
使用单引号括起来的字符串,不支持所有扩展。
使用双引号括起来的字符串,支持所有扩展,支持字符的转义。
比如:
[wind@bogon ~]$ A=10
[wind@bogon ~]$ echo '$A'
$A
[wind@bogon ~]$ echo "$A"
10
[wind@bogon ~]$ echo "\$A"
$A
[wind@bogon ~]$ echo "$(ls)"
build_package
Desktop
Documents
Downloads
Music
Pictures
Public
shellscript
Templates
Videos
[wind@bogon ~]$ echo '$(ls)'
$(ls)
用户和权限
本章节设计的命令:id useradd deluser usermod chmod su sudo chown passwd
在UNIX安全模型中,一个用户可以对文件或者目录有控制权,即owner。用户可以划归到某一个组中,如果改组对文件或者目录有控制权,那么其组内的用户均继承该控制权。那么除了用户自己和用户所在的组,剩余的均称为其它用户和其它用户组,拥有文件控制权的用户可以控制对应的文件或者目录是否对可以被其它用户访问。
注:超级用户(root)不受权限约束,除非 ... ...
id 查看当前用户id,所属组id等
[wind@bogon ~]$ id
uid=1000(wind) gid=1000(wind) groups=1000(wind),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[wind@bogon ~]$
同样的信息可以在/etc/passwd中查看到。
useradd 添加用户
常用参数:
-d 家目录路径
-m 家目录不存在时创建
-s 指定登录shell类型
wind@bogon ~]$ sudo useradd test -d /home/test -m -s /bin/bash
[sudo] password for wind:
[wind@bogon ~]$ sudo passwd test
Changing password for user test.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
[wind@bogon ~]$
userdel 删除用户
userdel user_name
常用参数:
-r 删除用户时同时清理掉家目录及相关目录。
[wind@bogon home]$ ls -rlth
total 12K
drwx------. 3 test test 4.0K Aug 24 16:23 sudo
drwx------. 3 test test 4.0K Aug 24 16:42 test
drwx------. 29 wind wind 4.0K Aug 24 16:45 wind
[wind@bogon home]$ sudo userdel test # 默认不会清理家目录
[wind@bogon home]$ ls -rlth
total 12K
drwx------. 3 1001 1001 4.0K Aug 24 16:23 sudo
drwx------. 3 1001 1001 4.0K Aug 24 16:42 test
drwx------. 29 wind wind 4.0K Aug 24 16:45 wind
[wind@bogon home]$
usermod 修改用户账户信息
usermod可以修改很多内容,包括:
- 用户家目录
- 用户组信息,添加删除修改
- 修改用户可使用时间等
以添加用户组为例:
[wind@bogon ~]$ sudo usermod -a -G test wind
给wind用户添加test组。注意这里需要用户重新登录才能生效。
读写可执行权限
文件或目录的权限情况可以通过 ls -l 来查看,如:
[wind@bogon ~]$ ls -l
total 392
drwxr-xr-x. 3 wind wind 4096 Jul 19 21:51 build_package
drwxr-xr-x. 3 wind wind 4096 Jul 12 14:36 Desktop
drwxr-xr-x. 2 wind wind 4096 Jan 10 2023 Documents
drwxr-xr-x. 4 wind wind 4096 Mar 8 16:40 Downloads
drwxr-xr-x. 2 wind wind 4096 Jul 3 12:12 genbu_service
drwxr-xr-x. 17 wind wind 4096 Aug 4 15:29 git
-rwxr-x---. 1 wind wind 82627 Feb 6 2023 gl33-gtf-master.txt
-rwxr-x---. 1 wind wind 253199 Feb 6 2023 gl33-master.txt
-rw-r--r--. 1 wind wind 60 Aug 15 11:50 ls_output.txt
[wind@bogon ~]$
各个权限对应的权值:
- r 可读权限,对应 4
- w 可写权限,对应 2
- x 可执行权限,对应 1
加和等于 7
Question:为什么是 1 2 4,不是1 2 3
常见的文件类型:
- - 普通文件
- d 目录文件
- l 符号链接文件,注意对于符号链接文件,其文件属性始终是rwxrwxrwx,是个伪属性,其指向的文件的属性才是真的文件属性
- c 字符设备文件,该文件类型表示以字节流形式处理数据的设备,比如终端(tty),比如我们的显卡设备/dev/dri/card0 ,比如我们的fb设备 /dev/fb0
[wind@bogon dev]$ ls -l fb0 dri/card0
crw-rw----+ 1 root video 226, 0 Aug 15 08:57 dri/card0
crw-rw----. 1 root video 29, 0 Aug 14 15:47 fb0
[wind@bogon dev]$
- b 块设备文件,该文件类型表示以数据块方式处理数据的设备,比如,磁盘设备,光盘设备
[wind@bogon dev]$ ls -l /dev/sda{1,2,3}
brw-rw----. 1 root disk 8, 1 Aug 14 15:47 /dev/sda1
brw-rw----. 1 root disk 8, 2 Aug 14 15:47 /dev/sda2
brw-rw----. 1 root disk 8, 3 Aug 14 15:47 /dev/sda3
[wind@bogon dev]$
chmod 更改文件或者目录权限
chmod 有很多种方式去修改文件权限
- 全量修改,即一次性指定所有的权限,包括user、group、other的权限,比如:
[wind@bogon shellscript]$ ls -rlth
-rw-r--r--. 1 wind wind 6 Aug 15 12:06 a
[wind@bogon shellscript]$ chmod 666 a
[wind@bogon shellscript]$ ls -l a
-rw-rw-rw-. 1 wind wind 6 Aug 15 12:06 a
自己需要事前计算好所有权值和
- 部分修改
如果只需要部分修改权值,则可以通过指定给 user 、group、other 添加或者减少什么权值,比如:
[wind@bogon shellscript]$ ls -l a
-rw-rw-rw-. 1 wind wind 6 Aug 15 12:06 a
[wind@bogon shellscript]$ chmod u+x a
[wind@bogon shellscript]$ chmod o+x a
[wind@bogon shellscript]$ chmod g-w a
[wind@bogon shellscript]$ ls -l a
-rwxr--rwx. 1 wind wind 6 Aug 15 12:06 a
[wind@bogon shellscript]$
- u 表示user
- g 表示 group
- o 表示 other
- a 表示 all
- 表示 添加 权限
- 表示 去除 权限
- = 表示指定权限
适用于只需要部分修改文件权限的场景。这里+或者-后面可以跟不止一个权限,比如 +rwx 也是可行的。
并且,可以同时给 ug,go,等组合添加或者去除权限。
更改身份
su 以其它用户和组ID的身份来运行shell
su 可以切换到指定用户去执行命令
su [-] username
su执行后会进入对应用户的登录shell界面,这里 - 的意思代表是否要切环境变量,如果指定了 - 表示使用要切换的用户的所有环境变量,而不是当前用户的所有环境变量。不指定 - 时,表示不切换环境变量,只是用户身份的切换。比如:
[wind@bogon shellscript]$ export A=10
[wind@bogon shellscript]$ su
Password:
[root@bogon shellscript]# echo $A
10
[root@bogon shellscript]#
exit
[wind@bogon shellscript]$ export B=20
[wind@bogon shellscript]$ su -
Password:
[root@bogon ~]# echo $B
[root@bogon ~]#
logout
[wind@bogon shellscript]$ su
Password:
[root@bogon shellscript]# echo $B
20
[root@bogon shellscript]#
注意,su 不指定用户名称时,默认会切换到超级用户,即root。
如果不进入用户的登录shell交互式执行命令,还可以直接 -c “command”的方式执行命令,即:
[wind@bogon shellscript]$ su - -c "ls"
Password:
anaconda-ks.cfg initial-setup-ks.cfg
[wind@bogon shellscript]$
退出shell的方式,exit或者ctrl-d均可,ctrl-d 的含义我们在信号章节继续讲。
sudo 以另一个用户的身份执行命令
sudo命令在很多方面都类似于su命令,不过管理员可以通过配置sudo命令,使系统以一种可控的方式,允许一个普通用户以一个不同的用户身份(通常是超级用户)执行命令。在特定情况下,用户可能被限制为只能执行一条或者几条特定的命令,而对其他命令没有执行权限。另一个重要的区别在于,使用sudo命令并不需要输入超级用户的密码。使用sudo命令时,用户只需要输入自己的密码来进行认证。(浅显的理解,sudo即super user do xxx)。
配置sudo可以使用visudo,或者直接修改/etc/sudoers 文件。推荐使用visudo,因为其可以帮助检查语法错误。我们可以精确配置某个用户使用sudo可以执行哪些命令,不能执行哪些命令。
用 sudo -l 可以详细查看当前用户可以执行的哪些命令。
[wind@bogon shellscript]$ ls -l a
-r-xr-x---. 1 root root 26 Aug 17 13:07 a
[wind@bogon shellscript]$ ./a
bash: ./a: Permission denied
[wind@bogon shellscript]$ sudo ./a
hello
[wind@bogon shellscript]$ sudo -l
Matching Defaults entries for wind on bogon:
!visiblepw, always_set_home, match_group_by_gid, always_query_group_plugin, env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS", env_keep+="MAIL QTDIR USERNAME LANG
LC_ADDRESS LC_CTYPE", env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES", env_keep+="LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE", env_keep+="LC_TIME LC_ALL
LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY", secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/var/lib/snapd/snap/bin
User wind may run the following commands on bogon:
(ALL) ALL
[wind@bogon shellscript]$
chown 更改文件所有者和所属群组
可以使用chown来修改文件或者目录所属于的用户或者组。
chown user[:[group]] file
这里的group如果和user相同,可以缺省(但是冒号得留着)。
也可以只修改user或者只修改group。只修改group时,冒号需要带上。
passwd 更改用户密码
passwd username 这个命令没有什么特别的。改用户密码。
高级键盘技巧
在Bash下敲命令,有很多快捷键,十分方便,给我们提升效率,以下介绍常用的快捷键,感兴趣的话可以详细查看。
clear 清理屏幕显示内容
clear会清理当前终端显示的所有内容,如果敲clear太麻烦,可以直接 Ctrl-l。
reset 清理当前及历史的所有输出
reset 不仅会清理当前终端显示内容,历史显示内容仍旧会清理,保证不会干扰后续的程序输出。
编辑命令行
当我们在敲命令时候,敲错了,或者漏敲了,怎么能快速完成这些操作呢?
Ctrl-a
将光标移动到行首,很好记,a是字母表的开始字母,表示开始的意思。
Ctrl-e
将光标移动到行尾,很好记,e是end的缩写。
Ctrl-f
将光标向前移动一个字符,f 是front的意思。
Ctrl-b
将光标向后移动一个字符,b是back的意思。
Alt-f
将光标向前移动一个单词。(可能会和终端快捷键起冲突)
Alt-b
将光标向后移动一个单词。
Ctrl-w
从后向前删除一个单词,w是word的意思。
Ctrl-d
删除光标处的字符。d->delete
Ctrl-k
剪切从光标到行尾的文本。
Ctrl-u
剪切从光标到行首的文本。
复制粘贴
和寻常我们使用的Ctrl-c Ctrl-v不同,Ctrl-c 已经用来代表其它含义了(发送信号,在信号章节介绍),再加一个shift。
复制粘贴选中的文本行
Ctrl-Shift-c
Ctrl-Shift-v
别再鼠标右键点来点去了。键盘操作起来吧。
PS: 在vim或者tmux中复制内容,可以按住shift再用鼠标选中和复制。
搜索命令行
history 显示历史执行的命令列表
每个历史命令都有一个编号,当我们知道这个编号以后,就可以直接使用 !num 来运行。
[wind@bogon mesa]$ history | tail
1082 sudo dnf upgrade vsftpd
1083 rpm -q vsftpd
1084 rpm -qa vsftpd
1085 rpm -q vsftpd
1086 man
1087 man rpm
1088 vmstat
1089 free
1090 man free
1091 history | tail
[wind@bogon mesa]$ !1089
free
total used free shared buff/cache available
Mem: 2000904 623772 200980 18032 1176152 1171288
Swap: 2000892 132352 1868540
[wind@bogon mesa]$
Ctrl-r 搜索历史命令
键入 Ctrl-r 之后,会进入搜索历史命令的模式,这时候只需要敲一些关键字,就会匹配到历史的命令,进而可以执行历史的命令。如果显示的命令不是你想要的那个,可以连续按 Ctrl-r 找到自己想要的命令。
找到之后可以 Ctrl-j 将命令或者Ctrl-a(光标自动到头b部),Ctrl-e(光标自动到尾部) 将命令先显示到提示符。
或者直接 Enter 执行。
(reverse-i-search)`free': free
[wind@bogon mesa]$ free
total used free shared buff/cache available
Mem: 2000904 624820 143484 18044 1232600 1170236
Swap: 2000892 131840 1869052
[wind@bogon mesa]$
上翻下翻历史命令
可以使用方向键 上下 来显示上一条或者下一条命令
也可以使用 Ctrl-p 和 Ctrl-n (prev,next)来上下翻执行过的命令。
进程相关
本章节涉及到的命令:pstree ps top jobs bg fg kill killall
所有的现代操作系统都能够同事运行若干进程,至少用户错觉上是这样的。如果系统只有一个处理器,那么给定时刻只有一个程序可以运行。在多处理器系统中,可以真正并行运行的进程数目,取决于物理CPU的数目。
内核和处理器之间建立了多任务的错觉,即可以并行做几种操作,这是通过以很短的时间间隔在系统运行的应用程序之间不停切换而做到的。由于切换间隔如此之短,使得用户无法注意到短时间内的停滞,从而在感官上觉得计算机能够同时做几件事情。 --- 来自《深入Linux内核架构》
这是一种复用机制的体现,对整个机器硬件的复用。早起的操作系统是单任务的,比如MSDOS,一次只能加载一个程序运行。受限于当时处理器机能限制,运行单个程序已经有些费劲,主频较低。随着Intel 80x86系列的崛起,以及后面的奔腾系列。单任务已经阻碍了充分发挥硬件的能力,随后微软推出了Windows。产生了多任务切换机制。
在整个操作系统中,我们可以随处可见复用机制:
- 端口机制
- IO 复用,select/poll/epoll
以及我们常听说的,波分复用,频分复用,分时复用。我们的网卡中就使用了频分复用。
内核会保存每个进程的信息以便确保任务有序进行。如果对内核都为进程保存了哪些信息感兴趣,可以深入学习 《深入Linux内核架构》中,进程管理和调度章节。或者详细分析task_struct结构体内容,在include/sched.h中。
在运行的Linux中,每个进程都会有一个唯一的ID来标识它,ID在一段时间内是递增的。所有用户进程的祖先均为1号进程,也就是init进程(或者是systemd进程)。
一个进程可以自行创建其它进程,习惯性称为父进程创建子进程。在Linux下可以使用fork系统调用进行创建。由此可知,进程之间是存在一个树状结构的。可以使用 pstree 来显示出这种树状结构。
进程的状态
Linux 下通过 ps 或者 top 显示的进程的状态:
D 表示不可中断的睡眠状态,也就是说,进程正在等待某些资源(例如磁盘I/O),不能被信号打断。
I 表示空闲状态,也就是说,进程没有运行,也没有被调度。
R 表示运行或可运行状态,也就是说,进程正在运行或者在运行队列中等待运行。
S 表示可中断的睡眠状态,也就是说,进程正在等待某些事件(例如信号)发生,可以被信号打断。
T 表示停止状态,也就是说,进程收到了停止信号(例如SIGSTOP),暂时停止运行。
Z 表示僵尸状态,也就是说,进程已经终止,但是父进程还没有回收它的资源。
僵尸进程没法杀死,只能等父进程回收资源。
[root@bogon ~]# pstree [63/63]
systemd─┬─ModemManager───3*[{ModemManager}]
├─NetworkManager───2*[{NetworkManager}]
├─2*[VBoxClient───VBoxClient───3*[{VBoxClient}]]
├─VBoxClient───VBoxClient───4*[{VBoxClient}]
├─VBoxDRMClient───3*[{VBoxDRMClient}]
├─VBoxService───8*[{VBoxService}]
├─abrt-dbus───2*[{abrt-dbus}]
├─3*[abrt-dump-journ]
├─lightdm─┬─Xorg───{Xorg}
│ ├─lightdm─┬─xfce4-session─┬─Thunar───2*[{Thunar}]
│ │ │ ├─abrt-applet───3*[{abrt-applet}]
│ │ │ ├─agent───2*[{agent}]
│ │ │ ├─blueman-applet───3*[{blueman-applet}]
│ │ │ ├─dnfdragora-upda───3*[{dnfdragora-upda}]
│ │ │ ├─nm-applet───3*[{nm-applet}]
│ │ │ ├─seapplet───2*[{seapplet}]
│ │ │ ├─ssh-agent
│ │ │ ├─tracker-miner-f───5*[{tracker-miner-f}]
│ │ │ ├─tracker-miner-r───4*[{tracker-miner-r}]
│ │ │ ├─xfce-polkit───2*[{xfce-polkit}]
│ │ │ ├─xfce4-notifyd───2*[{xfce4-notifyd}]
这里只截取了一部分。
如果对1号进程是怎么来的,0号进程怎么创建的1号进程,以及当前系统正在运行的进程都是怎么来的感兴趣的话,可以去查找Linux开机启动过程。这部分内容还是十分有趣的,毕竟操作系统是怎么将一堆会电人的硬件变成了我们的生产工具的过程还是很迷人的。
进程组和session
由此,自然而然地就产生了进程组的概念,即一个进程创建的多个进程会被归到一个进程组里面,我们可以通过命令来查看。多个进程组就组成了一个session,一般情况下,session中的第一个进程既是session的leader也是当前进程组的组长。
关于进程组和session 的更多信息,可以参考 Unix环境高级编程,第9章进程关系中进程组和会话章节。
ps 查看进程信息
ps 可以显示进程/线程状态,包括内存占用,运行时间。
可以 man ps,其中列举了多种常用的使用方式。详细可以查看man ps中EXAMPLES节。
比如:
EXAMPLES
To see every process on the system using standard syntax:
ps -e
ps -ef
ps -eF
ps -ely
To see every process on the system using BSD syntax:
ps ax
ps axu
To print a process tree:
ps -ejH
ps axjf
To get info about threads:
ps -eLf
ps axms
To see every process running as root (real & effective ID) in user format:
ps -U root -u root u
To see every process with a user-defined format:
ps -eo pid,tid,class,rtprio,ni,pri,psr,pcpu,stat,wchan:14,comm
ps axo stat,euid,ruid,tty,tpgid,sess,pgrp,ppid,pid,pcpu,comm
ps -Ao pid,tt,user,fname,tmout,f,wchan
Print only the process IDs of syslogd:
ps -C syslogd -o pid=
Print only the name of PID 42:
ps -q 42 -o comm=
应用一下:
如何查看进程属于某个组或者session:
[wind@bogon ~]$ ps
PID TTY TIME CMD
735131 pts/0 00:00:00 bash
735270 pts/0 00:00:00 ps
[wind@bogon ~]$ ps -q 735131 -o comm=,pid=,pgid=,sid=
bash 735131 735131 735131
# 或者
[wind@bogon ~]$ ps -C bash -o comm=,pid=,pgid=,sid=
bash 22160 22160 22160
bash 22404 22404 22404
bash 735131 735131 735131
[wind@bogon ~]$
使用PID查询较为精准,使用名称来查可能遇到多个相同名称的进程,接下来需要自己去确定哪个是你要找的进程。
引入组和session的概念是为了作业管理和信号传递。比如,可以给进程组的leader进程发送信号,可以让其传递给所有的组内的进程。我们在信号章节再做实验。
top 动态查看进程信息
top程序将按照进程活动的顺序,以列表的形式持续更新显示系统进程的当前信息(默认每3秒更新一次)。它主要用于查看系统“最高(top)”进程的运行情况,其名字也来源于此。top命令显示的内容包含两个部分,顶部显示的是系统总体状态信息,下面显示的是一张按CPU活动时间排序的进程情况表。
常用参数:
-p pid 显示指定pid的进程
-H 显示进程下的所有线程
-c 显示完整的进程命令
-b 不使用交互式运行,只是显示指定次数
-n 次数 和 -b 配合,明确指出top运行的次数
如果不想要动态刷新,可以指定运行几次:
[wind@bogon ~]$ top -c -b -n 1
top - 18:26:35 up 2:04, 1 user, load average: 0.00, 0.00, 0.00
Tasks: 163 total, 1 running, 162 sleeping, 0 stopped, 0 zombie
%Cpu(s): 7.7 us, 0.0 sy, 0.0 ni, 92.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 1954.0 total, 231.8 free, 643.2 used, 1079.0 buff/cache
MiB Swap: 1954.0 total, 1953.5 free, 0.5 used. 1157.3 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3922 root 20 0 335380 126528 46660 S 13.3 6.3 0:31.46 /usr/libexec/Xorg -core -noreset :0 -seat seat0 -auth /run/lightdm/root/:0 -nolisten tcp vt1 -novtswitch
6530 wind 20 0 690884 42836 33408 S 6.7 2.1 0:00.35 /usr/bin/xfce4-terminal
1 root 20 0 105772 16540 10752 S 0.0 0.8 0:01.09 /usr/lib/systemd/systemd rhgb --switched-root --system --deserialize=31
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 [kthreadd]
3 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 [rcu_gp]
# ... ... 省略若干行
6361 root 20 0 0 0 0 I 0.0 0.0 0:00.01 [kworker/u2:2-writeback]
6507 root 20 0 16284 6784 5888 S 0.0 0.3 0:00.00 systemd-userwork: waiting...
6508 root 20 0 16284 6784 5888 S 0.0 0.3 0:00.00 systemd-userwork: waiting...
6509 root 20 0 16284 6784 5888 S 0.0 0.3 0:00.00 systemd-userwork: waiting...
6556 wind 20 0 224264 5248 3584 S 0.0 0.3 0:00.01 bash
6624 wind 20 0 224804 3712 3072 R 0.0 0.2 0:00.00 top -c -b -n 1
[wind@bogon ~]$
在交互式情况下,按 h 可以进入help界面,q 退出。
比如 e 可以控制显示的进程内存占用的单位,E 可以指定概览区域显示的内存单位。等等
top 十分强大,可以参考man手册,这里给一个链接参考 https://zhuanlan.zhihu.com/p/623777553
前台进程
前台进程,顾名思义,在前台运行的进程,可以接受键盘输入,前台运行的所有进程构成了一个前台进程组。当终端上产生任何信号,将会递送给前台进程组。比如:
[wind@bogon ~]$ geany
geany并没有返回 因为Bash在等待geany执行完成,这里的geany即前台进程。
后台进程
在后台运行的进程,其不能接受键盘的输入交互式输入。bash中可以在命令后添加一个 & ,即可以让其在后台运行。比如:
[wind@bogon ~]$ sleep 10 &
[1] 735186
这里的输出有两个,[1] 和 735186 分别代表作业ID和进程ID。
Bash的作业管理会给当前后台运行的每个进程创建一个 Job ID。当后台进程执行完成之后,会在终端上打印Done。
[wind@bogon ~]$
[1]+ Done sleep 10
[wind@bogon ~]$
jobs 查看当前终端启动的所有作业。比如:
pi@raspberrypi:~ $ for((i=0;i<5;i++))do sleep 30 & done
[1] 1609
[2] 1610
[3] 1611
[4] 1612
[5] 1613
pi@raspberrypi:~ $
pi@raspberrypi:~ $ jobs
[1] Running sleep 30 &
[2] Running sleep 30 &
[3] Running sleep 30 &
[4]- Running sleep 30 &
[5]+ Running sleep 30 &
这里的 + 表示最后一个放入后台的进程,也是 fg 默认回放置到前台的进程。
这里的 - 表示倒数第二个放入后台的进程。当倒数第一个到前台之后,倒数第二个会变成+。
fg 将某个作业放置到前台执行。
fg jobid
比如正在写代码,突然同事来了,要然你帮忙看个log,看完之后,再继续写代码。
pi@raspberrypi:~/shell_script $ vim a.c
[1]+ Stopped vim a.c
pi@raspberrypi:~/shell_script $ vim b.log
pi@raspberrypi:~/shell_script $ fg
vim a.c
pi@raspberrypi:~/shell_script $
中断进程运行
Ctrl-C 会向进程发送一个中断信号,从而来中断进程。
停止进程运行
Ctrl-Z 回向进程发送一个停止信号,从而来停止当前进程。
pi@raspberrypi:~/shell_script $ geany
[1]+ Stopped geany
pi@raspberrypi:~/shell_script $ jobs
[1]+ Stopped geany
pi@raspberrypi:~/shell_script $
bg 让停止的进程重新回到后台运行的状态。
pi@raspberrypi:~/shell_script $ geany
[1]+ Stopped geany
pi@raspberrypi:~/shell_script $ jobs
[1]+ Stopped geany
pi@raspberrypi:~/shell_script $ bg 1
[1]+ geany &
pi@raspberrypi:~/shell_script $ jobs
[1]+ Running geany &
pi@raspberrypi:~/shell_script $ fg
geany
bash会将所有前台运行和后台运行的进程放在一个session中。bash自身作为session的leader。这样有个好处,就是当图示的调制解调器断开链接(挂断信号 SIGHUP)发送给bash进程时(或者Bash窗口关闭时),bash可以直接将信号都发送给session下的所有进程,用以session下管辖的进程。
如果我们想在当前中断启动一个长期运行的后台进程,不会在我们退出终端之后也退出了,可以使用nohup来启动程序。
nohup 启动长久的后台进程
pi@raspberrypi:~/shell_script $ nohup sleep 120 &
[1] 2074
pi@raspberrypi:~/shell_script $ nohup: ignoring input and appending output to 'nohup.out'
pi@raspberrypi:~/shell_script $ ls
a.c b.log nohup.out
pi@raspberrypi:~/shell_script $ jobs
[1]+ Running nohup sleep 120 &
pi@raspberrypi:~/shell_script $ ps
PID TTY TIME CMD
1526 pts/0 00:00:00 bash
2074 pts/0 00:00:00 sleep
2077 pts/0 00:00:00 ps
pi@raspberrypi:~/shell_script $
logout
Connection to 192.168.3.102 closed.
22/08/2023 21:20.36 /home/mobaxterm ssh -XY pi@192.168.3.102
pi@raspberrypi:~ $ ps aux |grep sleep
pi 2074 0.0 0.0 4936 492 ? S 14:20 0:00 sleep 120
pi 2111 0.0 0.0 5912 656 pts/0 S+ 14:20 0:00 grep --color=auto sleep
pi@raspberrypi:~ $
这是非常有用的一个命令,非常适合启动一个监控进程。比如定期监控磁盘使用,网络占用,内存占用等等。
这几个命令主要的实现原来均是读取/proc文件系统下面的进程信息,如果ps、top、htop不能满足你的需求,比如你想详细查看某个进程的内存映射布局、限制信息、文件描述符信息等,可以直接去/proc下查找具体的进程ID。/proc下面的内容较为丰富,足以单独提出来另起一篇再叙。感兴趣的话,大家可以自行分析/proc文件系统下面都保存了什么东西。
信号
关于信号的详细使用,编程以及实现方式,可以参考另一篇内容:Linux下信号的使用
在Bash下面,信号可以使用kill 或者 killall 来发送给指定进程或者进程组。
kill 对指定进程或者进程组发送信号
kill [-SIGNUM] PID
kill 只能通过指定PID的方式来发送信号,如果不加参数,默认发送SIGTERM信号。
关于信号编号及其默认对进程的影响行为,参考上述链接文档的内容。
kill 还可以给进程组发送信号,即:
kill -SIGNUM -PGID
killall 通过进程名称来发送信号
最简单的使用:
killall -SIGNUM ProcessName
当然,killall还支持正则表达式,方便我们匹配更多的进程名称。详细man killall
环境
本章节涉及到的命令:printenv set export alias
环境中存储的是什么
环境中存储的是环境变量和shell 变量,shell变量是Bash存放的少量数据。除了变量之外,shell还存储了一些编程数据,比如function和别名。
printenv 打印环境变量
printenv [variable name]
默认会打印全部的环境变量。
pi@raspberrypi:~ $ printenv
SHELL=/bin/bash
PWD=/home/pi
LOGNAME=pi
HOME=/home/pi
LANG=en_GB.UTF-8
TERM=xterm
USER=pi
DISPLAY=localhost:10.0
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
SSH_TTY=/dev/pts/0
TEXTDOMAIN=Linux-PAM
_=/usr/bin/printenv
pi@raspberrypi:~ $
set 同时显示shell变量和环境变量
会比printenv多shell自身的一些函数。
pi@raspberrypi:~ $ printenv
SHELL=/bin/bash
NO_AT_BRIDGE=1
PWD=/home/pi
LOGNAME=pi
XDG_SESSION_TYPE=tty
MOTD_SHOWN=pam
HOME=/home/pi
LANG=en_GB.UTF-8
# 省略大部分内容
quote ()
{
local quoted=${1//\'/\'\\\'\'};
printf "'%s'" "$quoted"
}
quote_readline ()
{
local ret;
_quote_readline_by_ref "$1" ret;
printf %s "$ret"
}
pi@raspberrypi:~ $
环境是如何建立的
换件在登录shell登录之后,会按照顺序读取指定位置的配置文件,设置一批环境变量。
文件路径 | 加载时机及作用 |
---|---|
/etc/profile | 适用于所有用户的全局配置脚本 |
/etc/bash.bashrc | 适用于所有用户的全局配置脚本 |
~/.bashrc | 用户的个人启动文件,可以扩展或者重写全局配置脚本中的设置 |
~/.bash_profile | 用户的个人启动文件,可以扩展或者重写全局配置脚本中的设置 |
~/.bash_login | 如果~/.bash_profile缺失,bash尝试读取此脚本 |
~/.profile | 如果/.bash_profile和/.bash_login均缺失,则bash尝试读取此文件 |
加载顺序是先系统后个人。
如你想配置自己的 alias,配置自己的PATH,配置自己的网络代理等等,就可以在个人启动文件中配置。
bash会自动加载。
修改环境变量
export 临时修改环境变量
export ENV_NAME=VALUE
仅在当前终端生效,包括终端后续要执行的命令中可以读取到。但是当新开启一个终端后,该设置即不生效了。
写入指定配置文件
几个重要的环境变量:
PATH:以冒号分割的一个目录列表,当用户输入一个可执行程序的名称时,会查找该目录列表。
DISPLAY:运行图形界面时界面的名称。通常是:0,表示由X服务器生成的第一个界面。
LANG:定义了语言的字符集和排序规则
PS1:定义了提示字符串的内容,有趣的定制。
PATH 的修改常用在当我们需要添加自己的命令,并且想让bash自动寻找和补全的时候。可以在PATH中添加。
[wind@fedora shellscript]$ ls
a a1 a.c b data.dat group.sh nohup.out text.log tmp
[wind@fedora shellscript]$ pwd
/home/wind/shellscript
[wind@fedora shellscript]$ export PATH=$PATH:/home/wind/shellscript
[wind@fedora shellscript]$ group
groupadd groupdel groupmems groupmod groups group.sh
[wind@fedora shellscript]$ group.sh
想让bash优先查找使用自己定义的命令时,可以将新路径添加到原始PATH的前面。即,export PATH=/home/wind/shellscript:$PATH
DISPLAY 常用在重定向显示,当我们不想让图形显示在当前的屏幕的时候,可以指定让其显示在某个已存在的屏幕上。
[wind@fedora shellscript]$ ssh -XY wind@10.0.2.15
Last login: Tue Aug 22 17:49:12 2023
[wind@fedora ~]$ printenv DISPLAY
localhost:10.0
[wind@fedora ~]$ glxgears
2230 frames in 5.0 seconds = 445.893 FPS
[wind@fedora ~]$ export DISPLAY=:0
[wind@fedora ~]$ glxgears
8142 frames in 5.0 seconds = 1628.385 FPS
8494 frames in 5.0 seconds = 1698.696 FPS
8729 frames in 5.0 seconds = 1745.698 FPS
[wind@fedora shellscript]$ ssh -XY wind@10.0.2.15
wind@10.0.2.15's password:
Last login: Wed Aug 23 10:32:28 2023 from 10.0.2.15
[wind@fedora ~]$ printenv DISPLAY
localhost:11.0
[wind@fedora ~]$
每个SSH客户端,X均会为其非配一个端口用来在需要重定向窗口内容的时候进行重定向。
source 环境变量文件,立即在当前进程生效。这是批量生效的方法。如果环境变量文件中存在函数定义, 也同样会生效。
LANG 常用来设置语言和字符集。
当想改变当前终端显示的内容的语言时,可以通过修改LANG实现。设置LANG的格式<语言_地区.字符编码>
比如:
[wind@fedora ~]$ export LANG=zh_CN.UTF-8
[wind@fedora ~]$ ls -rlth
总计 388K
drwxr-xr-x. 2 wind wind 4.0K 2023年 1月10日 Videos
drwxr-xr-x. 2 wind wind 4.0K 2023年 1月10日 Templates
drwxr-xr-x. 2 wind wind 4.0K 2023年 1月10日 Public
drwxr-xr-x. 2 wind wind 4.0K 2023年 1月10日 Pictures
drwxr-xr-x. 2 wind wind 4.0K 2023年 1月10日 Music
drwxr-xr-x. 2 wind wind 4.0K 2023年 1月10日 Documents
上图设置的LANG解释为,中文_中国大陆地区.UTF-8编码。
定制提示符
[wind@bogon ~]$ export PS1="\[\033[0;31m\]<\u@\h \W>\$ "
<wind@bogon ~>$ ls
black_screen Documents gl33-gtf-master.txt mount_point shellscript
build_package Downloads gl33-master.txt Music Templates
data genbu_service hello Pictures Videos
Desktop git log Public
<wind@bogon ~>$
<wind@bogon ~ 18:20:13>$ export PS1="\[\033[0;31m\]<\u@\h \W \t>\$ "
<wind@bogon ~ 18:20:16>$ export PS1="\[\033[0;31m\]<\u@\h \W \T>\$ "
<wind@bogon ~ 06:20:21>$ export PS1="\[\033[0;31m\]<\u@\h \W \d>\$ "
<wind@bogon ~ Thu Aug 24>$
通过修改 PS1 变量来定制自己的提示符。
网络
本章节涉及到的命令:ping nc telnet netstat wget ssh
Linux的网络包处理过程大致如下(引用自Linux内核网络数据包处理流程):
上图来自 《深入linux内核框架》第12章网络-使用套接字缓冲区处理数据。
在网络连接方面,Linux可以说是万能的。Linux工具可以建立各种网络系统及应用,包括防火墙、路由器、域名服务器、NAS(网络附加存储)盒等。由于网络连接涉及的领域很广,所以用于控制、配置网络的命令自然很多。
大家可能听说过iptables,iptables的实现就内核的Netfliter机制。Netfliter就像是一个滤网,可以过滤输入、输出的网络数据包。它强大到可以做代理,反向代理,可以对各个端口配置策略等等,足以单独另起一次分享。
感兴趣的话,可以详细查看Netfliter的实现,非常非常有趣。
如果家里没有路由器,但是你有一台Linux主机,就可以实现自己的软路由。可以配置各种路由策略,端口映射策略,创建各种网卡,桥接等等,可以满足你各类奇怪有趣的网络需求。
Linux的实现的网络的强大,足以让你研究上若干年。再加上各种网卡新硬件出现,docker的出现,namespace机制的应用,openvswitch的出现,使得网络更加有趣味性,可以在Linux上玩SDN(software define network)。
ping 向指定网络主机发送特殊的数据包
ping 命令常常用来检测目标主机或者链接是否正常在线。
ping 命令使用ICMP协议,发送ECHO包给对端。对端收到之后会回复。
[wind@fedora ~]$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.0.2.2 0.0.0.0 UG 100 0 0 enp0s3
10.0.2.0 0.0.0.0 255.255.255.0 U 100 0 0 enp0s3
[wind@fedora ~]$ ping 10.0.2.2
PING 10.0.2.2 (10.0.2.2) 56(84) bytes of data.
64 bytes from 10.0.2.2: icmp_seq=1 ttl=64 time=0.185 ms
64 bytes from 10.0.2.2: icmp_seq=2 ttl=64 time=0.114 ms
64 bytes from 10.0.2.2: icmp_seq=3 ttl=64 time=0.117 ms
64 bytes from 10.0.2.2: icmp_seq=4 ttl=64 time=0.221 ms
^C
--- 10.0.2.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3071ms
rtt min/avg/max/mdev = 0.114/0.159/0.221/0.045 ms
[wind@fedora ~]$
nc 通过命令行在网络上读写数据
nc常用来进行某个端口的链接,以及发送数据。接收数据。
[wind@fedora ~]$ nc -l 10000 │[wind@fedora ~]$ nc 127.0.0.1 10000
hello │hello
world │world
wahahah │wahahah
│
也可以用来测试某个节点的端口是不是开通了。
[wind@fedora ~]$ nc 127.0.0.1 22
SSH-2.0-OpenSSH_8.8
telnet 使用telnet协议与其它host链接
telnet的功能和nc大致相同,这里不再赘述。telnet自己不能 listen 。
netstat 查看网络设置及统计数据
netstat -ie 查看目前网卡设备都有哪些。
pi@raspberrypi:~ $ netstat -ie
Kernel Interface table
eth0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
ether dc:a6:32:79:54:2a txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 6020 bytes 101123702 (96.4 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 6020 bytes 101123702 (96.4 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.3.102 netmask 255.255.255.0 broadcast 192.168.3.255
inet6 fe80::2e2e:1d81:cd7a:7342 prefixlen 64 scopeid 0x20<link>
ether dc:a6:32:79:54:2b txqueuelen 1000 (Ethernet)
RX packets 37680 bytes 16617725 (15.8 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 21014 bytes 3456633 (3.2 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
pi@raspberrypi:~ $
netstat -r 显示路由表信息
pi@raspberrypi:~ $ netstat -r
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
default 192.168.3.1 0.0.0.0 UG 0 0 0 wlan0
192.168.3.0 0.0.0.0 255.255.255.0 U 0 0 0 wlan0
pi@raspberrypi:~ $
netstat -a 显示所有网络连接的信息
常用参数,
-n 显示自数字形式
-p 显示程序名称
-t 显示tcp相关套接字
-l 显示listen状态的套接字
-u 显示udp相关套接字
wget 下载http链接或者ftp链接对应的资源,比如:
pi@raspberrypi:~ $ wget www.baidu.com
--2023-08-23 14:14:31-- http://www.baidu.com/
Resolving www.baidu.com (www.baidu.com)... 14.119.104.254, 14.119.104.189
Connecting to www.baidu.com (www.baidu.com)|14.119.104.254|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2381 (2.3K) [text/html]
Saving to: ‘index.html’
index.html 100%[=================================================================================================================>] 2.33K --.-KB/s in 0.001s
2023-08-23 14:14:31 (1.72 MB/s) - ‘index.html’ saved [2381/2381]
pi@raspberrypi:~ $
下载了百度的首页资源。
如果想要提交表单内容,可以使用curl来实现,curl不仅可以发GET请求,POST也可以。
ssh 安全登录远程计算机
ssh 分为服务端和客户端。服务端监听22端口。启动ssh服务端可以使用:
启动ssh服务
pi@raspberrypi:~ $ sudo systemctl start sshd
pi@raspberrypi:~ $ systemctl status sshd
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2023-08-18 17:03:42 BST; 4 days ago
Docs: man:sshd(8)
man:sshd_config(5)
Process: 528 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
Main PID: 542 (sshd)
Tasks: 1 (limit: 3933)
CPU: 1.568s
CGroup: /system.slice/ssh.service
└─542 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
如果发现没有安装ssh服务端,可以安装 openssh-server 即可。
连接远端
使用 ssh user@ip 即可:
pi@raspberrypi:~ $ ssh pi@192.168.3.102
The authenticity of host '192.168.3.102 (192.168.3.102)' can't be established.
ECDSA key fingerprint is SHA256:618KauzvFZ9+J4LaIOKQLB4gNO6tb8hytMSYYxZHvI4.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.3.102' (ECDSA) to the list of known hosts.
pi@192.168.3.102's password:
Linux raspberrypi 6.1.21-v8+ #1642 SMP PREEMPT Mon Apr 3 17:24:16 BST 2023 aarch64
Last login: Wed Aug 23 14:34:11 2023 from 192.168.3.84
pi@raspberrypi:~ $
如果是第一次链接某个机器,则会出现上述情况,需要敲一个yes,然后输入密码即可。
X 重定向
如果我们连接上对端之后,想运行图形程序,可以将图形内容重定向到当前机器显示,不过在 ssh 连接时就需要明确告诉ssh server,需要重定向图形内容,可以通过-X参数来指定。
pi@raspberrypi:~ $ ssh -X pi@192.168.3.102
这样,就可以将图形内容传回来了。
ssh 直接执行命令
如果我们只需要执行一条或者几条简单的命令,确实没有必须登录终端。直接后面接命令和参数即可。
pi@raspberrypi:~ $ ssh pi@192.168.3.102 "ls -lrth"
pi@192.168.3.102's password:
total 44K
drwxr-xr-x 2 pi pi 4.0K May 3 04:23 Music
drwxr-xr-x 2 pi pi 4.0K May 3 04:23 Documents
drwxr-xr-x 2 pi pi 4.0K Aug 22 14:20 shell_script
-rw-r--r-- 1 pi pi 2.4K Aug 23 14:14 index.html
pi@raspberrypi:~ $
多个命令之间使用 ; 连接:
pi@raspberrypi:~ $ ssh pi@192.168.3.102 "ls -lrth; pwd"
pi@192.168.3.102's password:
total 44K
drwxr-xr-x 2 pi pi 4.0K May 3 04:23 Documents
drwxr-xr-x 2 pi pi 4.0K Aug 22 14:20 shell_script
-rw-r--r-- 1 pi pi 2.4K Aug 23 14:14 index.html
/home/pi
pi@raspberrypi:~ $
磁盘相关
本章节涉及到的命令:mount umount df fdisk fsck mkfs dd md5sum
所有的文件均存放在磁盘上,通过文件系统将文件组织成块,磁盘是块设备。Linux为我们提供了强大的磁盘管理功能。你可以用Linux系统做自己的RAID,做自己的NAS,还可以用LVM动态拉伸分区,跨磁盘拉伸都可以。
要管理存储设备首先要将存储设备挂载。就像你在一根树枝上挂了一个房子,每个树枝都可以挂房子。这里的树枝对应的就是目录,每个目录都可以挂载设备。
系统启动之后会有一些默认的挂载位置,这些信息均记录在一个 /etc/fstab文件中。
[wind@bogon ~]$ lsblk -f
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
sda
├─sda1
├─sda2 ext4 1.0 af739eb9-1bbd-4df5-a7f8-6613a4acf999 662.8M 25% /boot
└─sda3 ext4 1.0 a8dbe20e-9bb5-4dc2-9535-ffc0cde61227 8.5G 64% /
zram0 [SWAP]
[wind@bogon ~]$ cat /etc/fstab
# /etc/fstab
UUID=a8dbe20e-9bb5-4dc2-9535-ffc0cde61227 / ext4 defaults 1 1
UUID=af739eb9-1bbd-4df5-a7f8-6613a4acf999 /boot ext4 defaults 1 2
[wind@bogon ~]$
字段解释:
- UUID,每个文件系统均会有一个唯一ID来标识,可以使用lsblk -f,可以看到 sda3 这块设备,挂载到了 / 根路径。
- 挂载路径,每个设备想使用起来,均需要挂到某个位置。
- 文件系统名称,ext4 , ext3 , xfs, ntfs , fat32 等
- 挂载属性,只读、读写等
- dump 备份的频率
- fsck 校验文件系统的优先级
如果想要开机自动挂载,只需要修改这个文件即可,添加自己要挂载的内容。
注意,如果这个文件配错了,开机就起不来了。
mount 查看所有已挂载的文件系统列表
设备的排布也是按照编号,比如/dev/sda1 /dev/sda2等等。
挂载设备到指定位置
mount 设备路径 目标挂载路径
[wind@bogon ~]$ sudo mount ./data mount_point/
[wind@bogon ~]$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
loop0 7:0 0 1G 0 loop /home/wind/mount_point
sda 8:0 0 30G 0 disk
├─sda1 8:1 0 1M 0 part
├─sda2 8:2 0 1G 0 part /boot
└─sda3 8:3 0 28.5G 0 part /
zram0 252:0 0 1.9G 0 disk [SWAP]
[wind@bogon ~]$
上面将一个文件当做设备挂载起来,Linux支持将文件块当一个设备进行挂载使用,挂载的类型为loop设备。loop设备作为一个伪设备使用。
注意挂在前需要给设备制作文件系统。后续讲述。
umount 卸载已经挂载的文件系统
umount 设备名称或者挂载路径,均可以卸载掉。
为什么一定要卸载,卸载的重要性在于,外设的访问通常较慢,但是操作系统为了加快设备的读写,通常会给设备分配缓存空间,来将写入操作先缓存起来,到未来的某个时间或者等到缓存达到阈值又或者设备卸载时等多种触发机制,会将缓存的内容刷到外设,比如磁盘中。
`Bash
[wind@bogon ~] lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 30G 0 disk
├─sda1 8:1 0 1M 0 part
├─sda2 8:2 0 1G 0 part /boot
└─sda3 8:3 0 28.5G 0 part /
zram0 252:0 0 1.9G 0 disk [SWAP]
[wind@bogon ~]$
## df 查看设备使用情况
常用参数 -H , human readable
```Bash
[wind@bogon ~]$ df -H
Filesystem Size Used Avail Use% Mounted on
devtmpfs 4.2M 0 4.2M 0% /dev
tmpfs 1.1G 0 1.1G 0% /dev/shm
tmpfs 410M 1.2M 409M 1% /run
/dev/sda3 30G 20G 9.2G 68% /
tmpfs 1.1G 8.8M 1.1G 1% /tmp
/dev/sda2 1.1G 256M 696M 27% /boot
D_DRIVE 108G 56G 53G 52% /mnt
tmpfs 205M 95k 205M 1% /run/user/1000
/dev/loop0 1.1G 58k 951M 1% /home/wind/mount_point
[wind@bogon ~]$
du 查看文件、目录占用空间大小
递归查看当前路径下的所有的
du -sh ./* -R
-s show summary,按目录为级别汇总大小
-h human readable
--max-depth 统计深度
[wind@bogon ~]$ du -sh ./*
4.0K ./a.txt
4.0K ./black_screen
104K ./build_package
33M ./data
40M ./Desktop
4.0K ./Documents
640K ./Downloads
24K ./game
6.9G ./git
84K ./gl33-gtf-master.txt
248K ./gl33-master.txt
4.0K ./Templates
4.0K ./Videos
[wind@bogon ~]$
fdisk 在设备上创建新分区
fdisk 支持多种设备管理格式,GPT,MBR均支持。详细的GPT和MBR的原理,可以自行wiki。
fdisk -l 显示设备分区表
[wind@bogon ~]$ sudo fdisk -l /dev/sda
Disk /dev/sda: 30 GiB, 32212254720 bytes, 62914560 sectors
Disk model: VBOX HARDDISK
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: D7A333BE-91D8-41FD-A58C-678EA9F60DE7
Device Start End Sectors Size Type
/dev/sda1 2048 4095 2048 1M BIOS boot
/dev/sda2 4096 2101247 2097152 1G Linux filesystem
/dev/sda3 3125248 62912511 59787264 28.5G Linux filesystem
[wind@bogon ~]$
fdisk 初始化分区管理格式、创建、删除分区
初始化分区管理格式为GPT
[wind@bogon ~]$ fdisk /dev/sdb
Welcome to fdisk (util-linux 2.38.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): g
Created a new GPT disklabel (GUID: D6FCCB88-140E-9D43-9744-F2DDF3079D96).
Command (m for help): w
The partition table has been altered.
Syncing disks.
[wind@bogon ~]$
详细的其它功能,可以在进入fdisk后,按输入m查看help信息。
mkfs 给分区创建文件系统
mkfs 支持给设备制作多种文件系统:
[wind@bogon ~]$ mkfs.
mkfs.btrfs mkfs.exfat mkfs.ext3 mkfs.fat mkfs.hfsplus mkfs.msdos mkfs.vfat
mkfs.cramfs mkfs.ext2 mkfs.ext4 mkfs.gfs2 mkfs.minix mkfs.ntfs mkfs.xfs
[wind@bogon ~]$ mkfs.ext4 /dev/sda1
mkfs.ext4 设备路径
fsck 测试修复文件系统
fsck 会检查文件系统的完整新,还能修复损坏的文件系统,修复的程度取决于损坏的程度,在Linux下,已修复的文件会放置在 lost+found 目录中。
[me@linuxbox ~]$ sudo fsck /dev/sdb1
fsck 1.40.8 (13-Mar-2012)
e2fsck 1.40.8 (13-Mar-2012)
/dev/sdb1: clean, 11/3904 files, 1661/15608 blocks
上面输出直接粘贴的。
目前遇到过需要fsck的情况出现在经常断电,或者强制关机的场景,文件系统可能损坏。提醒我们正产关机下电的重要性。
dd 直接从/向设备转移数据
dd if=input_file of=output_file [bs=block_size [count=blocks]]
# 比如
dd if=/dev/sdb of=/dev/sdc
# 也可直接接将某个设备的所有内容dump出来
dd if=/dev/sdb of=flash_drive.img
md5sum 计算文件的md5sum 校验值
md5sum 文件名
当我们需要判断文件的完整性时,可以使用。尤其是在网络进行传输文件之后,非常有必要校验完整性。
文件搜索
本章节涉及到的命令: finds
find 强大的搜索命令
常用的方式:
- 直接 find | grep file_name
此种方式,find的默认搜索路径是当前路径以及当前路径下的所有子目录。
pi@raspberrypi:~ $ find | grep nohup
./shell_script/nohup.out
pi@raspberrypi:~ $
非常简洁但实用的查找方式,适合于你记住了项目种的文件名或者文件名的一部分,但不记得路径。
- 通过名字查找文件
find 路径 -name 文件名
pi@raspberrypi:~ $ find ./ -name nohup.out
./shell_script/nohup.out
pi@raspberrypi:~ $
忽略大小写,实用 -iname 而不是 -name
文件名还支持模糊匹配:
pi@raspberrypi:~ $ find ./ -iname "*hup*"
./shell_script/nohup.out
pi@raspberrypi:~ $
- 通过文件类型查找文件
可以通过指定 type 的方式查找文件,比如要找一个目录文件:
pi@raspberrypi:~ $ find ./ -type d -name wahaha
./shell_script/wahaha
pi@raspberrypi:~ $
这时候需要再添加 -name 指定名称参数
- 对查找到的文件自定义操作
pi@raspberrypi:~ $ find ./ -name "nohup*" -and -type f -size +1c -exec ls -l '{}' ';'
-rw------- 1 pi pi 12 Aug 23 15:40 ./shell_script/nohup.out
可以使用xargs实现同样的操作:
pi@raspberrypi:~ $ find ./ -name "nohup*" -and -type f -size +1c | xargs ls -l
-rw------- 1 pi pi 12 Aug 23 15:40 ./shell_script/nohup.out
pi@raspberrypi:~ $
find 查找到的文件,通过管道传递给 xargs,xargs 将内容作为 ls -l 的输入 。
- 指定查找的文件最大层级
pi@raspberrypi:~ $ find ./ -maxdepth 1 -name a.c
pi@raspberrypi:~ $ find ./ -maxdepth 2 -name a.c
./shell_script/a.c
pi@raspberrypi:~ $
- 添加多个查找条件
pi@raspberrypi:~ $ find ./ -name "nohup*" -and -type f -size +1c
./shell_script/nohup.out
pi@raspberrypi:~ $
size 支持的常用单位 c(字节),k,M,G,+表示大于,-表示小于。
还可以查找指定大小范围的文件、指定时间内修改的文件、指定权限的文件、合并多条件查询等。
包管理
本章节涉及到命令:dpkg apt rpm yum dnf
包文件是组成软件包系统的基本软件单元,它是由组成软件包的文件压缩而成的文件集。有些包直接提供一个命令,有些包则提供一些二进制库和开发所需的文件。
包和包之间也存在依赖关系,一些包需要依赖基础环境包存在。
包管理的命令区分不同的发行版本也会不同。
明白自己使用的是Debian系列的还是RedHat系列的发行版是第一步。别在Debian系列的系统上用rpm或者yum使劲敲发现一直报错,还不知道为啥。
apt 安装、卸载、更新软件
在开始安装之前,更新元信息。sudo apt-get update
包搜索
apt-cache search package_name
在使用apt-cache search之前,先更新元信息。apt-get update
安装、卸载、更新
apt-get install package_name
apt-get remove package_name
apt-get update package_name
查看已安装软件的信息:
apt-cache show package_name
yum 安装、卸载、更新软件
搜索
yum search package_name
在使用yum search之前,也可以生成cache。yum makecache
安装、卸载、更新
yum install package_name
yum remove package_name
yum update package_name
查看已安装软件的信息:
yum info package_name
dpkg 安装、卸载、查询
dpkg -i pacakge_file
dpkg -r package_file
dpkg -l | grep package_name
查找文件是由那个包提供的:
dpkg --search file_name
rpm 安装、卸载、查询
rpm -i package_file
rpm -e package_name
rpm -q package_name
查找文件是由那个包提供的:
rpm -qf file_name
[wind@bogon include]$ pwd
/usr/include
[wind@bogon include]$ ls | head
aio.h
aliases.h
alloca.h
a.out.h
argp.h
argz.h
ar.h
arpa
asm
asm-generic
[wind@bogon include]$ rpm -qf aio.h
glibc-headers-x86-2.36-9.fc37.noarch
[wind@bogon include]$
时间与日期
date
显示当前日期和时间,可以 -s 设置系统时间,格式"YYYY-MM-DD H:M:S。也可以设置日期的输出格式,在脚本中是非常有用的按照自己想要的格式获取当前时间的命令。
十分常用的命令,当系统时间不正确时,可以自行设置。
内存相关
本章节涉及到的命令:free
free 显示当前内存使用情况
pi@raspberrypi:~ $ free -h
total used free shared buff/cache available
Mem: 3.7Gi 267Mi 2.8Gi 35Mi 685Mi 3.3Gi
Swap: 99Mi 0B 99Mi
常用参数:
-h human readable
-m 按MB显示
-g 按GB显示
各字段的解释:
total: 总的内存大小
used: 已经使用的内存大小
free: 空闲的内存大小
shared: 共享的内存大小,这部分内存是由多个进程共享的,例如tmpfs文件系统。
buff/cache: 缓冲区和缓存的内存大小。这部分内存是由系统用来缓存磁盘数据和文件系统元数据的,可以提高系统的性能。当其他进程需要内存时,这部分内存可以被回收。
available: 可用的内存大小。这部分内存是指系统可以不用交换就能分配给进程的内存大小。
CPU 主板相关
lscpu 查看CPU型号、主频、缓存大小、支持指令集
或者 cat /proc/cpuinfo
lspci 查看pci设备信息
lspci -v 显示更详细的信息
dmidecode 查看主板信息
perf CPU端性能分析
详情参考:
https://www.brendangregg.com/perf.html
gdb,pstack,gstack 调用栈分析
当一个进程线上运行,但是卡住了,不知道用户态卡住在哪里,就可以使用gdb,再attach到进程。
或者如果系统装了 pstack 或者 gstack 可以直接跟 PID ,就可以查看,不仅可以把进程的调用栈打出来,还可以打印线程的调用栈。
stace 跟踪应用程序的系统调用。
用来排查进程的行为是否符合我们的预期,比如是否加载了我们期望的动态链接库、是否调用了指定的系统调用等。
是一个查看可执行文件执行时行为的利器。
strace -e 跟踪指定的系统调用列表
strace -p PID 指定进程ID跟踪。
strace 不仅能够跟踪系统调用,也能够统计每个系统调用执行的时间。
-T 参数可以统计出每个系统调用执行花费的时间。单位(s)
-tt 参数可以打印出追踪的系统调用开始执行时的挂钟时间。(精确到us)
[wind@bogon ~]$ strace -e "openat,read" -tt -T ls
15:12:16.350608 openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 <0.000009>
15:12:16.350775 openat(AT_FDCWD, "/lib64/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3 <0.000007>
15:12:16.350842 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832 <0.000005>
15:12:16.351009 openat(AT_FDCWD, "/lib64/libcap.so.2", O_RDONLY|O_CLOEXEC) = 3 <0.000008>
15:12:16.351078 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832 <0.000005>
15:12:16.351240 openat(AT_FDCWD, "/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 <0.000011>
15:12:16.351505 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320v\2\0\0\0\0\0"..., 832) = 832 <0.000005>
15:12:16.351681 openat(AT_FDCWD, "/lib64/libpcre2-8.so.0", O_RDONLY|O_CLOEXEC) = 3 <0.000008>
15:12:16.351752 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832 <0.000005>
15:12:16.352376 openat(AT_FDCWD, "/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3 <0.000009>
15:12:16.352538 openat(AT_FDCWD, ".", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3 <0.000007>
black_screen data Documents game git gl33-master.txt log Music Public Templates
build_package Desktop Downloads genbu_service gl33-gtf-master.txt hello mount_point Pictures shellscript Videos
15:12:16.353080 +++ exited with 0 +++
[wind@bogon ~]$
lsof,fuser 查看进程都使用了哪些设备或者文件,及设备、文件都被哪些进程使用。
lsof 排查句柄泄露的好工具。
当我们遇到进程的实际使用内存(RSS)一直在上涨的时候,除了怀疑有内存泄露之外,如果进程中有文件操作,还需要怀疑是否存在句柄泄露(根本上还是内存泄露),即fd泄露。句柄泄露不仅包含文件句柄,也包含网络句柄、等其它句柄。
这种情况,我们使用 lsof 来观测进程是否一直
lsof -p
fuser 查看设备、文件被哪些进程占用
fuser -v /dev/xxxx
valgrind 内存检查利器
valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all ./a.out
常见查问题使用到的命令
上述图片来自 brendangregg
Tips
如何在终端使用计算器
- 使用算数扩展 echo $((expr)),计算整数的加减乘除次幂取余没问题。
- 使用bc ,可以计算小数,设置精度。
- 使用python 前面两个能干的,这个都能干。