计算机只能认识(识别)机器语言(0和1),如(11000000 这种)。但是,我们的程序猿们不能直接去写01这样的代码,所以,要想将程序猿所开发的代码在计算机上运行,就必须找"人"(工具)来翻译成机器语言,这个"人"(工具)就是我们常常所说的编译器或者解释器。
编译型语言比解释型语言速度较快,但是不如解释型语言跨平台性好。如果做底层开发或者大型应用程序或者操作系开发一般都用编译型语言;如果是一些服务器脚本及一些辅助的接口,对速度要求不高、对各个平台的兼容性有要求的话则一般都用解释型语言。
总结:
# cat /etc/shells
/bin/sh #是bash的一个快捷方式
/bin/bash #bash是大多数Linux默认的shell,包含的功能几乎可以涵盖shell所有的功能
/sbin/nologin #表示非交互,不能登录操作系统
/bin/dash #小巧,高效,功能相比少一些
/bin/csh #具有C语言风格的一种shell,具有许多特性,但也有一些缺陷
/bin/tcsh #是csh的增强版,完全兼容csh思考:终端和shell有什么关系?

若干命令 + 脚本的基本格式 + 脚本特定语法 + 思想= shell脚本
重复化、复杂化的工作,通过把工作的命令写成脚本,以后仅仅需要执行脚本就能完成这些工作。
①自动化软件部署 LAMP/LNMP/Tomcat...
②自动化管理 系统初始化脚本、批量更改主机密码、推送公钥...
③自动化分析处理 统计网站访问量④自动化备份 数据库备份、日志转储...
⑤自动化监控脚本
多看(看懂)——>模仿(多练)——>多思考(多写)
1)脚本第一行,魔法字符**#!**指定解释器【必写】
#!/bin/bash 表示以下内容使用bash解释器解析
注意: 如果直接将解释器路径写死在脚本里,可能在某些系统就会存在找不到解释器的兼容性问题,所以可以使用:#!/bin/env 解释器 #!/bin/env bash
2)脚本第二部分,注释(#号)说明,对脚本的基本信息进行描述【可选】
#!/bin/env bash
# 以下内容是对脚本的基本信息的描述
# Name: 名字
# Desc:描述describe
# Path:存放路径
# Usage:用法
# Update:更新时间
#下面就是脚本的具体内容
commands3)脚本第三部分,脚本要实现的具体代码内容
编写人生第一个shell脚本
# cat example.sh
#!/bin/env bash
# 以下内容是对脚本的基本信息的描述
# Name: example.sh
# Desc: num1
# Path: /tmp/shell/example.sh
# Usage:/tmp/shell/example.sh
# Update:2019-05-05
echo "hello Aluo"
echo "hello world"
# pwd
/tmp/shell1、以路径方式执行,包括相对路径和绝对路径两种方式。
1) 相对路径
# cd /tmp/shell
# chmod +x example.sh
# ./example.sh
2) 绝对路径
# chmod +x /tmp/shell/example.sh
# /tmp/shell/example.sh
说明: ./ 代表在当前的工作目录下执行example.sh。如果不加上 ./,bash可能会因找不到相应example.sh而报错,因为目前的工作目录(/tmp/shell)可能不在执行程序默认的搜索路径之列,也就是说,不在环境变量 PASH的内容之中。查看PATH的内容可用echo $PASH命令。现在的/tmp/shell就不在环境变量PASH中的,所 以必须加上./才可执行。
路径方式执行要求脚本文件有可执行权限,所以需要事先设定脚本文件的执行权限。2、直接在命令行指定解释器执行,使用 bash 或 sh 命令执行。
1) bash
# cd /tmp/shell
# bash example.sh
# bash -x example.sh
+ echo 'hello Aluo'
hello Aluo
+ echo 'hello world'
hello world
----------------
-x:一般用于排错,查看脚本的执行过程
-n:用来查看脚本的语法是否有问题
------------
2) sh
# cd /tmp/shell
# sh example.sh
说明:使用bash或sh命令执行可以不必事先设定脚本文件的执行权限,甚至都不用写shell文件中的第一行(指定bash路径),因为这种方式是将example.sh作为参数传给sh(bash)命令来执行的,这时不是example.sh自己来执行,而是被人家调用执行,所以不要执行权限。那么不用指定bash路径自然也好理解了。3、在当前 shell 环境中执行
1) source
# cd /tmp/shell
# source example.sh # 或source /tmp/shell/example.sh
2) .
# cd /tmp/shell
# . example.sh # 或. /tmp/shell/example.sh
说明:前面两种方法执行shell脚本时都是在当前shell(称为父shell)中开启的一个子shell环境中去执行,shell脚本执行完后子shell环境随即关闭,然后又回到父shell中。而方法3则是在当前shell中执行的。一句话概括:变量是用来临时保存数据的,该数据是可以变化的数据。
变量名=变量值
变量名:用来临时保存数据的
变量值:就是临时的可变化的数据
# A=hello 定义变量A
# echo $A 调用变量A,要给钱的,不是人民币是美元"$"
hello
# echo ${A} 还可以这样调用,不管你的姿势多优雅,总之要给钱
hello
# A=world 因为是变量所以可以变,移情别恋是常事
# echo $A 不管你是谁,只要调用就要给钱
world
# unset A 不跟你玩了,取消变量
# echo $A 从此,我单身了,你可以给我介绍任何人虽然可以给变量(变量名)赋予任何值;但是,对于变量名也是要求的!
# A=hello
# a=world
# echo $A
hello
# echo $a
world# *A=hello
-bash: *A=hello: command not found
# ?A=hello
-bash: ?A=hello: command not found
# @A=hello
-bash: @A=hello: command not found
特别说明:对于有空格的字符串给变量赋值时,要用引号引起来
# A=hello world
-bash: world: command not found
# A="hello world"
# A='hello world'# 1A=hello
-bash: 1A=hello: command not found
# A1=hello
注意:不能以数字开头并不代表变量名中不能包含数字呦。# A =123
-bash: A: command not found
# A= 123
-bash: 123: command not found
# A = 123
-bash: A: command not found
# A=123
# echo $A
123NTP_IP=10.1.1.1
DIR=/u01/app1
TMP_FILE=/var/log/1.log
...
说明:一般变量名使用大写(小写也可以),不要同一个脚本中变量全是a,b,c等不容易阅读直接赋值给一个变量
# A=1234567
# echo $A
1234567
# echo ${A:2:4} 表示从A变量中第3个字符开始截取,截取4个字符
3456
说明:
$变量名 和 ${变量名}的异同
相同点:都可以调用变量
不同点:${变量名}可以只截取变量的一部分,而$变量名不可以# B=`date +%F`
# echo $B
2019-04-16
# C=$(uname -r)
# echo $C
2.6.32-696.el6.x86_64**目的:**让用户自己给变量赋值,比较灵活。
语法:read [选项] 变量名
常见选项:
选项 | 释义 |
|---|---|
-p | 定义提示用户的信息 |
-n | 定义字符数(限制变量值的长度) |
-s | 不显示(不显示用户输入的内容) |
-t | 定义超时时间,默认单位为秒(限制用户输入变量值的超时时间) |
举例说明:
用法1:用户自己定义变量值
# read name
harry
# echo $name
harry
# read -p "Input your name:" name
Input your name:tom
# echo $name
tom用法2:变量值来自文件
# cat 1.txt
10.1.1.1 255.255.255.0
# read ip mask < 1.txt
# echo $ip
10.1.1.1
# echo $mask
255.255.255.0目的: 给变量做一些限制,固定变量的类型,比如:整型、只读
用法:declare 选项 变量名=变量值
常用选项:
选项 | 释义 | 举例 |
|---|---|---|
-i | 将变量看成整数 | declare -i A=123 |
-r | 定义只读变量 | declare -r B=hello |
-a | 定义普通数组;查看普通数组 | |
-A | 定义关联数组;查看关联数组 | |
-x | 将变量通过环境导出 | declare -x AAA=123456 等于 export AAA=123456 |
举例说明:
# declare -i A=123
# echo $A
123
# A=hello
# echo $A
0
# declare -r B=hello
# echo $B
hello
# B=world
-bash: B: readonly variable
# unset B
-bash: unset: B: cannot unset: readonly variable# ps # 当前bash的进程号为29105
PID TTY TIME CMD
29105 pts/2 00:00:00 bash
29354 pts/2 00:00:00 ps
# echo $$ # 当前bash的进程号为29105
29105
# name=aluo
# echo $name
aluo
# /bin/bash # 再开启一个bash
# ps
PID TTY TIME CMD
29105 pts/2 00:00:00 bash
29355 pts/2 00:00:00 bash
29366 pts/2 00:00:00 ps
# ps auxf | grep bash # 进程号为29355的bash是进程号为29105的bash的子进程
root 28884 0.0 0.1 115680 2204 pts/1 Ss 10:37 0:00
root 29027 0.0 0.1 115680 2132 pts/1 S 12:32 0:00
root 29039 0.0 0.1 115680 2156 pts/1 S+ 12:32 0:00
root 29105 0.0 0.1 115680 2260 pts/2 Ss 13:30 0:00
root 29355 0.0 0.1 115680 2124 pts/2 S 15:15 0:00
root 29368 0.0 0.0 112812 972 pts/2 S+ 15:15 0:00
# echo $$ # 打印当前所在进程的进程号
29355
# echo $name # 子进程中无法调用父进程中定义的name变量
# exit
exit
# echo $name
aluoenv查看当前用户的环境变量set查询当前用户的所有变量(临时变量与环境变量)export 变量名=变量值 或者 变量名=变量值;export 变量名 或者 declare -x 变量名=变量值# export A=hello # 临时将一个本地变量(临时变量)变成环境变量
# env|grep ^A
A=hello
永久生效:
vim /etc/profile 或者 ~/.bashrc
export A=hello
或者
A=hello
export A
说明:
系统中有一个变量PATH,环境变量
export PATH=/usr/local/mysql/bin:$PATH文件名 | 说明 | 备注 |
|---|---|---|
~/.bashrc | 当前用户的bash信息,用户登录时读取 | 局部。定义别名、umask、函数等 |
~/.bash_profile | 当前用户的环境变量信息,用户登录时读取 | 局部。 |
~/.bash_logout | 当前用户退出当前shell时最后读取 | 局部。定义用户退出时执行的程序等 |
~/.bash_history | 当前用户的历史命令 | 局部。history -w保存历史记录 history -c清空历史记录 |
/etc/bashrc | 全局的bash信息 | 全局。所有用户都生效 |
/etc/profile | 全局环境变量信息 | 全局。系统和所有用户都生效 |
**说明:**以上文件修改后,都需要重新source让其生效或者退出重新登录。
说明:本地变量、环境变量、全局变量是根据变量的作用域来区分的。
内置变量 | 含义 |
|---|---|
$? | 上一条命令执行后返回的状态;状态值为0表示执行正常,非0表示执行异常或错误 |
$0 | 当前执行的程序或脚本名 |
$# | 脚本后面接的参数的个数 |
$* | 脚本后面所有参数,参数当成一个整体输出,每一个变量参数之间以空格隔开 |
$@ | 脚本后面所有参数,参数是独立的,也是全部输出 |
1~9 | 脚本后面的位置参数,$1表示第1个位置参数,依次类推 |
{10}~{n} | 扩展位置参数,第10个位置变量必须用{}大括号括起来(2位数字以上扩起来) |
$$ | 当前所在进程的进程号,如echo $$ |
$! | 后台运行的最后一个进程号 (当前终端) |
!$ | 调用最后一条命令历史中的参数 |
#!/bin/bash
#了解shell内置变量中的位置参数含义
echo "\$0 = $0"
echo "\$# = $#"
echo "\$* = $*"
echo "\$@ = $@"
echo "\$1 = $1"
echo "\$2 = $2"
echo "\$3 = $3"
echo "\$11 = ${11}"
echo "\$12 = ${12}"*:表示将变量看成一个整体 @:表示变量是独立的
#!/bin/bash
for i in "$@"
do
echo $i
done
echo "======我是分割线======="
for i in "$*"
do
echo $i
done
# bash 3.sh a b c
a
b
c
======我是分割线=======
a b c算术运算:默认情况下,shell就只能支持简单的整数运算
运算内容:加(+)、减(-)、乘(*)、除(/)、求余数(%)、幂(**)
表达式 | 举例 | 说明 |
|---|---|---|
$(( )) | echo $((1+1)) | |
$[ ] | echo $[10-5] | |
expr | expr 10 / 5 | expr程序中,数值与运算符之间需要空格隔开,乘(*)运算符需要用转义符( \ )转义,expr不能做幂运算 |
let | n=1;let n+=1 等价于 let n=n+1 | let n*=2 等价于let n=n*2,不能使用let n**=2 |
# i=1
# let i++
# echo $i
2
# j=1
# let ++j
# echo $j
2# unset i j
# i=1;j=1
# let x=i++ 先赋值,再运算
# let y=++j 先运算,再赋值
# echo $i
2
# echo $j
2
# echo $x
1
# echo $y
2数组名[索引下标]=值
array[0]=v1
array[1]=v2
array[2]=v3
array[3]=v4数组名=(值1 值2 值3 ...)
array=(var1 var2 var3 var4)
array1=(`cat /etc/passwd`) 将文件中每一行赋值给array1数组
array2=(`ls /root`)
array3=(harry amy jack "Miss Hou")
array4=(1 2 3 4 "hello world" [10]=linux)${数组名[元素下标]}
echo ${array[0]} 获取数组里第一个元素
echo ${array[*]} 获取数组里的所有元素
echo ${#array[*]} 获取数组里所有元素个数
echo ${!array[@]} 获取数组元素的索引下标
echo ${array[@]:1:2} 访问指定的元素;1代表从下标为1的元素开始获取;2代表获取后面几个元素
查看普通数组信息:
# declare -adeclare -A asso_array1
declare -A asso_array1
declare -A asso_array2
declare -A asso_array3数组名[索引or下标]=变量值
# asso_array1[linux]=one
# asso_array1[java]=two
# asso_array1[php]=three# asso_array2=([name1]=harry [name2]=jack [name3]=amy [name4]="Miss Hou")# declare -A
declare -A asso_array1='([php]="three" [java]="two" [linux]="one" )'
declare -A asso_array2='([name3]="amy" [name2]="jack" [name1]="harry" [name4]="Miss Hou" )'# echo ${asso_array1[linux]}
one
# echo ${asso_array1[php]}
three
# echo ${asso_array1[*]}
three two one
# echo ${!asso_array1[*]}
php java linux
# echo ${#asso_array1[*]}
3
# echo ${#asso_array2[*]}
4
# echo ${!asso_array2[*]}
name3 name2 name1 name4# declare -A books
# let books[linux]++
# declare -A|grep books
declare -A books='([linux]="1" )'
# let books[linux]++
# declare -A|grep books
declare -A books='([linux]="2" )'dirname和 basename# A=/root/Desktop/shell/mem.txt
# echo $A
/root/Desktop/shell/mem.txt
# dirname $A 取出目录
/root/Desktop/shell
# basename $A 取出文件
mem.txt一个“%”代表从右往左删除
两个“%%”代表从右往左去掉最多
一个“#”代表从左往右去掉删除
两个“##”代表从左往右去掉最多
举例说明:
# url=www.taobao.com
# echo ${#url} 获取变量的长度
# echo ${url#*.}
# echo ${url##*.}
# echo ${url%.*}
# echo ${url%%.*}替换:/ 和 //
1015 echo ${url/ao/AO} 用AO代替ao(从左往右第一个)
1017 echo ${url//ao/AO} 贪婪替换(替代所有)
替代: - 和 :- +和:+
1019 echo ${abc-123}
1020 abc=hello
1021 echo ${abc-444}
1022 echo $abc
1024 abc=
1025 echo ${abc-222}
${变量名-新的变量值} 或者 ${变量名=新的变量值}
变量没有被赋值:会使用“新的变量值“ 替代
变量有被赋值(包括空值): 不会被替代
1062 echo ${ABC:-123}
1063 ABC=HELLO
1064 echo ${ABC:-123}
1065 ABC=
1066 echo ${ABC:-123}
${变量名:-新的变量值} 或者 ${变量名:=新的变量值}
变量没有被赋值或者赋空值:会使用“新的变量值“ 替代
变量有被赋值: 不会被替代
1116 echo ${abc=123}
1118 echo ${abc:=123}
# unset abc
# echo ${abc:+123}
# abc=hello
# echo ${abc:+123}
123
# abc=
# echo ${abc:+123}
${变量名+新的变量值}
变量没有被赋值或者赋空值:不会使用“新的变量值“ 替代
变量有被赋值: 会被替代
# unset abc
# echo ${abc+123}
# abc=hello
# echo ${abc+123}
123
# abc=
# echo ${abc+123}
123
${变量名:+新的变量值}
变量没有被赋值:不会使用“新的变量值“ 替代
变量有被赋值(包括空值): 会被替代
# unset abc
# echo ${abc?123}
-bash: abc: 123
# abc=hello
# echo ${abc?123}
hello
# abc=
# echo ${abc?123}
${变量名?新的变量值}
变量没有被赋值:提示错误信息
变量被赋值(包括空值):不会使用“新的变量值“ 替代
# unset abc
# echo ${abc:?123}
-bash: abc: 123
# abc=hello
# echo ${abc:?123}
hello
# abc=
# echo ${abc:?123}
-bash: abc: 123
${变量名:?新的变量值}
变量没有被赋值或者赋空值时:提示错误信息
变量被赋值:不会使用“新的变量值“ 替代
说明:?主要是当变量没有赋值提示错误信息的,没有赋值功能