BASH 基本语法
本节内容
一 什么是shell script |
将OS命令堆积到可执行的文件里,由上至下的顺序执行文本里的OS命令,就是脚本
再加上些智能(条件/流控)控制,就变成了智能化脚本
read -p 'please input hostname: ' name hostnamectl set-hostname $name
二 变量 |
part1为何要有变量
程序的运行就是一些状态的变量 --> 用变量值的变化去表示
part2变量命名规则
以字母或下划线开头,剩下的部分可以是:字母、数字、下划线
最好遵循下述规范:
1. 以字母开头
2. 使用下划线做单词连接
3. 同类型的用数字区分
4. 对于文件最好加上扩展名 例如 sql_bak.tar.gz, log_bak.tar.bz2
part3 系统变量
set:显示所有变量
env:环境变量
part4 变量赋值
VARNAME=VALUE
echo $VARNAME
删除变量 unset VARNAME
part5 常用系统变量
PATH --> 第三方命令搜索路径
PWD --> 当前路径
LANG --> 字符编码 en_US.UTF-8
HOME --> 家目录
HISTSIZE --> 历史命令条数
PS1 --> 命令提示符 [root@myname ~]
IFS --> 域分隔符 是空格,换行,TAB键的合集
part6 全局变量与局部变量
当前用户进入bash后自己定义的变量,与系统变量(固化到文件里,启动时加载)不同
export var_name=var_value # export 声明全局变量
var_name=var_vale # 声明局部变量
[root@localhost ~]# gender='male' # 在爹这个位置定义一个局部变量gender
[root@localhost ~]# export money=1000 # 在爹这个位置定义一个全局变量money
[root@localhost ~]# bash # 切换到子bash
[root@localhost ~]# echo $gender # 在儿子这里看它爹的局部变量gender,结果为空->看不到
[root@localhost ~]# echo $money # 在儿子这里看它爹的全局变量money,可以看到
1000
[root@localhost ~]# export hobby='readding' # 在儿子这里定义一个全局变量hobby
[root@localhost ~]# exit # 退出,进入爹的bash环境
exit
[root@localhost ~]# echo $hobby # 爹是看不到儿子的export的,儿子的儿子可以看到
[root@localhost ~]#
part7 定义变量的边界
[root@myname ~]# moeny=10000
[root@myname ~]# echo $moneyyuan
[root@myname ~]# echo ${money}yuan
10000yuan
[root@myname ~]#
part8 数据类型
bash中的变量无须声明,拿来就用,默认的变量都会时是字符类型,还可以有数字类型。普通脚本,这两种类型够用
实例:获取men_used
[root@myname ~]# free
total used free shared buff/cache available
Mem: 999936 529440 111152 9552 359344 239252
Swap: 2097148 124208 1972940
[root@myname ~]# mem_used=`free | awk 'NR==2{print $3}'`
[root@myname ~]# echo $mem_used
529844
三 运算符 |
part1 算数运算符
+
-
*
/
%
[root@www ~]# echo $[3+1]
4
part2 关系操作
> < <= >= == != && || 要与(())连用才能达到效果
test命令相关,[]可以达到相同效果
-gt -lt -le -ge -eq -ne -a -o
[root@www ~]# x=1;y=2;a=10;b=5
[root@www ~]# [ $x -lt $y -a $a -gt $b ]
[root@www ~]# echo $?
0
part3 赋值运算符
(( )) 里面不用写$,就可以取变量值
((x+=1))
((x-=1))
((x*=2))
((x/=2))
((x%=2))
[root@www ~]# x=1
[root@www ~]# ((x=x+1))
[root@www ~]# ((x=x+1))
[root@www ~]# echo $x
3
part4 shell里面的所有计算器
a=$[1+2]
a=$((x+=1))
expr 1 + 2
浮点运算,如内存使用率,bc yum install -y bc
[root@www ~]# echo 'scale=2;3/10'|bc -l # scale=2,保留2位小数
.30
[root@www ~]#
实例:求内存的百分比
[root@www ~]# free total used free shared buff/cache available Mem: 999936 456368 136924 9272 406644 329564 Swap: 2097148 150356 1946792 [root@www ~]# free | awk 'NR==2{print $2}' 999936 [root@www ~]# mem_total=`free | awk 'NR==2{print $2}'` [root@www ~]# mem_used=`free | awk 'NR==2{print $3}'` [root@www ~]# echo $mem_total 999936 [root@www ~]# echo $mem_used 456752 [root@www ~]# echo "scale=2;$mem_used/$mem_total" | bc -l .45 [root@www ~]# echo "scale=2;$mem_used/$mem_total" | bc -l | cut -d. -f2 45 [root@www ~]# mem_per=`echo "scale=2;$mem_used/$mem_total" | bc -l | cut -d. -f2` [root@www ~]# echo ${mem_per}% 45% [root@www ~]#
part5 测试操作
命令执行后会返回到一个系统变量中$? 如果$?值为0 表示命令执行成功,否则为失败
part5-1 测试文件状态
test -d /etc 等价于 [ -d /etc ] 然后用echo $? 查看结果状态 # 目录是否存在
-d 目录 [ -d /etc ]
-s 文件长度 > 0、非空
-e 文件 [ -d /etc/passwd ]
-f 普通文件[ -f /etc/passwd ]
-r 当前用户是否读权限 [ -r /etc/passwd ]
-w 当前用户是否写权限 [ -w /etc/passwd ]
-x 当前用户是否执行权限 [ -x /etc/passwd ]
part5-2 测试字符串
= 两个字符串相等
!= 两个字符串不相等
-z 空串
-n 非空串
part5-3 测试数值
-eq 等于
-ne 不等于
-gt 大于
-lt 小于
-ge 大于等于
-le 小于等于
-a 并列
-o 或者
四 流程控制 |
part1 分支流程
#!/bin/bash var='/etc/passwd' if [ -f $var ] then echo "$var is regular file" elif [ -b $var ] then echo "$var is block file" elif [ -d $var ] then echo "$var is directory" elif [ -h $var ] then echo "$var is link file" else echo "$var is unkown" fi
说明:
-
if...else 只有一个分支会执行
-
if 后面有then else后面没有then
-
最后有个fi
以空格为单位 读取文本输入参数 $1 $2 $3 ... ${10}
[root@localhost temp]# cat b.sh #/bin/bash echo $1 echo $2 echo $3 echo ${10} echo ${11} [root@localhost temp]# ./b.sh 1 2 3 4 5 6 7 8 9 10 11 1 2 3 10 11
说明:
$$ 进程pid
$* 所有参数
$@ 所有参数
$# 参数个数
$? 上一条命令执行结果
简易启动nginx服务
#/bin/bash ps aux | grep nginx | grep -v 'grep' if [ $? -ne 0 ] then systemctl start nginx if
part2 循环结构
循环重复地做某件事
part2-1 while循环
while : do clear free sleep 1 done
1. while死循环
#!/bin/bash var1=AAA var2=BBB var3=CCC while : do clear echo -e "A:${var1}\nB:${var2}\nC:${var3}" temp=$var1 var1=$var2 var2=$var3 var3=$temp sleep 1 done
2. 打印1 - 10
#!/bin/bash count=1
while [ $count -le 10 ] do echo $count ((count++)) done
3. 登录 运行命令
#!/bin/bash while : do read -p "please input your username: " username read -p "please input your password: " password
# 验证输入的有效性 if [ -z $username ] || [ -z $password ] then echo "usrename or password is none." continue fi
if [ $username = 'alex' -a $password = '123456' ]
# 用户名密码验证正确 then echo "Login successfully.Welcome $username"
# 正确进行业务处理 while : do read -p "please input your cmd: " cmd if [ "$cmd" = 'quit' ] then break fi $cmd done else
# 用户名密码验证错误 echo "Wrong username or password" fi done
part2-2 for循环
1. echo 1到100
#!/bin/bash for i in {1..100} # 1-100 do echo $i done
#!/bin/bash for i in `ls /boot` # ls /boot 命令结果 do echo $i done
#!/bin/bash for i in {2..253} do ping -c1 192.168.100.$i &> /dev/null if [ $? -ne 0 ] then echo "192.168.100.$i is available" fi done
part2-3 case语句
#!/bin/bash read -p ">>: " name case $name in root) echo "welcome root" ;; admin) echo "welcome admin" ;; default) echo "welcome default" ;; *) echo "no user $name" esac
part2-4 综合到一起,制作一个简单的菜单功能
#!/bin/bash echo "script name: `basename $0`" echo "version 1.0" echo "date 2017-10-09" echo "Author: Tom" while read -p "(h for help): " var do case $var in p|P|cpu|CPU) echo -e "\n\n" grep 'model name\|cpu MHz\|processor' /proc/cpuinfo |sort |uniq echo -e "\n\n" ;; m|m|mem|MEM) echo -e "\n\n" free echo -e "\n\n" ;; d|D|disk|DISK) echo -e "\n\n" df -Th echo -e "\n\n" ;; h|H|help|HELP) echo -e "\n\tcommand\taction\n\n" for i in cpu mem disk do echo -e "\t$i\t${i}_info" done echo -e "\thelp\tthis help page.." echo -e "\tquit\texit !!.." echo -e "\n\n" ;; q|Q|quit|exit) exit ;; *) echo -e "\n$var Enter Error...\n" esac done
五 函数 |
#!/bin/bash function start(){ echo "start..." } function install(){ echo "install..." } if [ "$1" = 'start' ] then start elif [ "$1" = 'install' ] then install else echo "cmd not found" fi
说明:
1. 交互命令行的函数 function abc(){echo 'aaa';echo 'bbb';}; abc ,另外脚本文件中也可以定义函数
2. set 查看定义的函数;unset function_name 取消函数定义
3. 向函数传递参数就像脚本使用变量位置 $1, $2, $3, ... $9
4. 函数返回状态 echo $?,成功一般是返回0,定义自定义return 值
六 计划任务crontab |
什么是计划任务
后台运行,到了预定时间就会自动执行的任务,前提是:事先手动将计划任务设定好,这就用到了crond服务
计划任务分为两类:系统级和用户级
无论是系统级还是用户级的cron计划都是文本文件。
系统的计划文件存放在 /etc/crontab路径下,用户的计划文件存放在/var/spool/cron/用户名
root用户可以直接对文件进行修改来编写计划任务也可以使用 crontab -e命令,而普通用户只能使用后者
[root@localhost ~]# crontab -e -u root # 编辑 root 用户的计划任务
[root@localhost ~]# crontab -l -u root # 查看 root 用户的计划任务
crontab任务配置基本格式:
* * * * * command
分钟(0-59) 小时(0-23) 天(1-31) 月(1-12) 星期(0-7,0和7表示星期天) 命令
参 数:
-e 编辑该用户的计时器设置
-l 列出该用户的计时器设置
-r 删除该用户的计时器设置
-u <用户名称> 指定要设定计时器的用户名称
注意:
1. 查看计划任务的执行:tail -f /var/log/cron
2. 写计划任务时,命令必须加上绝对路径,否则会出现这种情况:从日志中看,确实触发了计划任务的执行,但是命令却没有执行成功,
比如* * * * * reboot就会出现这种情况,需要将reboot写成/usr/sbin/reboot
crontab例子:
30 21 * * * /usr/local/etc/rc.d/apache restart # 每晚的21:30 重启apache 45 4 1,10,22 * * /usr/local/etc/rc.d/apache restart # 每月1、10、22日的4 : 45重启apache 10 1 * * 6,0 /usr/local/etc/rc.d/apache restart # 每周六、周日的1 : 10重启apache 0,30 18-23 * * * /usr/local/etc/rc.d/apache restart # 每天18 : 00至23 : 00之间每隔30分钟重启apache 0 23 * * 6 /usr/local/etc/rc.d/apache restart # 每星期六的11 : 00 pm重启apache * 23-7/1 * * * /usr/local/etc/rc.d/apache restart # 晚上11点到早上7点之间,每隔一个小时的每分钟重启 apache 0 */1 * * * /usr/local/etc/rc.d/apache restart # 每一小时重启apache 0 11 4 * mon-wed /usr/local/etc/rc.d/apache restart # 每月的4号与每周一到周三的11点重启apache 0 4 1 jan * /usr/local/etc/rc.d/apache restart # 一月一号的4点重启apache */30 * * * * /usr/sbin/ntpdate 210.72.145.44 # 每半小时同步一下时间 0 */2 * * * www /usr/bin/somecommand >> /dev/null 2>&1 # 以用户www的身份每两小时就运行某个程序: 0 1 * * * /home/testuser/test.sh # 每天1点调用/home/testuser/test.sh */10 * * * * /home/testuser/test.sh # 每10钟调用一次/home/testuser/test.sh 30 21 * * * /usr/local/etc/rc.d/lighttpd restart # 每天的21:30重启lighttpd 45 4 1,10,22 * * /usr/local/etc/rc.d/lighttpd restart # 每月1、10、22日的4 : 45重启lighttpd 10 1 * * 6,0 /usr/local/etc/rc.d/lighttpd restart # 每周六、周日的1 : 10重启lighttpd 0,30 18-23 * * * /usr/local/etc/rc.d/lighttpd restart # 上面的例子表示在每天18 : 00至23 : 00之间每隔30分钟重启apache。 0 23 * * 6 /usr/local/etc/rc.d/lighttpd restart # 上面的例子表示每星期六的11 : 00 pm重启lighttpd * */2 * * * /usr/local/etc/rc.d/lighttpd restart # 每两小时的每分钟重启lighttpd 0 23-7/1 * * * /usr/local/etc/rc.d/lighttpd restart # 晚上11点到早上7点之间,每隔一小时重启lighttpd 0 11 4 * mon-wed /usr/local/etc/rc.d/lighttpd restart # 每月的4号与每周一到周三的11点重启lighttpd 0 4 1 jan * /usr/local/etc/rc.d/lighttpd restart # 一月一号的4点重启lighttpd */30 * * * * /usr/sbin/ntpdate 210.72.145.44 # 每半小时同步一下时间
更多信息
http://www.cnblogs.com/linhaifeng/p/6602149.html
posted on 2017-10-09 16:51 Jonathan1314 阅读(1333) 评论(0) 编辑 收藏 举报