BASH 基本语法

时间:2023-03-08 22:56:02
BASH 基本语法

本节内容

1.  什么是shell script

2.  变量

3.  运算符

4.  流程控制

5.  函数

6.  计划任务 crontab

一  什么是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:
Swap:
[root@www ~]# free | awk 'NR==2{print $2}' [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 [root@www ~]# echo $mem_used [root@www ~]# echo "scale=2;$mem_used/$mem_total" | bc -l
.
[root@www ~]# echo "scale=2;$mem_used/$mem_total" | bc -l | cut -d. -f2 [root@www ~]# mem_per=`echo "scale=2;$mem_used/$mem_total" | bc -l | cut -d. -f2`
[root@www ~]# echo ${mem_per}%
%
[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 = '' ]
# 用户名密码验证正确
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