Please enable Javascript to view the contents

Linux-面试速记-bash脚本

 ·  ☕ 10 分钟

知识

规范

文件系统层次标准(FHS):规范目录中存放的内容所指定的标准。解决两个问题:文件放哪里;文件去哪里找。

Posix规范:

1. 文件管理

1.1

2. 文本处理

3. 进程管理

4. 磁盘管理

5. 可观测性(日志、资源、网络)

find命令

问题

1. 文件删除后,但文件空间没有被释放,原因与解决方案

原因:Linux系统中,如果有进程打开文件并持有文件句柄时,即使其他程序删除了文件,文件系统也不会立即释放磁盘空间,知道持有文件句柄的所有进程都关闭了文件才行。

Linux系统中,文件彻底删除取决于两个计数器:磁盘引用计数器(记录文件有几个硬链接)、内存引用计数器(记录文件被几个进程打开)。只有两个计数器全部为0时,文件才会被真正删除。

解决:

  1. 等持有文件句柄的进程退出

可以通过命令lsof(list open files)查看打开文件的进程。

  1. 截断文件

truncate命令可将文件缩小、扩展到指定的大小。通常用来清除日志文件,-s指定字节大小。

1
truncate -s 0 /var/log/xx.log 

cat /dev/null > xx.log 会使文件内容为null,文件大小为0;echo '' > xx.log会使文件内容为空字符串,文件大小为1。

1
cat /dev/null >

格式:
find <文件路径> <条件> <文件名>

常用参数

-name匹配文件名-nouser匹配无所属主的文件
-perm匹配文件权限-nogroup匹配无所属组的文件
-user匹配文件所属主-newer匹配比指定文件更新的文件
-group匹配文件所属组-type匹配文件类型
-mtime匹配最后修改文件内容时间-size匹配文件大小
-atime匹配最后读取文件内容时间-prune不搜索指定目录
-ctime匹配最后修改文件属性时间-exec…… {};进一步处理搜索结果

按时间查找

查找/目录下,距离现在7天之前修改过的文件

1
find / -mtime 7 -ls|head

-mtime: 文件修改时间;-ctime:改变时间(权限、属主等);-atime: 访问时间(read);
-mmin,-cmin,-amin以分钟为单位,上面三个以天为单位
时间比较参数:-mnewer: 修改时间比xxx文件更晚的文件。 还有anewercnewer
7:当前时间-文件修改时间=7,即距今7天时修改的文件;-7:修改时间差<7的文件;+7:修改时间差>7的文件
-ls:详细信息;
head:默认显示前10行

grep命令

grep: Global Regular Expression Print(全局正则表达式版本)的缩写, 文本搜索工具。

匹配所有d开头文件中包含test的行

1
grep 'test' d*

匹配xx文件中至少包含5个连续小写字母的行

1
grep '[a-z]\{5\}' xx

目录操作

默认 只搜索当前目录
-r 搜索子目录
-d 忽略子目录搜索

POSIX

全名为Portable Operating System Interface(可移植操作系统接口),由IEEE制定的OS接口标准化的规范。保证不同Unix系统上的应用的兼容性。

POSIX规范将正则表达式实现分为两种:基本正则表达式(BRE)、扩展正则表达式(ERE)

POSIX还规定了线程之间的隔离屏障、线程内存空间大小等。

通配符规则(glob)

POSIX中对glob()函数的标准化,定义一种模式匹配规则,用于匹配文件系统中的文件名(类似Shell中的通配符,但更为灵活)。

以下是一些常见的通配符和它们的含义:

通配符含义举例
*匹配零个或多个任意字符。例如,*.txt 匹配所有以 .txt 结尾的文件名。
?匹配任意单个字符。例如,file?.txt 匹配 file1.txt、file2.txt 等。
[]用于指定一个字符集,可以匹配方括号中的任何单个字符。例如,file[123].txt 匹配 file1.txt、file2.txt、file3.txt。
{}用于指定多个可能的匹配项,以逗号分隔。例如,{*.txt,*.pdf} 匹配所有以 .txt 或 .pdf 结尾的文件名。
!用于排除匹配项。例如,!*.txt 匹配所有不以 .txt 结尾的文件名。

基本正则表达式(BRE)

类型元字符语法举例
转义字符\用于转义特殊字符,使其失去其特殊含义。\t: 制表符;\r: 回车;\n: 换行;\.: 小数点本身
字符集\d一个数字。\d: “9”,“0”,“1”
\w一个非空字符A-Za-z0-9_。\w: “A”,“a”,“0”,"_"
\s一个空白字符。\s: “\t”, “\n”
.\n外的任一字符.: “A”,“a”,“0”,"_","\t","\r"
自定义字符集[][]匹配内的任字符[ab@#]: “a”, “b”, “@”, “#”
[-][-]范围的任字符[a-d]: “a"到"d"之间的任一字符
[^][^]匹配之外的任字符[^ab@#]: 非"a”, “b”, “@”, “#“的任一字符
匹配次数{n}表达式匹配N次a{3}: “aaa”
{m,n}M =< 表达式匹配次数 <= N。[ab]{1,2}: “a”, “aa”, “b”, “bb”
{m,}M =< 表达式匹配次数\w\d{2,}: “a12”, “_4567”, “A12345”…
?0次或者1次,等同{0,1}a[bc]?: “a”, “ac”, “ad”
+1次以上,等同{1,}a+b: “ab”, “aab”, “aaab”…
*0次以上(不出现或者任意次),等同{0,}a*b: “b”, “ab”, “aab”…
非贪婪模式匹配次数后加?,匹配次数不定的表达式尽可能少的匹配目标文本"dxxdxxxxd”: 正则d\w+?: “dx”; 正则d\w+?d: “dxxd”
其他^字符串开始地方匹配^aa: “aaxxx”
$字符串结束地方匹配bb$: “xxxbbb”
\d匹配单词边界,即单词与空格之间
表达式``或,既可匹配左表达式,又可匹配右表达式
()1. 匹配次数时,()内被整体修饰;(ab)+: “ab”, “abab”…
2. 取结果时,()中的内容可单独取到¥(\d+.?\d*): “¥ 20.5”…,单独获取括号范围匹配内容为"20.5”
\d匹配单词边界,即单词与空格之间

举例

  1. 数字:^[0-9]*$

  2. n位的数字:^\d{n}$

  3. 至少n位的数字:^\d{n,}$

  4. 零和非零开头的数字:^(0|[1-9][0-9]*)$

  5. 非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$

  6. 带1-2位小数的正数或负数:^(-)?\d+(.\d{1,2})?$

  7. 正数、负数、和小数:^(-|+)?\d+(.\d+)?$

  8. 有两位小数的正实数:^[0-9]+(.[0-9]{2})?$

  9. 有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$

  10. 非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]){1,3}$ 或 ^+?[1-9][0-9]$

  11. 非零的负整数:^-[1-9][]0-9"$ 或 ^-[1-9]\d$

  12. 非负整数:^\d+$ 或 ^[1-9]\d*|0$

  13. 非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$

  14. 非负浮点数:^\d+(.\d+)?$ 或 ^[1-9]\d*.\d*|0.\d*[1-9]\d*|0?.0+|0$

  15. 浮点数:^(-?\d+)(.\d+)?$ 或 ^-?([1-9]\d*.\d*|0.\d*[1-9]\d*|0?.0+|0)$

4.2 检验字符

  1. 汉字:^[\u4e00-\u9fa5]{0,}$

  2. 英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$

  3. 长度为3-20的所有字符:^.{3,20}$

  4. 由26个英文字母组成的字符串:^[A-Za-z]+$

  5. 由26个大写英文字母组成的字符串:^[A-Z]+$

  6. 由26个小写英文字母组成的字符串:^[a-z]+$

  7. 由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$

  8. 由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$

  9. 中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$

  10. 中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$

  11. 可以输入含有^%&’,;=?$"等字符:[^%&’,;=?$\x22]+ 12 禁止输入含有~的字符:[^~\x22]+

文件描述符与输出重定向

1
bash your_script.sh > /dev/null 2>&1

>操作符将标准输出重定向到/dev/null,2>&1将标准错误重定向到与标准输出相同的位置,也就是/dev/null,这样就会丢弃所有的输出。
0: 标准输入;1: 标准输出; 2: 标准错误输出; 3及以上: 非默认动态创建。&用于将输出重定向到文件描述符,而不是文件。

servicesystemctl的区别与联系

RHEL 5/6系统,使用service命令来管理系统服务
RHEL 7/8系统,使用systemctl命令来管理服务

1
systemctl start|restart|stop|reload|status httpd

Bash与Shell的关系

Shell是接受用户指令,然后将指令交给系统执行的软件的统称,Bash是其中一种解释器,Bash是Sell的子集。

Linux系统与Linux内核

Linux内核:控制计算机系统的所有软件和硬件,在必要时分配硬件。并根据需要执行软件。主要有四种功能:内存管理、软件程序管理、硬件设备管理、文件系统管理。

Linux系统:OS是

ps命令

参数作用
-a显示所有进程(包括其他用户进程)
-u显示详细信息(用户信息等)
-x显示没有控制终端的进程

进程状态:

R(运行):进程正在运行或在运行队列中等待。
S(中断):进程处于休眠中,当某个条件形成后或者接收到信号时,则脱离该状态。
D(不可中断):进程不响应系统异步信号,即便用kill命令也不能将其中断。
Z(僵死):进程已经终止,但进程描述符依然存在, 直到父进程调用wait4()系统函数后将进程释放。
T(停止):进程收到停止信号后停止运行。
除了上面5种常见的进程状态,还有可能是高优先级(<)低优先级(N)被锁进内存(L)包含子进程(s)以及多线程(l)
这5种补充形式。

nice命令

调整进程优先级。格式 nice <优先级Num> <服务名称>

在top命令输出的结果中,PR和NI值代表的是进程的优先级(取值范围是-20~19),数字越低,优先级越高。

例如,将bash服务的优先级调至最高

1
nice -20 bash

pidof命令

查询指定服务进程的PID。格式:pidof <服务名|sshd>

转义字符

参数存在空格,但需要作为一个参数传递:双引号
双引号中的某些字符需要转义:反斜杠
不希望出现转义:单引号

4个最常用的转义字符如下所示:

反斜杠(\):使反斜杠后面的一个变量变为单纯的字符。

单引号(’ ‘):转义其中所有的变量为单纯的字符串。

双引号(" “):保留其中的变量属性,不进行转义处理。

反引号( :把其中的命令执行后返回结果。

Shell脚本参数说明

example.sh one two three命令举例:

$#: 参数的数量, 示例中值为3
$*: 所有参数的值(空格分隔),示例中值为"one two three”
$?: 上一次命令的返回值(交互式模式比较常用)
$0: 脚本文件名, 示例中值为"example.sh"
$1: 第一个参数, 示例中值为"one"
$2: 第二个参数, 示例中值为"two"

Shell脚本控制语句

判断语句

类型操作符说明
文件判断-etrue: 文件存在
-dtrue: 目录类型
-ftrue: 一般文件
-rtrue: 文件可读
-wtrue: 文件可写
-xtrue: 文件可执行
逻辑判断&&与:成功才会执行后语句
||或:失败才会执行后语句
!非:
!非:
数值判断-eq等于
-ne不等于
-gt大于
-lt小于
-le小于等于
-ge大于等于
字符判断=字符串相同
=字符串不同
-z字符串为空

交互式

  • 判断当前用户,root用户打印”administer“;普通用户打印”user“
1
[ ! $USER = root ] && echo "user" || echo "root"

对($USER = root)的结果取反,即,当用户不为root时,打印user(前语句成功,才执行&&后语句);当用户为root时,打印root(前语句echo user失败, 执行||语句)

等同于[ $USER = root ] && echo "root" || echo "user"

  • 查看内存可用量,如果<1024M,则打印"内存不足"
1
2
3
FreeM=`free -m | grep 'Mem:' | awk '{print $4}'`

[FreeM -lt 1024] && echo "low memory"

批处理

格式
单分支:

1
2
3
4
if [条件]
then
    echo "True echo"
fi

双分支:

1
2
3
4
5
6
if [条件]
then
  echo "True"
else
  echo "False"
fi

多分支:

1
2
3
4
5
6
7
8
if [条件A]
then
  echo "条件A is True"
elif [条件B]
  echo "条件B is True"
else
  echo "条件A & 条件B is False"
fi

判断主机是否在线

1
2
3
4
5
6
7
8
ping -c 3 -i 0.2 -w 3 $1 > /dev/null 2>&1 

if [ $? -eq 0]
then
  echo "$1 is OnLine"
else
  echo "$1 is OffLine"
fi

ping 发送3个数据包,间隔0.2秒,超时时间3秒,目标IP从脚本第一个参数获得,并丢弃标准输出和错误输出(也可写省略写法 ping xxx &> /dev/null
判断上面ping命令的执行结果,等于0意味着,ping命令执行成功,服务可达;不等于0意味着,ping命令失败,服务不可达。

for循环

格式

1
2
3
4
for i in $取值列表
do
  echo $i
done

while循环

死循环,可通过exit,在合适的实际退出死循环。
格式

1
2
3
4
while [条件]
do
  echo ”“
done 

case语句

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
case 变量 in
模式1)
  echo "变量 in 模式1"
  ;;
模式2)
  echo "变量 in 模式1"
  ;;
*)
  echo "Default"
esac

周期任务

  • 语法分 时 日 月 星期 命令
  • 时间间隔*/2
  • 时间范围,一种:1-3;另一种1,2,3

注意事项

  • 文件目录必须写绝对路径
  • 分字段必须有数值,不能为空或者*
  • 日、星期字段不能同时使用
分享

Hex
作者
Hex
CloudNative Developer

目录