1变量
[root@zab ~]# name=zhang
[root@zab ~]# echo $name
zhang
[root@zab ~]# vim zh.sh
#!/bin/bash
echo "$name"
name=wang
echo "zh.sh:name=$name"
~
[root@zab ~]# bash zh.sh
zh.sh:name=wang
[root@zab ~]# echo $name
zhang
[root@zab ~]# source zh.sh = . zh.sh
zh.sh:name=wang
[root@zab ~]# echo $name
wang
程序执行用bash不需要执行权限 。执行需要执行权限以及程序的路径执行。如./zh.sh 在当前目录下执行 /root/zh.sh 绝对路径执行 source会影响操作环境。
bash和.会开启子进程 。source不会开启子进程。.
显示当前进程编号echo $$
显示进程关系 pstree -p
[root@zab ~]# num1=zhang
[root@zab ~]# num2=$num1 ---- 把num1指向的数据地址zhang 让num2也指向地址zhang 并不是num2指向num1
[root@zab ~]# echo $num1
zhang
[root@zab ~]# echo $num2
zhang
[root@zab ~]# num1=wang ---- num1的指向地址由zhang变为wang
[root@zab ~]# echo $num1
wang
[root@zab ~]# echo $num2 ---- num2的指向地址还是zhang
Zhang
[root@zab ~]# unset num1 num2 ----当脚本执行完后,需unset取消变量定义 如果取消环境变量。会影响调用该变量的进程。
2变量种类
*本地变量:生效范围当前shell进程 在脚本下定义变量为本地变量 不能影响脚本里的脚本
[root@zab ~]# vim f1.sh
#!/bin/bash
n="su1"
echo "f1.sh:n=$n"
./f2.sh 调用f2.sh 要指明路径
~
[root@zab ~]# vim f2.sh
#!/bin/bash
echo "f2.sh:n=$n"
s="su2"
echo "f2.sh:s=$s"
~
[root@zab ~]# chmod +x f2.sh 给f2.sh赋予执行权限
[root@zab ~]# bash f1.sh
f1.sh:n=su1
f2.sh:n= 未显示
f2.sh:s=su2
[root@zab ~]# bash -x f1.sh 进行调试
+ n=su1
+ echo f1.sh:n=su1
f1.sh:n=su1
+ ./f2.sh
f2.sh:n= 变量n为本地变量只对f1.sh生效 未对f2.sh生效
f2.sh:s=su2
注意{ ;空格}
在操作环境终端下输入定义name 变量赋值 name变量影响子进程b.sh 以及b.sh脚本中脚本f1.sh
*变量赋值:(1) 可以是直接字串; name="root" (2) 变量引用:name="$USER" (3) 命令引用:name=`COMMAND` name=$(COMMAND)
(2)变量引用:${name} $name
[root@zab ~]# name=`cat /etc/fstab`
[root@zab ~]# echo $name
# # /etc/fstab # Created by anaconda on Tue Jul 11 21:48:40 2017 # # Accessible filesystems,by reference,are maintained under '/dev/disk'
[root@zab ~]# echo "$name"
#
# /etc/fstab
# Created by anaconda on Tue Jul 11 21:48:40 2017
#
# Accessible filesystems,are maintained under '/dev/disk'
"$name" $name两者区别
如果name=命令
要执行命令 $name
3.环境变量:生效范围为当前shell进程以及子进程 脚本下定义环境变量 会影响脚本里脚本
[root@zab ~]# vim f1.sh
#!/bin/bash
n="su1"
export n n为环境变量
echo "f1.sh:n=$n"
./f2.sh 调用f2.sh
echo "f1.sh:n=$n"
[root@zab ~]# vim f2.sh
#!/bin/bash
echo "f2.sh:n=$n"
s="su2"
echo "f2.sh:s=$s"
n="su3" 环境变量n重新赋值su3
echo "f2.sh:n=$n"
./f3.sh
[root@zab ~]# vim f3.sh
#!/bin/bash
echo "f3.sh:n=$n"
[root@zab ~]# chmod +x f3.sh
[root@zab ~]# bash f1.sh
f1.sh:n=su1 定义n为环境变量 值为su1
f2.sh:n=su1 环境变量f2.sh中n为su1
f2.sh:s=su2 f2.sh并给S赋值 并重新定义环境变量n 赋值为su3
f2.sh:n=su3 n值为su3
f3.sh:n=su3 在f2.sh中调用f3.sh 因为环境变量n重新定义su3
f1.sh:n=su1 返回f1.sh中 n的值为su1
可以发现环境变量会影响当前shell进程以及后续的子进程,但不会影响向上的父进程。
变量声明、赋值: export name=VALUE declare -x name=VALUE
变量引用:$name,${name}
*脚本调试:
检测脚本中的语法错误bash -n *.sh
调试执行 bash -x *.sh
*脚本不能识别别名
声明只读变量: readonly name declare -r name Ü
查看只读变量: readonly –p
在脚本中set -- 清空所有位置变量
unset name 取消变量
*只读变量
[root@zab ~]# name=zhang;file=d.log;(age=20;echo $age;echo $name;name=wang;num=two);echo $name;echo $num;echo $file
20
zhang
zhang
d.log
括号内变量只影响括号内 括号外的变量能影响括号内 括号相当于开启子shell进程
[root@zab ~]# umask
0022
[root@zab ~]# (umask 777;touch f1)
[root@zab ~]# ll f1
----------. 1 root root 0 Jul 27 18:24 f1 umask为777
[root@zab ~]# touch f3
[root@zab ~]# ll f3 umask为022
-rw-r--r--. 1 root root 0 Jul 27 18:25 f3 umask在括号内定义,只影响括号内;括号外不影响,umask为原值
$1,$2,...:对应第1、第2等参数,shift [n]换位置
$0: 命令本身
$*: 传递给脚本的所有参数,全部参数合为一个字符串
$@: 传递给脚本的所有参数,每个参数为独立字符串
$#: 传递给脚本的参数的个数
$@ $* 只在被双引号包起来的时候才会有差异
set -- 清空所有位置变量
[root@zab ~]# vim f1.sh {a..m}
#!/bin/bash
echo "1st arg is $1"
echo "2st arg is $2"
echo "10st arg is ${10}"
echo "All args are $*"
echo "All args are $@"
echo "$0"
echo "$#"
~
[root@zab ~]# bash f1.sh {a..m}
1st arg is a
2st arg is b
10st arg is j
All args are a b c d e f g h i j k l m
All args are a b c d e f g h i j k l m
f1.sh
13
[root@zab ~]# bash f1.sh {a..m}
#!/bin/bash
echo "1st arg is $1"
echo "All args are $@"
shift 2
echo "shift 2"
echo "1st arg is $1"
echo "All args are $@"
~
[root@zab ~]# bash f1.sh {a..m}
1st arg is a
All args are a b c d e f g h i j k l m
shift 2 shift [n]换位置
1st arg is c 第一个参数变为c
All args are c d e f g h i j k l m
[root@zab ~]# vim f2.sh
#!/bin/bash
echo "$@"
./f3.sh "$@" 创建f3.sh 需指明路径
./f4.sh "$*" 同上
[root@zab ~]# vim f3.sh
#!/bin/bash
echo "$1"
[root@zab ~]# vim f4.sh
#!/bin/bash
echo "$1"
[root@zab ~]# chmod +x f3.sh
[root@zab ~]# chmod +x f4.sh
[root@zab ~]# bash f2.sh {a..m}
a b c d e f g h i j k l m
a
a b c d e f g h i j k l m
[root@zab ~]# bash -x f2.sh {a..m}
+ echo a b c d e f g h i j k l m
a b c d e f g h i j k l m
+ ./f3.sh a b c d e f g h i j k l m $@
a $1
+ ./f4.sh 'a b c d e f g h i j k l m' $*
a b c d e f g h i j k l m $1
$*与$@区别
[root@zab ~]# vim scipt.sh
#!/bin/bash
cat>$1<<eof
#!/bin/bash
######################
#auther:71
#creat-time:`date +%F`
#filename:`basename $1`
######################
eof
vim + $1
chmod +x $1
~
~
[root@zab ~]# bash scipt.sh zab.sh
#!/bin/bash
######################
#auther:71
#creat-time:2017-07-27
#filename:zab.sh
######################
~
~
退出状态
进程使用退出状态来报告成功或失败
• 0 代表成功,1-255代表失败
• $? 变量保存最近的命令退出状态
exit [n]:自定义退出状态码 用于编写脚本执行命令,给命令不同的状态码,看命令是否成功
注意:脚本中一旦遇到exit命令,脚本会立即终止;终止退出 状态取决于exit命令后面的数字
注意:如果未给脚本指定退出状态码,整个脚本的退出状态码 取决于脚本中执行的最后一条命令的状态码
[root@centos7 ~]#cat b.sh
#!/bin/bash
cmd
(exit 100) ()号表示开启的子进程 exit退出当前子进程
hostname
[root@centos7 ~]#bash b.sh
b.sh: line 2: cmd: command not found
centos7.64 继续执行
#!/bin/bash
cmd
exit 100 退出当前进程
hostname 不执行
[root@centos7 ~]#bash b.sh
b.sh: line 2: cmd: command not found
[root@centos7 ~]#echo $?
100
算术运算
vbash中的算术运算:help let +,-,*,/,%取模(取余),**(乘方) 数字 $[number]
实现算术运算:
(1) let var=算术表达式 let c=a+b echo $c
(2) var=$[算术表达式]
(3) var=$((算术表达式)) $((a-b))
(4) var=$(expr arg1 arg2 arg3 ...) expr 1 + 2 命令 1 + 2为参数 需要空格 expr 0 + $num 可用于判断num是不是非0的整数
5) declare –i var = 数值
(6) echo ‘算术表达式’ | bc v
乘法符号有些场景中需要转义,如* 为(\*)
bash有内建的随机数生成器:$RANDOM(0-32767) echo $[$RANDOM%50] :0-49之间随机
echo $SHLVL 当前进程嵌套深度pstree -p 查看
[root@centos7 ~]#i=10
[root@centos7 ~]#let j=i++
[root@centos7 ~]#echo $j
10
[root@centos7 ~]#echo $i
11
[root@centos7 ~]#unset i
[root@centos7 ~]#i=10
[root@centos7 ~]#let j=++i
[root@centos7 ~]#echo $j
11
[root@centos7 ~]#echo $i
11
注意如下
[root@centos7 ~]#unset k
[root@centos7 ~]#let k=0
[root@centos7 ~]#let k++ k为0
[root@centos7 ~]#echo $?
1
[root@centos7 ~]#unset k
[root@centos7 ~]#let k=0
[root@centos7 ~]#let ++k k为1
[root@centos7 ~]#echo $?
0
exit状态 最后一个参数为0,将返回1
[root@centos7 ~]#let k+=6
[root@centos7 ~]#echo $k
7
[root@centos7 ~]#let k+=6 = k=k+6
[root@centos7 ~]#echo $k
13
条件测试 用于两个参数进行判断
专用的测试表达式需要由测试命令辅助完成测试过程
• [ EXPRESSION ]
•[[ EXPRESSION ]] 用于正则表达式
注意:EXPRESSION前后必须有空白字符
[]内是字符串、数值、文件测试 单条命令行判断不需要[]中括号
表达式查看test man帮助
注意如下
[root@centos7 ~]#var=' '
[root@centos7 ~]#[ $var ] && echo true
[root@centos7 ~]#echo $?
1 字符为空 判断为假
[root@centos7 ~]#[ 0 ] && echo true
true
1.字符串测试
= 等于则为真
变量比较用到的操作数需加引号
[ "$a" = "wang" ] 或者[ x$a == x"wang" ]前面加字符防止$a为空而报错
格式的例子:
[ "abc" = "abc" ] && echo "Strings are equal"
!= 是否不等于,不相等为真
=~ 左侧字符串是否能够被右侧的PATTERN所匹配
注意: 此表达式一般用于[[ ]]中;扩展的正则表达式
[[ $a =~ \<[Yy]|([Yy][Ee][sS])$ ]] && echo "hello" ||echo "fk"
-z "STRING“ 字符串是否为空,空为真,不空为假 [ ! -z string ] 等同于 [ -n srting ]
-n "STRING“ 字符串是否不空,不空为真,空为假
实例演示:
num1="ru1noob"
num2="runoob"
if [ $num1 = $num2 ]
then
echo '两个字符串相等!'
else
echo '两个字符串不相等!'
fi
输出结果:
两个字符串不相等!
2.数值测试
-eq 等于则为真
-le小于等于则为真
-lt小于则为真
-ge大于等于则为真
-gt大于则为真
实例演示:
num1=100
num2=100
if [ ${num1} -eq ${num2} ]
then
echo '两个数相等!'
else
echo '两个数不相等!'
fi
输出结果:
两个数相等!
代码中的 [] 执行基本的算数运算,如:
#!/bin/bash
a=5
b=6
result=$[a+b] # 注意等号两边不能有空格
echo "result 为: $result"
结果为:
result 为: 11
Bash的文件权限测试
3.文件测试
文件存在测试:
文件类型测试:
文件是否打开:
-t fd: fd表示文件描述符是否已经打开且与某终端相关
文件权限测试: 实际权限
-r FILE:是否存在且可读
-w FILE: 是否存在且可写
-x FILE: 是否存在且可执行
文件特殊权限测试:
-u FILE:是否存在且拥有suid权限
-g FILE:是否存在且拥有sgid权限
-k FILE:是否存在且拥有sticky权限
双目测试:
FILE1 -ef FILE2: FILE1与FILE2是否指向同一个设 备上的相同inode file1是不是file2硬链接
FILE1 -nt FILE2: FILE1是否新于FILE2(mtime)
FILE1 -ot FILE2: FILE1是否旧于FILE
另外,Shell还提供了与( -a )、或( -o )、非( ! )三个逻辑操作符用于将测试条件连接起来,其优先级为:"!"最高,"-a"次之,"-o"最低。
例如:
cd /bin
if [ -e ./notFile -o -e ./bash ]
then
echo '有一个文件存在!'
else
echo '两个文件都不存在'
fi
输出结果:
有一个文件存在!
逻辑运算
如果true 1,false 0
与: 1 与 1 = 1 或: 1 或 1 = 1
1 与 0 = 0 1 或 0 = 1
0 与 1 = 0 0 或 1 = 1
0 与 0 = 0 0 或 0 = 0
短路运算
非:!
! 1 = 0 ! 0 = 1
短路与
第一个为0,结果必定为0
第一个为1,第二个必须要参与运算
短路或
第一个为1,结果必定为1 第一个为0,第二个必须要参与运算
条件性的执行操作符
&& 代表条件性的AND THEN
|| 代表条件性的OR ELSE
Bash的组合测试条件
第一种方式: COMMAND1 && COMMAND2 并且
COMMAND1 || COMMAND2 或者
! COMMAND 非
如:[ -r FILE ] && [ -w FILE ]
第二种方式: EXPRESSION1 -a EXPRESSION2 并且
EXPRESSION1 -o EXPRESSION2 或者
! EXPRESSION 必须使用测试命令进行
EXPRESSION1 -o EXPRESSION2 = COMMAND1 || COMMAND2
EXPRESSION1 -a EXPRESSION2 = COMMAND1 && COMMAND2
[ -r file -a -w file ] 等同于 [ -r FILE ] && [ -w FILE ]
! EXPRESSION
EXPRESSION is false
[ ! EXPRESSION1 -a EXPRESSION2] = -not expression1 -o -not expression2
[ ! EXPRESSION1 -o EXPRESSION2] = -not expression1 -a -not expression2
EXPRESSION1 -a EXPRESSION2
both EXPRESSION1 and EXPRESSION2 are true
EXPRESSION1 -o EXPRESSION2
either EXPRESSION1 or EXPRESSION2 is true
示例:
[root@centos7 ~]#num=60
[root@centos7 ~]#[ $num -gt 30 -a $num -lt 100 ] && echo "right"||echo "error"
right
等同于
[root@centos6 ~]#[ $num -gt 30 ] && [ $num -lt 100 ] && echo "right" ||echo "error"
right
cmd1 &&cmd2 ||cmd3
Cmd1 为假 cmd2 不执行 执行cmd3
cmd1为真 cmd2 执行 不执行cmd3
[root@centos7 ~]#id wang; id wang &> /dev/null && echo "id wang exist" || useradd wang
#!/bin/bash
name=wang; id $name &> /dev/null && { echo "$name exist";exit 100; } ||(useradd wang;echo bing|passwd --stdin $name; )
判断num是不是整数
[root@centos7 ~]#expr 0 + $num && echo "$num is number" || echo "$num is not number" 只能判断非0整数
[root@centos7 ~]#expr 0 + $num && echo "$num is number" || echo "$num is not number"
[root@centos7 ~]#[[ $num =~ ^-?[0-9]+$ ]] && echo "$num is number"|| echo "$num is not number"
使用read命令来接受输入参数变量
v 使用read来把输入值分配给一个或多个shell变量
-s 静默输入,一般用于密码
-n N 指定输入的字符长度N
-d ‘字符’ 输入结束符
-t N TIMEOUT为N秒
read 从标准输入中读取值,给每个单词分配一个变量 所有剩余单词都被分配给最后一个变量 read -p “Enter a filename: “ FILE
#!/bin/bash
read -s -p "please input your passwd: " pass
echo -e "\nyour passwd is $pass"
@H_902_2502@多个变量 @H_902_2502@防止扩展 v
反斜线(\)会使随后的字符按原意解释
$ echo Your cost: \$5.00
Your cost: $5.00 v
加引号来防止扩展
• 单引号(’)防止所有扩展
• 双引号(”)也防止所有扩展,但是以下情况例外:
î $(美元符号) - 变量扩展
î(反引号) - 命令替换
î \(反斜线) - 禁止单个字符扩展
î !(叹号) - 历史命令替换
全局配置:
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc v
个人配置:
~/.bash_profile
~/.bashrc
shell登录两种方式
v 交互式登录:
(1)直接通过终端输入账号密码登录 (2)使用“su - UserName” 切换的用户
执行顺序:/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc v 调用
# .bashrc
# User specific aliases and functions
PS1="\[\e[31m\][\u@\h \W]\\$\[\e[0m\]"
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i' #别名定义
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
~
~
~ .bashrc ——>/etc/bashrc
~
~
非交互式登录: (1)su UserName (2)图形界面下打开的终端 (3)执行脚本 (4)任何其它的bash实例
执行顺序: ~/.bashrc --> /etc/bashrc --> /etc/profile.d/*.sh
按功能划分,存在两类: profile类和bashrc类
vprofile类:为交互式登录的shell提供配置
全局:/etc/profile,/etc/profile.d/*.sh
个人:~/.bash_profile
功用: (1) 用于定义环境变量 (2) 运行命令或脚本
bashrc类:为非交互式和交互式登录的shell提供配置
全局:/etc/bashrc
个人:~/.bashrc
功用: (1) 定义命令别名和函数 (2) 定义本地变量
编辑配置文件生效
两种方法: 1重新启动shell进程 2 . 或source 例: . ~/.bashrc
Bash 退出任务
v 在退出登录shell时运行
v1、让所有用户的PATH环境变量的值多出一个路径,例如: /usr/local/apache/bin
v2、用户root登录时,将命令指示符变成红色,并自动启用如 下别名:rm=‘rm –i’ cdnet=‘cd /etc/sysconfig/network-scripts/’ editnet=‘vim /etc/sysconfig/network-scripts/ifcfg-eth0’ editnet=‘vim /etc/sysconfig/network-scripts/ifcfgeno16777736 或 ifcfg-ens33 ’ (如果系统是CentOS7)
在 vim .bashrc配置文件中定义
v3、任意用户登录系统时,显示红色字体的警示提醒信息 “Hi,dangerous!”
v4、编写生成脚本基本格式的脚本,包括作者,联系方式,版 本,时间,描述等
[root@zab ~]# vim scipt.sh
#!/bin/bash
cat>$1<<eof
#!/bin/bash
######################
#auther:71
#creat-time:`date +%F`
#filename:`basename $1`
######################
Eof
chmod +x $1
vim + $1