shell 脚本开头的两个字符叫做 shebang “#!”。在unix系统中,程序会分析 shebang 后面内容,作为解析器的指令。相当于告诉系统用那种解析器去解读脚本。yarn 就是python 开发的
- 以 #!/bin/sh 开头的文件,程序在执行的时候会调用 /bin/sh,也就是bash解释器
- 以 #!/usr/bin/python 开头的文件,代表指定python解释器去执行
- 以 #!/usr/bin/env 解释器名称,是一种在不同平台上都能正确找到解释器的办法
运行
新建一个shell脚本, test.sh
1 | !/bin/sh |
运行
1 | test.sh # 找不到目录 |
查看当前解析器
1 | echo $SHELL |
脚本注释
为了方便阅读,要有写注释的习惯。
当行注释: #
常用命令
history
查看历史命名,echo $HISTSIZE 命令历史条数
打开会话历史文件 ~/.bash_history
1
2
3
4
5
6
7history #命令以及参数
-c:清空内存中命令历史;
-r:从文件中恢复历史命令
数字 :显示最近n条命令 history 10
执行指定历史命令 !id: !502
执行上一条命令: !!echo
1
2
3
4
5
6
7
8-n 不换行输出
-e 解析字符串特殊符号
\r 回车
\t 制表
\n 换行
\b 退格eval
执行多个命令
1
eval ls; cd /tmp
exec
不创建子进程,执行后续命令,执行完毕自动 exit
1
exec date
export
read
shift
快捷键
1 | ctrl + l # 清屏 |
变量
临时存放,shell 进程是一个作用域,弱类型跟js一样。
变量与赋值之间不能空格
单引号不识别特殊语法,双引号识别
1 | name='aaa' |
特殊变量
1 | 0 获取she11脚本文件名,以及脚本路 |
$@ 与 $ 的区别*
1 | !/bin/bash |
特殊状态变量
1 | ? 上一次命令执行状态返回值,0正确,非0失败 |
source 是在当前shell环境加载脚本,因此保留当前变量。bash都会开启一个子shell,不会保留当前shell变量
脚本控制返回值玩法
test.sh
1 | !/bin/bash |
执行完上边脚本,$? 会保存 119
1 | 此时会提示 must be two args |
让程序后台执行
1 | 后台执行 ping baidu.com 并将日志输出到黑洞文件中.命令产生一个pid |
环境变量
个人变量优先于全局
用户个人配置文件 ~/.bash_profile
远程用户特有文件 ~/.bashrc
全局配置文件 /etc/profile, /etc/bashrc. 系统建议不要直接修改主文件而是创建 /etc/profile.d/
set : 检索变量 name开头
1 | set |grep ^name |
env : 只显示全局变量
1 | env |wc -l # 显示输出条数 |
declare: 输出所有的变量,如同set
export: 显示和设置环境变量值
unset 变量名: 撤销环境变量
readonly:只有shell结束,只读便变量失效。只对当前shell生效
子串玩法
1 | ${变量) 返回变量值 |
统计字符串长度的其他方法
1 | expr length "${name}" |
子串拓展
1 | 如果parameter变量值为空,返回word字符串${parameter:-word} |
删除7天以上的过期数据
1 | find xargs 搜索,且删除 |
linux 特殊符号
1 | {vars} 取出变量结果 |
父子shell
开启子shell去做其他事情不会耽误我去做其他事情,类似于于多进程
-
- source和点执行脚本,只在当前的shell环境中执行生效
- 指定bash sh解释器运行脚本,是开启subshell ,开启shell运行脚本命令
- ./script,都会指定shebang, 通过解释器运行,也是开启subshell 运行命令
父子 shell 查看方式
1 | pstree |
创建进程列表
使用小括号
1 | (cd ~; pwd;ls; cd /tmp/; pwd; ls) |
判断父子shell
通过内置变量 $BASH_SUBSHELL, 值为0 则是当前shell,否者就是可开启了子shell
内置命令,外置命令
内置命令:在系统启动时就在载入内存,常驻内存,执行效率高但是占用资源。如 cd,
外置命令:用户需要从硬盘中读取,在写入内存加载.如 nginx
判断命令是否内置,外置命令
- 通过Linux的 【type 命令 】验证(输出此命令是shell内嵌),不会开启子进程
- 外置命令执行肯定会开启子进程
- 查询所有内置命令:compgen -b
循环
1 | for n in {1..100} |
1 | 统计循环时间 |
批量修改文件名
将所欲后缀 _finished.jpg 图片名称去除 _finished
1 | 找出所有图片名包含 xxx_finished.jpg |
数值运算
linux 大多运算不持支小数。 大多数运算符与js,java 类似
双小括号
1 | 这总反式不能取值 |
比较运算中 真为1 ,假为0
运算脚本
1 | !/bin/bash |
let 命令
let 命令等同于双括号计算,((赋值表达式))。但是双括号效率更高
1 | rs=5 |
expr 命令
expr 命令允许在命令处理数学表达式。
1 | expr 1 + 1 |
模式匹配
- :, 计算字符串中的字符数
- .*,任意字符串重复0次或多次
1 |
|
应用
通过是否匹配的上来判断文件格式,返回长度0 不能匹配,长度>0匹配
bc 管道命令
整数计算,双小括号,let,expr。带小数计算使用 bc
1 | echo 4*4|bc |
中括号运算[]
$[表达式]语法如此,加减乘除
1 | rs=10 |
awk计算
支持小数,if 条件判断
1 | echo "3.2 3.2" | awk '{print ($1+4*$2)}' |
用户输入
read 内置命令
-p 设置提示信息
-t 等待用户输入超时, timeout
1 | read -p "给你5s中,时间输入密码:" pwd |
if-then 语句
编程语言中 if 条件语句要求 结果是 false,true.而shell中并不是,bash 的if 语句会直接运行后边的命令,如果其执行正确则进入 then 否则不进入
1 | if command |
if-then-else 语句
增加了一个判断条件
1 | if command |
elif
1 | if command |
test
用于评估一个表达式;如果条件为真,则返回一个0, 非0则为假。判断结果通过 $? 访问
文件类型侦测
1
test -e filename
-e 该文件名] 是否存在?(常用)
-f 该文件名是否为文件(file)?(常用)
-d 该文件名 是否为目录(directory)? (常用)
-b 该文件名是否为一个 block device 装置?
-c 该[文件名是否为一个 character device 装置?
-s 该文件名是否为一个 Socket 文件?
-p 该文件名是否为一个 FIFO (pipe) 文件?
-L 该文件名是否为一个连结档?
文件权限侦测
1
test -r filename
-r 侦测该文件名是否具有可读。的属性?
-w 侦测该文件名是否具有可写。的属性?
-x 侦测该文件名是否具有 可执行, 的属性?
-u 测该文件名是否具有 SUID 的属性?
-g 侦测该文件名是否具有 SGID 的属性?
-k 侦测该文件名是否具有 sticky bit 的属性?
-s 测该文件名是否为非空白文件。?
两个文件之间比较
1
test file -nt file2
-nt (newer than)判断 file1 是否比 file2 新
-ot (older than)判断 file1 是否比 file2 旧
-ef 判断 file2与 file2是否为同一文件,可用在判断 hard link 的判定
两整数之间判断
1
test n1 -eq n2
-eq 两数值相等(equal)
-ne 两数值不等 (not equal)
-gt n1 大于 n2 (greater than)
-lt n1 小于 n2 (less than)
-ge n1 大于等于 n2 (greater than or equal)
-le n1 小于等于 n2 (less than or equal)
判断字符串的数据
1
2
3
4
5
6test -z string # 字符串为0?true: false
test -n string # 判断字符串是否为0?false: true, -n 可省略
test str1 = str2 # 相等 true, 反之 false
test str1 != str2 # 相等 返回false, 反之 true多重判断
1
test -r filename -a -x filename
-a 两种状况同时成立
-o 两种状况任意成立
! 反相状态
简洁的测试方式
1 | 注意空格 |
Linux 内存监控
1 | FreeMem=`free -m |awk 'NR==2' {print $NF}` |
符合条件测试
[ 条件1 ] && [ 条件2 ]
[ 条件1 ] || [ 条件2 ]
布尔运算符
1 | !/bin/bash |
测试 nginx 服务是否存在
1 | !/bin/bash |
双小括号
前面计算时就用到了这个语法,它支持数值运算,逻辑运算。还能在if 条件中使用
1 | val=10 |
双方括号
双方括号提供了针对字符串的高级特性,模式匹配,正则表达式的匹配。双括号中字符不需要转义。一般不用,特殊场景使用
双括号中可以使用 &&,||,!
1 | 在双中括号里,进行了 == 双等号,进行字符串匹配 r*,也就找到了 root 。 |
中括号
也可以做一些数值字符比较,但是中括号中 字符需要 添加转义符,很常用
中括号中不能使用逻辑运算符 ||,&&, 要使用 -a ,-o 代替
case 语句
1 | 语法 |
while 循环
1 | while test command |
- 本文作者: 王不留行
- 本文链接: https://wyf195075595.github.io/2023/04/23/programming/linux/shell/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!