要想玩转Linux系统,编写shell脚本是必须要掌握的技能。那什么是shell编程呢?简单来说,shell编程就是对多个Linux命令进行逻辑处理。
下面,我们从编程的基础开始讲起:
一、编程基础
1.什么是程序?
程序是指:指令+数据
程序编程风格可分为:
过程式:以指令为中心,数据服务于指令(关注过程,小软件开发)
对象式:以数据为中心,指令服务于数据(关注结果,适合开发大型软件)
2.程序的执行方式
计算机:运行二进制命令
编程语言:
低级:汇编
高级:
编译:高级语言–>编译器–>目标代码 (由程序员完成编译器翻译过程,安全性相对好)
java,C#
解释:高级语言–>解释器–>机器代码 (由电脑完成解释器翻译过程,安全性不如编译型)
shell,perl,python
shell程序:提供了编程能力,解释执行
3.编程基本概念
编程逻辑处理方式:
顺序执行
循环执行
选择执行
shell编程:过程式、解释执行
编程语言的基本结构:
各种系统命令的组合
数据存储:变量、数组
表达式:a+b
语句:if
二、脚本基本格式
格式要求:
首行shebang机制(即声明脚本使用哪种编程语言)
如: #!/bin/bash
#!/bin/python
shell脚本的用途有:
自动化常用命令
执行系统管理和故障排除
创建简单的应用程序
处理文本或文件
运行脚本:
- 给予执行权限,执行
- 直接运行解释器,将脚本作为解释器程序的参数运行
脚本规范:
脚本代码开头约定:
- 第一行一般为调用使用的语言
- 程序名,避免更改文件名为无法找到正确的文件
- 版本号
- 更改后的时间
- 作者相关信息
- 该程序的作用,及注意事项
- 最后是各版本的更新简要说明
脚本示例:
1 | \#!/bin/bash |
脚本调试:
- bash -n script 检查脚本的语法错误
- bash -x script 调试脚本执行
三、变量
定义变量时,变量名不加$符号,如:
1 | my_name="wangx" |
变量命名规则:
- 数字、字母、下划线,不能以数字开头
- 不能使用程序中的保留字:如if,for等
- 做到见名知意
注意:
引用变量一般需加$
赋值变量:
name=” “ 要加引号
存放多行字符时”$name”变量外加双引号可保留换行格式
bash变量的种类
局部变量、全局变量、本地变量、位置变量、特殊变量
局部变量:只在当前shell进程生效,对当前shell之外其他shell进程,包括父shell和子shell都无效
全局变量:生效范围在当前shell进程及其子进程;父进程变量可以传给子进程,子进程变量不可向上传给父进程
数字变量:$10以上的变量需要加花括号${10}
特殊变量:$1,$@,$*,$#,$0等、
$1,$2,…:对应第1、第2参数,shift[n]换位置
$0:命令本身
$*:传递给脚本的所有参数,每个参数合为一个字符串
$@:传递给脚本的所有参数,每个参数为独立字符串
$#:传递给脚本的参数的个数
$@$*只在被双引号包起来的时候才会有差异
set– 清空所有位置变量
注:怎么判断变量前加不加$符号?
如果命令能识别变量就不加$,如果命令不能识别变量加$;
养成好习惯:编完脚本将变量用unset删掉;
()中使用的命令为一次性的,小括号中相当于在子进程中执行命令
注:小括号中所说的子进程与常规的子进程不是一回事
例如:x=1;echo $$;(echo $$)中显示进程号一致
{ ;}中使用命令时在当前shell环境中执行,不开启子进程影响当前shell环境
变量运算
bash中的算术运算:help let
+,-,*,/,%取余,**乘方
实现算术运算:
- let var=算术表达式
- var=$[算术表达式]
- var=$((算术表达式))
注:算术运算过程中,空格尽量删除
条件测试过程中,能加空格地方尽量加空格
正则条件测试时,正则表达式不加引号
四、条件测试
测试命令:
test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]] 双括号一般用于左侧字符匹配右侧扩展正则表达式
注:EXPRESSION前后必须有空白字符
评估布尔声明,以便用在条件性执行中:
若真,则返回0
若假,则返回1
例如:
1 | a=1;b=2 |
条件性的执行操作符
&&代表条件性的AND THEN,前面执行结果$?=0时,继续执行&&后命令
||代表条件性的OR ELSE,前面执行结果$?不为0时,执行||后命令
test 与[ ]效果相同,注意括号里内容两边需加空格
-v VAR 变量VAR是否设置
数值测试:
1 | -gt 是否大于(greater-than) |
字符串测试:
1 | == 是否等于 |
文件相关测试:
存在性测试:
1 | -a FILE 同-e |
存在性及类别测试:
1 | -b FILE 是否存在且为块设备文件 |
文件权限测试:
1 | -r FILE 是否存在且有可读权限 |
文件特殊权限测试:
1 | -u FILE 是否存在且拥有suid权限 |
文件小测试:
1 | -s FILE 是否存在且非空 |
文件是否打开:
1 | -t fd:fd 文件描述符是否在终端已经打开 |
注意:文件测试后跟空字符时,也反馈为True,如果要保证一个文件存在且满足测试条件时,
应表示为:
例:[ -n “file” -a -d “file” ]
file文件是否存在且为目录文件
双目测试:
1 | FILE1 -ef FILE2 FILE1是否是FILE2的硬链接 |
Bash的组合测试条件:
第一种方式:
1 | COMMAND1 && COMMAND2 并且 |
第二种方式:
1 | [ EXPRESSION -a EXPRESSION ] 并且 |
注:优先级为:”!”最高,”-a”次之,”-o”最低
短路与&&
1 | 0&&0=0 |
cmd1 && cmd2
如果cmd1为假,cmd2不需要执行,反之cmd1为真,需要cmd2执行
短路或||
1 | 0||0=0 |
cmd1 || cmd2
如果cmd1为真,cmd2不需要执行,反之cmd1为假,需要cmd2执行
异或 ^
如果相同为假,反则为真
1 | 0 ^ 1 = 1 |
注意:[ ]和test用变量时,最好加双引号””避免出问题
1 | false || { echo cmd1 ; echo cmd2 ; } |
使用read命令来接受输入
read 使用read来把输入值分配给一个或多个shell变量
1 | -p 指定要显示的提示 |
read命令从标准输入中读取单词,并给每个单词分配一个变量
例如:
read -p “Enter a filename:” FILE 标准输入将赋予变量$FILE
read命令从标准输入中读取单词,并给每个单词分配一个变量
read 给多个变量赋值的方法:
将多个变量输入一个文件中,用空格分开,输出重定向
1
read a b c < f
用”>>>”分开:
1
read a b c <<< "x y z"
五、配置用户环境
bash的配置文件
按生效范围划分,存在两类:
全局配置:
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc
个人配置:
~/.profile
~/.bashrc
shell登录的两种方式:
交互式登录:
1. 直接输入账号密码登录
2. su – username 切换的用户
执行顺序:/etc/profile –> /etc/profile.d/*.sh –> ~/.bash_profile –> ~/.bashrc–> /etc/bashrc
非交互式的登录:
1. su usernme
2. 图形界面打开的终端
3. 执行脚本
4. 任何其他的bash实例
执行顺序:~/.bashrc –> /etc/bashrc –> /etc/profile.d/*.sh
注:只在交互式登录生效:/etc/profile,~/.bash_profile
配置执行文件按功能划分,存在两类:
profile类和bashrc类
Profile类:为交互式登录的shell提供配置
全局生效:/etc/profile ,/etc/profile.d/*.sh
个人生效:~/.bash_profile
功用:
用于定义环境变量
运行命令或脚本
Bashrc类:为非交互式和交互式登录的shell提供配置
全局生效:/etc/bashrc
个人生效:~/.bashrc
功用:
- 定义命令别名和函数
- 定义本地变量
修改profile和bashrc文件后使生效的两种方法:
重新启动shell进程
.或sourc;例:.~/.bashrc
注: .或source执行脚本表示将在当前进程运行,而不是开启一个子进程运行(配置文件一般用此方式执行)
bash执行脚本则是开启一个进程执行(运行脚本一般用此方式执行)
Bash退出任务
保存在~./.bash_logout文件中(用户)
在退出登录shell时运行
可用于:
创建自动备份
清除临时文件
清除操作历史等
特殊的变量$-
1 | \#echo $- |
bash展开命令的优先级:
把命令行分成单个命令词
展开别名
展开大括号{}
展开波浪符~
命令替换$()和
再次把命令行分成命令词
展开文件通配(*、?等)
I/O重定向
运行命令