Linux Shell编程最小常识
整体说明
# 这一行相当于导入依赖包,将`Linux`中的`/bin/bash`文件引入脚本的执行环境,它必须放在第一行。且只有这种固定格式的`#!`才不是表示注释的意思
#!/bin/bash
echo hello linux
执行shell
脚本的方式有六种。
bash hello.sh
:bash
是指定Linux的脚本执行环境,类似于java user.jar
命令中java
所起的作用,因为Linux除了bash
,还有其他的脚本执行环境,例如zsh
,它们的区别也类似于JDK
和OpenJDK
的区别。sh hello.sh
:在当前大部分的Linux发行版中,sh
是一个指向/bin/bash
的链接/bin/sh -> bash
,也就是一个快捷方式。当然有的Linux发行版中的sh
和bash
还是区分开的。./hello.sh
:这种方式省略了bash
或sh
,表示执行当前目录下的hello.sh
脚本。当以这种方式执行脚本时,这个脚本必须有可执行权限,也就是x
权限,可以通过chmod +x
指定。前面两种之所以不需要执行权限,是因为它们把hello.sh
作为字符串参数,传给了bash
或sh
命令。hello.sh
:这种方式需要修改环境变量PATH
,将它所在的目录加入其中才能被Linux识别。hello
:这种方式是前一种方式的简写,Linux可以自动识别并执行以hello
为文件名,以.sh
为后缀的脚本文件。bash -x: hello.sh
:它表示单步执行脚本命令。如果脚本文件包含多条命令,那么这种方式会将每一条命令和它执行的结果都打印出来,方便对照和调试。
使用变量
shell
是弱类型的脚本语言,变量不需要提前声明,初始化也不需要指定类型。
变量赋值有一个奇怪
的规定:在变量
、=
和数值
之间不能有空格。
# 错误的赋值语句
> i = 1
> i= 1
> i =1
> 2i = 1
> i$ = 1
# 正确的赋值语句
> i=1
> i2=1
> i_=1
> echo $i
1
> echo $i2
1
> echo $i_
# 或者写出完整形式
1
> echo ${i}
1
> echo ${i2}
1
> echo ${i_}
1
# 区别在于
> echo $i0
> echo ${i}0
10
if条件判断
第一种格式。
# 语法格式
if 分支条件
then
选择分支
fi
> vi if.sh
if [ $# -lt 1 ]
then
echo "params error"
exit 100
fi
flag=$1
if [ $flag = "linux" ]
then
echo "hello linux"
fi
> sh ./if.sh linux
hello linux
> sh ./if.sh
params error
> echo $?
100
> sh ./if.sh 1 1 1
> echo $?
0
第二种格式。
# 语法格式
if 分支条件
then
选择分支1
else
选择分支2
fi
> vi if.sh
flag=$1
if [ $flag = "linux" ]
then
echo "hello linux"
else
echo "you welcome"
fi
> sh ./if.sh linux
hello linux
> sh ./if.sh lixungyun
you welcome
第三种格式。
# 语法格式
if 分支条件1
then
选择分支1
elif 分支条件2
then
选择分支2
......
else
选择分支n
fi
> vi if.sh
flag=$1
if [ $flag = "linux" ]
then
echo "hello linux"
elif [ $flag = "lixungyun" ]
then
echo "you welcome"
else
echo hello $flag
fi
> sh ./if.sh linux
hello linux
> sh ./if.sh lixungyun
you welcome
> sh ./if.sh wanglin
hello wanglin
for循环
第一种格式,适用于数值累加有规律且数据较多的列表。
# 语法格式
for((i=0;i<10;i++))
do
循环体
done
> vi for.sh
for((i=0;i<10;i++))
do
echo $i
done
第二种格式,适用于没有规律或数据比较少的列表。
# 语法格式
for i in 1 2 3
do
循环体
done
> vi for.sh
for i in 1 2 3 4 5
do
echo $i
done
while循环
主要用于循环次数未知,或不便于使用for
时。
第一种格式。
# 语法格式
while test EXP
do
循环体
done
> vi while.sh
while test 2 -gt 1
do
echo "2 > 1"
sleep 1
done
第二种格式。
# 语法格式
while [ EXP ]
do
循环体
done
> vi while.sh
while [ "hello" = "world" ]
do
echo "yes"
done
定时器crontab
crontab
可以执行周期性的定时任务,例如每天凌晨三点做出销售统计报表。
# 语法格式
* * * * * user-name command
↑ ↑ ↑ ↑ ↑ ↑ ↑
| | | | | | |
| | | | | | └-------
| | | | | |
| | | | | └---------------
| | | | |
| | | | └--------------------- 每周第几天(0 ~ 6,周日=0或7)
| | | |
| | | └----------------------- 表示月份(1 ~ 12)
| | |
| | └------------------------- 每月第几天(1 ~ 31)
| |
| └--------------------------- 表示小时(0 ~ 23)
|
└----------------------------- 表示分钟(0 ~ 59)
# * 表示匹配任意的时间点(分钟、小时、天、月、周)
# 查看crontab服务状态
> systemctl status crond
● crond.service - Command Scheduler
Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled; preset: enabled)
Active: active (running) since Thu 2022-10-20 20:42:35 CST; 1 week 2 days ago
Main PID: 1304 (crond)
Tasks: 1 (limit: 100105)
Memory: 1.3M
CPU: 5.372s
CGroup: /system.slice/crond.service
└─1304 /usr/sbin/crond -n
# 添加定时任务
> vi printdatetime.sh
#!/bin/bash
current_time=`date "+%Y-%m-%d %H:%M:%S"`
echo ${current_time}
# 每分钟执行一次
> vi /etc/crontab
* * * * * root sh /home/work/printdatetime.sh >> /home/work/logs/printdatetime.log
# 查看crontab执行日志
> tail -f /var/log/cron
crontab
的定时任务不是从脚本执行那一刻开始计算的,而是会从整点开始往后推。
每1分钟执行一次,会在每分钟的第一秒执行
xx:xx:01
。每5分钟执行一次,会在
xx:05:01
、xx:10:01
、xx:15:01
、xx:20:01
、......这几个时间点执行。每7分钟执行一次,会在
xx:00:01
、xx:07:01
、xx:14:01
、......xx:56:01
这几个时间点执行。当1小时过后,又会从下一个小时的xx:00:01
、xx:07:01
开始执行,而不是顺延7分钟执行,也就是xx:03:01
。每1天执行一次,会在每天的
00:00:01
开始执行。
# 每7分钟执行一次
> vi /etc/crontab
*/7 * * * * root sh /home/work/printdatetime.sh >> /home/work/logs/printdatetime.log
# 查看crontab执行日志
> tail -f /home/work/logs/printdatetime.log
感谢支持
更多内容,请移步《超级个体》。