一、crontab配置(定时)
1、功能
在固定的间隔时间执行指定的系统指令或 shell script脚本。时间间隔的单位可以是分钟、小时、日、月、周及以上的任意组合。这个命令非常适合周期性的日志分析或数据备份等工作。
2、安装
[root@node03 ~]# yum install crontabs
已加载插件:fastestmirror, security
设置安装进程
Loading mirror speeds from cached hostfile
* base: mirrors.tuna.tsinghua.edu.cn
* extras: mirrors.163.com
* updates: mirrors.tuna.tsinghua.edu.cn
base | 3.7 kB 00:00
extras | 3.4 kB 00:00
updates | 3.4 kB 00:00
包 crontabs-1.10-33.el6.noarch 已安装并且是最新版本
无须任何处理
service crond start ## 启动服务
service crond stop ## 关闭服务
service crond restart ## 重启服务
service crond reload ## 重新载入配置
service crond status ## 查看crontab服务状态
service crond start ## 手动启动crontab服务
chkconfig --list ## 查看crontab服务是否已设置为开机启动
chkconfig --level 35 crond on ## 加入开机自动启动
3、修改任务计划命令
crontab [-u user] file
crontab [-u user] [ -e | -l | -r ]
(1)说明:
-u user ##用来设定某个用户的crontab服务,例如,“-u ixdba”表示设定ixdba用户的crontab服务,此参数一般有root用户来运行。
file ##file是命令文件的名字,表示将file做为crontab的任务列表文件并载入crontab。
-e ##编辑某个用户的crontab文件内容。如果不指定用户,则表示编辑当前用户的crontab文件。
-l ##显示某个用户的crontab文件内容,如果不指定用户,则表示显示当前用户的crontab文件内容。
-r ##删除定时任务配置,从/var/spool/cron目录中删除某个用户的crontab文件,如果不指定用户,则默认删除当前用户的crontab文件。
-i ##在删除用户的crontab文件时给确认提示。
(2)命令示例:
crontab file [-u user] ## 用指定的文件替代目前的crontab。
crontab -l [-u user] ## 列出用户目前的crontab. (重)
crontab -e [-u user] ## 编辑用户目前的crontab. (重)
##例:
crontab -e
*/1 * * * * echo “haha” >> /root/haha.txt
*/1 * * * * echo “xixi” >> /root/xixi.txt
##编辑的这个文件在/var/spool/cron
crontab -r ##删除定时任务
4、调度配置
(1)配置说明
基本格式 :
* * * * * command
##分 时 日 月 周 命令
##第1列表示分钟1~59 每分钟用*或者 */1表示
##第2列表示小时0~23(0表示0点) 7-9表示:7点到9点之间
##第3列表示日期1~31
##第4列表示月份1~12
##第5列标识号星期0~6(0表示星期天)
##第6列要运行的命令
(2)配置示例
##每分钟执行一次date命令
*/1 * * * * date >> /root/date.txt
##每晚的21:30重启apache
30 21 * * * /usr/local/etc/rc.d/httpd restart
##每月1、10、22日的4 : 45重启apache
45 4 1,10,22 * * /usr/local/etc/rc.d/httpd restart
##每周六、周日的1 : 10重启apache
10 1 * * 6,0 /usr/local/etc/rc.d/httpd restart
##每天18 : 00至23 : 00之间每隔30分钟重启apache
0,30 18-23 * * * /usr/local/etc/rc.d/httpd restart
##每星期六的11 : 00 pm重启apache
0 23 * * 6 /usr/local/etc/rc.d/httpd restart
##每一小时重启apache
* */1 * * * /usr/local/etc/rc.d/httpd restart
##晚上11点到早上7点之间,每隔一小时重启apache
* 23-7/1 * * * /usr/local/etc/rc.d/httpd restart
##每月的4号与每周一到周三的11点重启apache
0 11 4 * mon-wed /usr/local/etc/rc.d/httpd restart
##一月一号的4点重启apache
0 4 1 jan * /usr/local/etc/rc.d/httpd restart
二、shell编程
Shell是用户与内核进行交互操作的一种接口,目前最流行的Shell称为bash Shell
Shell也是一门编程语言<解释型的编程语言>,即shell脚本<就是在用linux的shell命令编程>
一个系统可以存在多个shell,可以通过cat /etc/shells命令查看系统中安装的shell,不同的shell可能支持的命令语法是不相同的
1、基本格式
代码写在普通文本文件中,通常以 .sh为后缀名
[root@node03 shelllx]# vi hello.sh
##下面在文件中进行,后面不做赘述 以Tab代表
##按一下a、i、o中任意一个进入编辑模式
#!/bin/bash ## 表示用哪一种shell解析器来解析执行我们的这个脚本程序
echo "hello world" ##注释也可以写这里
##Esc退出编辑模式
##Shift+zz或:wq保存或退出 :q!退出且不保存
##执行脚本
[root@node03 shelllx]# sh hello.sh
hello world
##直接执行脚本
[root@node03 shelllx]# ./hello.sh
-bash: ./hello.sh: 权限不够
##给脚本添加权限
[root@node03 shelllx]# chmod 755 hello.sh
[root@node03 shelllx]# ./hello.sh
hello world
2、基本语法
(1)系统变量
Linux Shell中的变量分为“系统变量”和“用户自定义变量”,可以通过set命令查看变量
[root@node03 shelllx]# set
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:expand_aliases:extquote:force_fignore:hostcomplete:interactive_comments:login_shell:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSINFO=([0]="4" [1]="1" [2]="2" [3]="2" [4]="release" [5]="x86_64-redhat-linux-gnu")
BASH_VERSION='4.1.2(2)-release'
COLORS=/etc/DIR_COLORS
COLUMNS=87
CVS_RSH=ssh
DIRSTACK=()
DISPLAY=localhost:11.0
EUID=0
......
系统变量: H O M E 、 HOME、 HOME、PWD、 S H E L L 、 SHELL、 SHELL、USER等
[root@node03 shelllx]# a=1
_=
a=1
colors=/etc/DIR_COLORS
##打印变量的值
[root@node03 shelllx]# echo $a
1
[root@node03 shelllx]# a=hello world
-bash: world: command not found
##多了一个空格,world命令不存在
[root@node03 shelllx]# a="hello world"
[root@node03 shelllx]# echo $a
hello world
##在变量a的输出hello world后边+s
[root@node03 shelllx]# echo $a+"s"
hello world+s
[root@node03 shelllx]# echo $as
##前两种均无法正确输出
[root@node03 shelllx]# echo $a"s"
hello worlds
[root@node03 shelllx]# echo ${a}s
hello worlds
(2)自定义变量
1)
变量=值 (例:STR=abc)
等号两侧不能有空格
变量名称一般习惯为大写
使用变量: $arg
双引号和单引号有区别,双引号仅将空格脱意,单引号会将变量引用比如$param脱意
[root@node03 shelllx]# STR="hello world"
[root@node03 shelllx]# A=9
[root@node03 shelllx]# echo $A
9
[root@node03 shelllx]# echo $STR
hello world
##打印hello worlds is greate
[root@node03 shelllx]# echo $STRs is greate
is greate
##上述方法显然不对,应该用以下方法
[root@node03 shelllx]# echo ${STR}s is greate
hello worlds is greate
##撤销变量
[root@node03 shelllx]# unset A
[root@node03 shelllx]# echo $A
##声明静态变量
[root@node03 ~]# readonly g=2
[root@node03 ~]# echo $g
2
[root@node03 ~]# g=3 #不能更改
-bash: g: readonly variable
export 把变量提升为当前shell进程中的全局环境变量,可供其他子shell程序使用
##不做export定义
[root@node03 shelllx]# vi a.sh
:!/bin/bash
a="a in a.sh"
echo $a
/home/shelllx/b.sh
[root@node03 shelllx]# vi b.sh
#!/bin/bash
b="b in b.sh"
echo $b
echo $a
[root@node03 shelllx]# chmod 755 a.sh
[root@node03 shelllx]# chmod 755 b.sh
[root@node03 shelllx]# sh a.sh
a in a.sh
b in b.sh
##未在b脚本打出定义的a变量
##做export定义
root@node03 shelllx]# vi a.sh
:!/bin/bash
export a="a in a.sh"
echo $a
/home/shelllx/b.sh
[root@node03 shelllx]# vi b.sh ##子进程
#!/bin/bash
b="b in b.sh"
echo $b
echo $a
[root@node03 shelllx]# chmod 755 a.sh
[root@node03 shelllx]# chmod 755 b.sh
[root@node03 shelllx]# sh a.sh
a in a.sh
b in b.sh
a in a.sh
##a变量成了a.sh脚本所在bash进程的全局变量,该进程的所有子进程都能访问到变量a
总结:
1、a.sh中直接调用b.sh,会让b.sh在a所在的bash进程的“子进程”空间中执行
2、而子进程空间只能访问父进程中用export定义的变量
3、一个shell进程无法将自己定义的变量提升到父进程空间中去
4、“.”号执行f脚本时,会让脚本在调用者所在的shell进程空间中执行
2)反引号赋值
[root@node03 shelllx]# A=`ls -la`
[root@node03 shelllx]# echo $A
总用量 32 drwxr-xr-x 2 root root 4096 9月 2 20:46 . drwxr-xr-x. 8 root root 4096 9月 2 18:00 .. -rwxr-xr-x 1 root root 42 9月 2 20:45 a.sh -rwxr-xr-x 1 root root 42 9月 2 19:32 b.sh -rwxr-xr-x 1 root root 169 8月 27 13:53 cheng.sh -rwxr-xr-x 1 root root 52 8月 27 11:29 dashuju.sh -rw-r--r-- 1 root root 96 8月 27 11:39 dashuju.txt -rwxr-xr-x 1 root root 141 9月 2 18:51 hello.sh
[root@node03 shelllx]# A=$(ls -la)
[root@node03 shelllx]# echo $A
总用量 32 drwxr-xr-x 2 root root 4096 9月 2 20:46 . drwxr-xr-x. 8 root root 4096 9月 2 18:00 .. -rwxr-xr-x 1 root root 42 9月 2 20:45 a.sh -rwxr-xr-x 1 root root 42 9月 2 19:32 b.sh -rwxr-xr-x 1 root root 169 8月 27 13:53 cheng.sh -rwxr-xr-x 1 root root 52 8月 27 11:29 dashuju.sh -rw-r--r-- 1 root root 96 8月 27 11:39 dashuju.txt -rwxr-xr-x 1 root root 141 9月 2 18:51 hello.sh
3)特殊变量
$? ##上一个命令退出的状态码(0-255)
$$ ##当前进程编号
$0 ##当前脚本名称
$n ##n位置的输入参数(n代表数字,n>=1)
$# ##表示参数的个数,常用于循环
$*和$@ ##表示参数列表
##注:$*与$@区别
##相同点
##都表示传递给函数或脚本的所有参数
##都以$1 $2 … $n 的形式组成参数列表
##不同点
##"$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式组成一个整串;
##"$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式组成一个参数列表
##演示
[root@node03 shelllx]# vi canshu.sh
#!/bin/basg
echo $$
echo $?
echo $1
echo $2
echo $3
echo $4
echo $*
echo $@
echo $#
echo $0
[root@node03 shelllx]# sh canshu.sh b c m s f
2870
0
b
c
m
s
b c m s f
b c m s f
5
canshu.sh
3、算数表达式运算
(1)expr
expr m + n 或$((m+n))
##分布计算
[root@node03 shelllx]# S=`expr 2 + 3`
[root@node03 shelllx]# B=`expr $S \* 4` ## *需要转义
[root@node03 shelllx]# echo $B
20
##一步完成
[root@node03 shelllx]# expr `expr 2 + 3 ` \* 4
20
[root@node03 shelllx]# echo `expr \`expr 2 + 3\` \* 4`
20
(2)(())
[root@node03 shelllx]# a=$((1+2)) ##一定要加$
[root@node03 shelllx]# echo $a
3
(3)$[]
[root@node03 shelllx]# a=$[1+2]
[root@node03 shelllx]# echo $a
3
(4)let
[root@node03 shelllx]# i=1
[root@node03 shelllx]# let i++
[root@node03 shelllx]# echo $i
2
4、流程控制
(1)if语法
1)
##结果
if condition
then
statements
[elif condition
then statements. ..]
[else
statements ]
fi
##示例
[root@node03 shelllx]# vi hello.sh
#!/bin/bash
read -p "please input your name:" NAME ##从控制台读取输入数据
if [ $NAME = root ]
then
echo "hello ${NAME}, welcome !"
elif [ $NAME = ydhl2 ]
then
echo "hello ${NAME}, welcome !"
else
echo "Get out here !"
fi
[root@node03 shelllx]# sh hello.sh
please input your name:ydhl2
hello ydhl2, welcome !
[root@node03 shelllx]# sh hello.sh
please input your name:xxx
Get out here !
##错误
[root@node03 shelllx]# vi hello.sh
#!/bin/bash
read -p "please input your name:" NAME ##从控制台读取输入数据
if [ $NAME=root ]
then
echo "hello ${NAME}, welcome !"
elif [ $NAME = ydhl2 ]
then
echo "hello ${NAME}, welcome !"
else
echo "Get out here !"
fi
[root@node03 shelllx]# sh hello.sh
please input your name:xxx
hello xxx, welcome !
##错误原因:if [ $NAME=root ]中=两边没有空格,默认$NAME=root是输入一个参数,条件永远成立
2)判断条件
①基本语法
[root@node03 shelllx]# if [ a = b ];then echo ok;else echo notok;fi
notok
[root@node03 shelllx]# if [ a=b ];then echo ok;else echo notok;fi
ok
##不加空格默认只有一个参数,[]非空则返回true
[root@node03 shelllx]# if [ a = a ];then echo ok;else echo notok;fi
ok
②短路(三元运算符)
##满足条件执行&&后面的语句,不满足执行||后面的语句
[root@node03 shelllx]# a=2
[root@node03 shelllx]# b=2
[root@node03 shelllx]# c=3
[root@node03 shelllx]# [ $a = $b ] && echo ok || echo notok
ok
[root@node03 shelllx]# [ $a = $c ] && echo ok || echo notok
notok
③条件判断组合
注:[] 与[[ ]] 的区别:[[ ]] 中逻辑组合可以使用 &&、|| 符号,而[] 里面逻辑组合可以用 -a(and)、-o(or)
[root@node03 shelllx]# if [ a = b && b = c ]; then echo ok;else echo notok;fi
-bash: [: missing `]'
notok
[root@node03 shelllx]# if [ a = b -a b = b ]; then echo ok;else echo notok;fi
notok
[root@node03 shelllx]# if [ a = b -o b = b ]; then echo ok;else echo notok;fi
ok
[root@node03 shelllx]# if [[ a = b && b = b ]]; then echo ok;else echo notok;fi
notok
[root@node03 shelllx]# if [[ a = b || b = b ]]; then echo ok;else echo notok;fi
ok
④判断运算符
##字符串比较
= ##字符串是否相等
!= ##字符串是否不相等
-z ##字符串长度为0返回true
-n ##字符串长度不为0返回true
##示例
if [ 'aa' = 'bb' ]; then echo ok; else echo notok;fi
if [ -n "aa" ]; then echo ok; else echo notok;fi
if [ -z "" ]; then echo ok; else echo notok;fi
##整数比较
-lt ##小于
-le ##小于等于
-eq ##等于
-gt ##大于
-ge ##大于等于
-ne ##不等于
\< ##转义的数学符号
##文件判断:
if [ -d /bin ]; then echo ok; else echo notok;fi ##-d 是否为目录
if [ -f /bin/ls ]; then echo ok; else echo notok;fi ##-f 是否为文件
if [ -e /bin/ls ]; then echo ok; else echo notok;fi ##-e 是否存在
(2)while语法
##第一种
while expression
do
command
…
done
##第二种
i=1
while ((i<=3))
do
echo $i
let i++
done
##示例
[root@node03 shelllx]# vi while.sh
[root@node03 shelllx]# sh while.sh
1
2
3
(3)case语法(常用)
[root@node03 shelllx]# vi case.sh
case $1 in
start)
echo "starting"
;;
stop)
echo "stoping"
;;
*)
echo "Usage: {start|stop}"
esac
[root@node03 shelllx]# sh case.sh 2
Usage: {start|stop}
[root@node03 shelllx]# sh case.sh start
starting
[root@node03 shelllx]# sh case.sh stop
stoping
(4)for语法
①方式一
##第一种
[root@node03 shelllx]# vi for.sh
for N in 1 2 a
do
echo $N
done
[root@node03 shelllx]# sh for.sh
1
2
a
##第二种
[root@node03 shelllx]# for N in 1 2 3; do echo $N; done
1
2
3
##第三种
[root@node03 shelllx]# for N in {1..3}; do echo $N; done
1
2
3
②方式二
##第一种
[root@node03 shelllx]# vi for.sh
for ((i = 0; i <= 5; i++))
do
echo "welcome $i times"
done
[root@node03 shelllx]# sh for.sh
welcome 0 times
welcome 1 times
welcome 2 times
welcome 3 times
welcome 4 times
welcome 5 times
##第二种
[root@node03 shelllx]# for ((i = 0; i <= 5; i++)); do echo "welcome $i times"; done
welcome 0 times
welcome 1 times
welcome 2 times
welcome 3 times
welcome 4 times
welcome 5 times
③练习:打印九九乘法表
[root@node03 shelllx]# vi cheng.sh
echo ""
echo "9x9乘法表"
echo ""
for ((i = 1; i <= 9; i++))
do
for ((j = 1; j <= i; j++))
do
echo -n "$i x $j = $[ $i * $j ]"$'\t'
done
echo ""
echo ""
done
[root@node03 shelllx]# sh cheng.sh
9x9乘法表
1 x 1 = 1
2 x 1 = 2 2 x 2 = 4
3 x 1 = 3 3 x 2 = 6 3 x 3 = 9
4 x 1 = 4 4 x 2 = 8 4 x 3 = 12 4 x 4 = 16
5 x 1 = 5 5 x 2 = 10 5 x 3 = 15 5 x 4 = 20 5 x 5 = 25
6 x 1 = 6 6 x 2 = 12 6 x 3 = 18 6 x 4 = 24 6 x 5 = 30 6 x 6 = 36
7 x 1 = 7 7 x 2 = 14 7 x 3 = 21 7 x 4 = 28 7 x 5 = 35 7 x 6 = 42 7 x 7 = 49
8 x 1 = 8 8 x 2 = 16 8 x 3 = 24 8 x 4 = 32 8 x 5 = 40 8 x 6 = 48 8 x 7 = 56 8 x 8 = 64
9 x 1 = 9 9 x 2 = 18 9 x 3 = 27 9 x 4 = 36 9 x 5 = 45 9 x 6 = 54 9 x 7 = 63 9 x 8 = 72 9 x 9 = 81
5、函数使用
(1)函数定义
[root@node03 shelllx]# vi func1.sh
hello() ## 函数定义
{
echo "Hello there today's date is `date +%Y-%m-%d`"
return 2 ###返回值是状态码,只能在[0-255]范围内
}
echo "now going to the function hello"
hello
echo $? #获取函数的return值(即:返回上一条命令执行的后的值。true返回0,false返回1)
echo "back from the function"
[root@node03 shelllx]# vi func1.sh
[root@node03 shelllx]# sh func1.sh
now going to the function hello
Hello there today's date is 2019-09-03
2
back from the function
##函数调用
function hello()
function hello
hello
##脚本调试
sh -vx helloWorld.sh
##或者在脚本中增加set -x
注意:
1.必须在调用函数地方之前,先声明函数,shell脚本是逐行运行。不会像其它语言一样先预编译
2.函数返回值,只能通过$? 系统变量获得,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)
(2)参数函数
[root@node03 shelllx]# vi fun1.sh
funWithParam(){
echo "第一个参数为 $1 !"
echo "第二个参数为 $2 !"
echo "第十个参数为 $10 !"
echo "第十个参数为 ${10} !"
echo "第十一个参数为 ${11} !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
[root@node03 shelllx]# sh fun1.sh
第一个参数为 1 !
第二个参数为 2 !
第十个参数为 10 !
第十个参数为 34 !
第十一个参数为 73 !
参数总数有 11 个!
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !
注意: $ 10 不能获取第十个参数,获取第十个参数需要 $ {10}。当n>=10时,需要使用${n}来获取参数
(3)函数返回值
[root@node03 shelllx]# vi fun2.sh
funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"
[root@node03 shelllx]# sh fun2.sh
这个函数会对输入的两个数字进行相加运算...
输入第一个数字:
9
输入第二个数字:
8
两个数字分别为 9 和 8 !
输入的两个数字之和为 17 !
(4)跨脚本调用函数
[root@node03 shelllx]# vi fun_other.sh
. /home/shelllx/fun2.sh
## 注: . 和 / 之间有空格
# 或者 source /home/shelllx/fun2.sh
[root@node03 shelllx]# sh fun_other.sh
这个函数会对输入的两个数字进行相加运算...
输入第一个数字:
6
输入第二个数字:
4
两个数字分别为 6 和 4 !
输入的两个数字之和为 10 !
6、except的使用
痛点:使用scp命令远程拷贝文件时,会有人机交互的过程,如何让脚本完成人机交互?
妙药: expect
用法示例:
先观察 ssh localhost 的过程
再看expect的功能
[root@node03 shelllx]# vi exp_test.sh
set timeout -1;
spawn ssh localhost;
expect {
"(yes/no)" {send "yes\r";exp_continue;}
"password:" {send "hadoop\r";exp_continue;}
eof {exit 0;}
}
[root@node03 shelllx]# expect -f exp_test.sh
spawn ssh localhost
The authenticity of host 'localhost (::1)' can't be established.
RSA key fingerprint is e0:b8:15:42:b5:88:8b:ac:f2:b3:bd:c1:4f:35:23:d7.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'localhost' (RSA) to the list of known hosts.
Last login: Mon Sep 2 22:49:32 2019 from 192.168.72.1