一、概述
1、Shell有什么用?
Shell是一个命令解释器,它接收应用程序/用户命令,然后调用操作系统内核。
Shell还是一个功能强大的编程语言,具有容易编写、容器调试、灵活性强的优点。
2、Shell的几种实现方式?
在Xshell中输入cat /etc/shells
,可以看到如下内容:
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
这都是shell解释器的实现方式,我们通过cd /bin
命令进如bin
目录下面,然后执行ll | grep sh
命令,可以看到如下内容:
lrwxrwxrwx. 1 root root 4 Apr 30 2020 sh -> bash
当然在/usr/bin
下看到的内容也是一样的,所以sh
就是bash
的软链接,所以两者没有区别,至少在Centos7中是这样
二、脚本入门
1、脚本格式
脚本以#!/bin/bash
开头,其中/bin/bash
就是shell语句解释器文件的全路径,对应上一节2、Shell的几种实现方式?
2、编写第一个shell脚本
要求: 编写shell脚本文件,用于输出hello world!
内容:
#!/bin/bash
echo 'hello world!'
操作:
- 执行
touch helloworld.sh
命令用于创建文件 - 将内容添加到文件中
3、shell脚本的常见执行方法
- 使用
sh
或者bash
脚本文件的相对路径或者绝对路径,如下所示:
- 使用脚本相对路径或者绝对路径直接执行,但是一定要对当前脚本文件具有执行权,需要通过命令
chmod 777 脚本文件名称.sh
进行授权,然后通过相对路径或者绝对路径调用即可,如下所示:
- 使用
source
或者.
命令执行,如下所示:
解释:
- 第一种执行方式:本质是bash解析器帮我们执行脚本,所以不要求脚本具有执行权限。
- 第二种执行方式:本地是需要脚本文件自己执行,所以需要执行权限。
- 第三种执行方式和前面两种都不同,其中
source
或者.
都是shell内嵌的命令,大家可以通过type source
和type .
查看,所以这两种执行方式也不要求脚本文件具有可执行权限;另外第三种执行方式会直接使用主shell进程
去执行,而第一种和第二种方式会使用子shell进程
执行,其中子shell进程
执行某些命令可能会不生效,毕竟它的作用范围有限。因此在修改一些文件之后,我们会通过第三种方式执行下,让主shell进程
去执行,可以保证命令可以生效,老师给的解释如下:
4、进入或者退出子bash
# 进入子bash
bash
# 退出子bash
exit
5、判断当前进程所在的bash层级
执行ps -f
命令(注意:不带-e,因为-e是显示所有进程,而-f是全格式显示),可以查看正处于Running的进程,根据显示结果来看,可以显示当前环境的进程和父进程,其中ps -f
命令进程的PPID(父进程)是当前bash,然后可以根据层级关系计算出当前bash层级
三、变量
1、分类
- 系统变量-作用范围:所有层级的bash都可以用
- 自定义变量-作用范围:只有当前层级的bash可以使用
- 特殊变量:以$符开头的一些特殊含义的命令
2、优先级
- 如果当前bash有同名自定义变量,那就使用这个
- 如果当前bash没有同名自定义变量,但是系统变量中有,那就使用系统变量
- 如果当前bash和系统变量中都没有,那就打印空行
3、查看全部变量
命令如下:
set
4、系统变量
4.1、查看所有系统变量
evn
4.2、查看系统变量
# 1、使用printenv
# 语法:
printenv 系统变量名称
# 示例:查看家目录
printenv HOME
# 2、使用echo
# 语法:
echo $系统变量名称
# 示例:查看家目录
echo $HOME
4.3、使用系统变量
# 语法:
命令 $系统变量名称
# 示例:
ls $HOME
4.4、常用系统变量
# 1、家目录
HOME
# 2、当前目录的全路径
PWD
# 3、当前shell所用bash
SHELL
# 4、当前用户
USER
# 5、执行命令时扫描路径列表
PATH
4.5、拓展:系统环境变量“PATH”的作用
执行echo $PATH
之后,可以看到:
/opt/apache-maven-3.5.0/bin:/usr/local/jdk1.8.0_121/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
当我们执行命令的时候,Linux系统会自动扫描上述路径下面的文件,然后执行这些文件
如果想让输入自定义脚本文件的全名称就执行脚本文件,我们可以把脚本文件放在这些路径下面即可,这个时候文件全名称就变成一个命令了,我们在任何地方直接执行文件名称就可以执行该脚本文件了
# 1、将脚本文件放到/root/bin下
cp helloworld.sh /root/bin
# 2、在任何地方都可以通过脚本文件名称执行该脚本文件了
helloworld.sh
另外/bin
是usr/bin
的软链接,而/sbin
是usr/sbin
的软链接,因此我们把上述脚本文件放在/bin
或者/sbin
目录下面也可以起到一样的效果
5、自定义变量
5.1、基础语法
# 1、定义变量
# 语法:
变量名=变量值
# 注意:
# (1)变量名称可以由数字、字母、下划线组成,但是不能以数字开头,建议系统变量大写
# (2)等号前后不能有空格,因为空格是用来分隔命令或者参数的,而变量名不是命令
# (3)变量值带有空格,需要使用双引号或者单引号括起来
# (4)支持多次对同一个变量赋值
# 示例:
my_var=hello
my_var2="hello world"
# 2、定义自定义只读变量
# 注意:要求和上面一样,只是在命令前面添加readonly,该变量类型可以读取变量值,但是不能修改变量值
# 语法:
readonly 变量名=变量值
# 示例:
readonly a=5
# 3、撤销变量
# 注意:只能撤销“普通自定义变量”,但是不能撤销“自定义只读变量”
unset 变量名
# 4、提升自定义变量为系统变量
# 注意:
# (1)只有在顶级bash执行才有效,虽然在子bash(或者孙子bash)也可以执行,但是无效
# (2)可以多次执行
# 语法:
export 变量名称
# 示例:
export my_var
5.2、类型
默认类型是字符串,不会进行数据运算
6、特殊变量
6.1、$数字或者${数字}
# 功能:
在sh脚本文件中获取用户传入的参数,即执行./脚本文件.sh 参数1 参数2 ……
# 语法:
(1)$0:该脚本文件被执行的命令
(2)$1~$9:第1~9个参数
(3)${n}:n代表>=10的数字,比如${10},其中位次大于10的参数需要使用这种方式获取
# 示例:
# 脚本文件(canshu.sh)
#!/bin/bash
echo ======当前脚本被执行的命令======
echo $0
echo ======第一个传入的参数======
echo $1
# 执行命令
./canshu.sh HelloWorld
# 执行结果
======当前脚本被执行的命令======
./canshu.sh
======第一个传入的参数======
HelloWorld
# 拓展:
# 在shell脚本文件中,你知道单引号和双引号对变量取值的影响吗?
# 单引号:让所有变量($变量名称)变成普通字符串,不会在发挥作用
# 双引号:会让所有变量依然发挥作用
# 示例:
# 脚本文件(yinhao.sh)
#!/bin/bash
echo 'hello world, i am $0'
echo "hello world, i am $0"
# 执行命令
./yinhao.sh
# 执行结果
hello world, i am $0
hello world, i am ./yinhao.sh
6.2、$#
# 作用:获取输入参数个数;常用于校验参数个数、循环次数
# 语法:在sh脚本文件中直接使用
# 示例
# 脚本文件(jinghao.sh)
#!/bin/bash
echo "参数数量:$#"
# 执行命令1
./jinghao.sh
# 执行结果1
参数数量:0
# 执行命令2
./jinghao.sh 1 2 3
# 执行结果2
参数数量:3
6.3、$* 或者 $@
# 作用:获取命令行中的所有参数
# 区别:
# $*:将所有参数组成的字符串(中间用空格分隔)
# $@:将所有参数放到集合中
# 示例:
# 脚本文件(xinghao.sh)
#!/bin/bash
echo 星号:$*
echo @符号:$@
# 执行命令
./xinghao.sh
# 执行结果
星号:1 2 3
@符号:1 2 3
6.4、$?
# 作用:返回上一次命令的执行状态,0代表成功,其他值代表失败
# 示例:
# 脚本文件(wenhao.sh)
#!/bin/bash
echo 'hello world'
echo 执行状态:$?
echo1 'hello world'
echo 执行状态:$?
# 执行命令
./wenhao.sh
# 执行结果
hello world
执行状态:0
./wenhao.sh: line 4: echo1: command not found
执行状态:127
四、运算符
# 作用:进行四则运算
# 语法:$((四则运算)) 或者 $[四则运算]
# 注意:四则运算中可以包含空格或者服务,想怎么写都可以
# 示例1:演示四则运算
# 脚本文件(sizeyunsuan1.sh)
#!/bin/bash
echo $[(($1 + $2 - $3) * $4) / $5]
# 执行命令
./sizeyunsuan1.sh 10 20 10 4 5
# 结果
16
# 示例2:演示赋值操作
# 脚本文件(sizeyunsuan2.sh)
#!/bin/bash
jieguo=$[(($1 + $2 - $3) * $4) / $5]
echo $jieguo
# 执行命令
./sizeyunsuan2.sh 10 20 10 4 5
# 结果
16
五、条件判断
1、基本语法
# 什么情况下代表执行成功?答:条件执行结果不是false(逻辑值)或者空串即可
# 方法1:推荐使用
[ 条件 ]
# 要求:条件前后要有空格
# 注意:条件非空或者逻辑false即为true,
# 其中[ atguigu ]是true,[ 2 = 2 ]是true,[ ]是false
# 方法2:不推荐使用
test 条件
# 示例
a=hello
test a = world
echo $?
# 结果
1
2、比较字符串
# 语法:
# =:判断是否相等
# !=:判断是否不相等
# 示例:
# 使用=
a=hello
[ $a = world ]
echo $?
# 结果
1
# 使用!=
a=hello
[ $a != hello ]
echo $?
# 结果
0
3、比较整数
# 语法:
# -eq:判断是否相等(equal)
# -ne:判断是否不相等(not equal)
# -lt:判断是否小于(less than)
# -le:判断是否小于等于(less equal)
# -gt:判断是否大于(greater than)
# -ge:判断是否大于等于(greater equal)
# 示例:
# 使用-eq,这里就不演示其他类型了~
a=1
[ $a eq 1 ]
echo $?
# 结果
0
4、判断文件权限
# 语法:
# -r 文件名称:是否有读的权限
# -w:文件名称:是否有写的权限
# -x:文件名称:是否有执行的权限
# 示例:
# 使用-r,这里就不演示其他类型了~
[ -r xinghao.sh ]
echo $?
# 结果
0
5、判断文件存在
# 语法:
# -e:该文件或者目录存在?(existence)
# -f:该文件存在?(file)
# -d:该目录存在?(directory)
# 示例
# 首先我通过“echo 1 > 1.txt和mkdir a”命令创建了文件“1.txt”和目录“a”
# 判断文件/目录是否存在
[ -e 2.txt ]
echo $?
# 判断文件/目录是否存在结果
1
# 判断文件是否存在
[ -f 2.txt ]
echo $?
# 判断文件是否存在结果
1
# 判断目录是否存在
[ -e b ]
echo $?
# 判断目录是否存在结果
1
# 将文件当成目录进行判断
[ -d 1.txt ]
echo $?
# 将文件当成目录进行判断结果
1
# 将目录当成文件判断的结果同理所示,这里不在演示
6、多条件判断
# 作用:类似java中的三元运算符,即:条件 ? 代码1 : 代码2,如果条件为真将执行代码1,否则执行代码2
# 语法:
&&:当前一条命令执行成功,才执行后面的命令(逻辑与)
||:当前一条命令执行失败,才执行后面的命令(逻辑或)
# 示例1:
[ atguigu ] && echo OK || echo notOK
# 示例1结果:
OK
# 示例2:
[ ] && echo OK || echo notOK
# 示例2结果:
notOK
六、流程控制(重点)
1、if判断
1.1、单分支语句
# 语法:
# 方式1(then前面的分号代表在一行语句中分隔两条命令):
if [ 条件判断式 ];then
程序
fi
# 方式2:
if [ 条件判断式 ]
then
程序
fi
# 注意:
# (1)[ 条件判断式 ]就是上一节介绍的
# (2)以if反写而成的fi结尾
# 示例:
# 普通使用:
age=20
if [ $age -ge 18 ];then echo 年满18周岁;fi
# 结果:
年满18周岁
# 和逻辑与一起使用,写法1:
age=20
if [ $age -ge 18 ] && [ $age -lt 35 ];then echo 年满18周岁,但是小于35岁;fi
# 结果:
年满18周岁,但是小于35岁
# 和逻辑与一起使用,写法2(-a代表逻辑与and):
age=20
if [ $age -ge 18 -a $age -lt 35 ];then echo 年满18周岁,但是小于35岁;fi
# 结果:
年满18周岁,但是小于35岁
# 拓展:
在一行语句中,可以使用分号分隔两条命令,但是后面的命令所执行的名称空间依赖前面的命令
比如:cd /root/;ls
其中该行命令中的ls是在root目录下执行的
额外拓展:
如果在if语句中比较字符串大小,左侧的值是传进来的参数,如果直接写$1 = atguigu
,当用户没有输入参数的时候,脚本就会执行出错,所以可以将$1用双引号括起来,然后在后面加一个x,然后也在后面值的后面加一个x,即使出现上述情况,也不会报错,如下:
1.2、多分支语句
# 语法:
if [ 条件判断式 ]
then
程序
elif [ 条件判断式 ]
then
程序
……
else
程序
fi
# 注意:
# (1)可以写多个elif子句,其中elif代表else if
# (2)else子句不是必须的
# (3)结尾依然以if反写成fi结尾
# 示例1:使用if、elif
# 脚本文件(if1.sh)
#!/bin/bash
if [ $1 -gt 60 ]
then
echo 老年人
elif [ $1 -gt 35 ]
then
echo 中年人
elif [ $1 -gt 18 ]
then
echo 青年人
fi
# 测试命令1
./if1.sh 80
# 结果1
老年人
# 示例2:使用if、elif、else
# 脚本文件(if2.sh)
#!/bin/bash
if [ $1 -gt 60 ]
then
echo 老年人
elif [ $1 -gt 35 ]
then
echo 中年人
elif [ $1 -gt 18 ]
then
echo 青年人
else
echo 孩子
fi
# 测试命令2
./if2.sh 10
# 结果2
孩子
2、case语句
# 语法:
case $变量名 in
值1)
程序1
;;
值2)
程序2
……
*)
默认程序
;;
esac
# 注意:
# (1)最后一个程序后面的;;不是必须的,;;相当于break
# (2)最后一个默认程序不是必须的,相当于default语句
# (3)中间每一个程序后面必须加上;;,否则会执行报错
# 示例1:不使用默认语句
# 脚本文件(case1.sh)
#!/bin/bash
case $1 in
10)
echo 年龄10岁了
;;
20)
echo 年龄20岁了
esac
# 测试命令1
./case1.sh 10
# 结果1
年龄10岁了
# 示例2:使用默认语句
# 脚本文件(case2.sh)
#/bin/bash
case $1 in
10)
echo 年龄10岁了
;;
20)
echo 年龄20岁了
;;
*)
echo 不知道具体年龄
esac
# 测试命令2
./case1.sh 30
# 结果2
不知道具体年龄
3、for循环
3.1、写法1(类似java中的fori,优点:控制粒度细)
# 语法
for (( 初始值; 循环控制条件; 变量变化 ))
do
程序
done
# 注意:
# (1)双括号里面的内容可以随意写,不用在于空格等问题
# 示例(用于计算数字加和结果)
# 脚本文件(for1.sh)
#!/bin/bash
sum=0
for (( i = 1;i <= $1; i++ ))
do
# 四则运算法则
sum=$[$sum + $i]
done
echo "从1加到$1,结果是:$sum"
# 执行命令
./for1.sh 10
# 结果
从1加到10,结果是:55
3.2、写法2(类似java中的foreach,优点:书写简单)
# 语法
for 变量名 in 值1 值2 ……
do
程序
done
# 注意
# (1)值的写法有很多种,比如:“美的 海尔 格力”、“{小数值..大数值}”、“$1 $2 ……”、“$*”、“$@”等
# 示例1(使用字符串组合)
# 脚本文件(for1.sh)
#!/bin/bash
for i in 美的 海尔 格力
do
echo $i
done
# 执行程序
./for1.sh
# 结果
美的
海尔
格力
# 示例2(使用顺序数值组合)
# 脚本文件(for2.sh)
#!/bin/bash
for i in {2..4}
do
echo $i
done
# 执行程序
./for2.sh
# 结果
2
3
4
# 示例3(使用用户传参)
# 脚本文件(for3.sh)
#!/bin/bash
for i in $1 $2
do
echo $i
done
# 执行程序
./for3.sh
# 结果
1
2
# 示例4(使用$*)
# 脚本文件(for4.sh)
#!/bin/bash
for i in $*
do
echo $i
done
# 执行程序
./for4.sh
# 结果
1
2
3
# 示例5(使用$@)
# 脚本文件(for5.sh)
#!/bin/bash
for i in $@
do
echo $i
done
# 执行程序
./for5.sh
# 结果
1
2
3
# 示例6(对于$*和$@的区别)
# 脚本文件(for6.sh)
#!/bin/bash
echo '用双引号将$*括起来'
for i in "$*"
do
echo $i
done
echo '用双引号将$@括起来'
for i in "$@"
do
echo $i
done
# 执行程序
./for6.sh
# 结果
用双引号将$*括起来
1 2 3
用双引号将$@括起来
1
2
3
4、while循环
# 语法
while [ 条件判断式 ]
do
程序
done
# 示例1(使用传统写法编写循环体程序)
# 脚本文件(while1.sh)
#!/bin/bash
i=1
sum=0
while [ $i -le $1 ]
do
sum=$[$sum + $i]
i=$[$i + 1]
done
echo "从1加到$1,结果是:$sum"
# 执行命令
./while1.sh 10
# 结果
从1加到10,结果是:55
# 示例2(使用新命令编写循环体程序)
# 脚本文件(while2.sh)
#!/bin/bash
i=1
sum=0
while [ $i -le $1 ]
do
# 使用let命令,然后+=前后不能存在空格,并且++前面也不能有空格
let sum+=i
let i++
done
echo "从1加到$1,结果是:$sum"
# 执行命令
./while2.sh 10
# 结果
从1加到10,结果是:55
七、读取控制台输入
# 语法
read 选项 参数
# 选项(非必须):
# -p:指定用户输入时的提示信息
# -t:指定等待用户输入的超时时间(单位:秒),如果不加-t参数,控制台将一直等待
# 参数(必须):接受用户输入的变量名称
# 示例1(不使用-t参数)
# 脚本文件(read1.sh)
#!/bin/bash
read -p "请输入您的姓名:" name
echo "welcome, $name"
# 执行命令
./read1.sh
# 操作
页面输出提示信息“请输入您的姓名:”
然后我输入“李华”后点击回车按键
# 结果
welcome, 李华
# 示例2(使用-t参数)
# 脚本文件(read2.sh)
#!/bin/bash
read -t 10 -p "请输入您的姓名:" name
echo "welcome, $name"
# 执行命令
./read2.sh
# 操作
页面输出提示信息“请输入您的姓名:”
然后我什么都不操作
# 结果
等待10秒之后,在原有“请输入您的姓名:”接着打印welcome
# 分析
如果我不输入的话,添加超时时间之后,如果在时间之内输入内容,效果没有什么异常;如果没有输入内容,程序也会继续往下执行,只是参数没啥内容
# 思考
不知道大家是否还记得,有一些程序在执行过程中需要你输入Y或者N,可能就 是这样实现的吧!
八、函数
1、学习前提
1.1、命令替换
# 作用
(1)用于执行命令,并且获取命令的标准输出,但是无法获取标准错误;此时echo就不会输出结果到控制台了
(2)命令替换在命令行中会被优先执行,可以根据需求,将其放置在命令行的任意位置
(3)命令替换获取到的标准输出,其中换行字符全部变成了空格字符
(4)支持嵌套,即$(XXX$(XXX)XXX)
# 语法
$(命令)
2、系统函数
2.1、函数、脚本、命令的关系
- 函数或者命令其实都是脚本文件,只是叫法不同
- 系统函数是被放在“环境变量PATH”指定目录列表下的脚本文件,当执行命令的时候,Linux系统会扫描“系统环境变量PATH”指定的目录列表,其中
/usr/bin
就是该目录的代表;我们可以执行ls /usr/bin | grep basename
命令看到“basename”脚本文件(basename函数)
2.2、basename
# 作用
(1)去除最后一个/之前的内容,包括最后一个/
(2)去除后缀
# 语法
basename 字符串或者路径 后缀
# 注意
(1)字符串或者路径:必须加上
(2)后缀:比如.jpg,不是必须要加上的
# 示例1
basename ~/shellStudy/0629/print.sh
# 结果
print.sh
# 示例2
basename print.sh
# 结果
print.sh
# 示例3
basename ~/shellStudy/0629/print.sh .sh
结果
print
# 示例4
basename print.sh .sh
结果
print
2.3、dirname
# 作用
(1)去除“/文件名称”(非目录的部分),然后返回剩下的路径(目录的部分)
# 语法
dirname 文件绝对路径
# 示例1
dirname print.sh
# 结果
.
# 示例2
dirname ~/shellStudy/0629/print.sh
# 结果
/root/shellStudy/0629
2.4、综合案例
# 作用:打印脚本文件所在目录的全路径
# 脚本文件(systemfun.sh)
#!/bin/bash
echo "当前脚本文件所在目录全路径: $(cd $(dirname $0);pwd)"
# 执行命令
./systemfun.sh
# 结果
当前脚本文件所在目录全路径: /root/shellStudy/0629
# 分析
$0代表执行脚本文件的路径,但是使用source打印的就是“-bash”,注意不实用source执行本次测试即可;
$(dirname $0):打印脚本文件所在目录的路径,可能是相对路径,也可能是绝对路径,主要看用户怎么输入的
cd $(dirname $0);pwd:进入脚本文件所在目录路径,然后打印目录全路径
3、自定义函数
# 语法
[function] 函数名称[()]
{
程序
[return 整数结果;]
}
# 注意
(1)方括号中的内容都是可以省略的
(2)整数结果的范围是0~255,然后在调用函数之后通过$?命令获取返回值,该结果一般作用是返回执行状态信息,而不是返回结果
(3)可以通过echo命令将结果输出到控制台,然后通过命令替换写法获取该值,即$(调用函数)
# 示例(打印两数之和,以及两数之和的2次方)
# 脚本文件(custom.sh)
#!/bin/bash
function add()
{
echo $[$1 + $2]
}
read -p "请输入第一个加数:" num1
read -p "请涮涮第二个加数:" num2
sum=$(add $num1 $num2)
power=$[$sum * $sum]
echo "$num1 和 $num2 的和:$sum"
echo "$num1 和 $num2 的和的二次方:$power"
# 执行脚本
./custom.sh
# 操作
页面提示“请输入第一个加数:”,我输入1
页面提示“请输入第二个加数:”,我输入2
# 结果
1 和 2 的和:3
1 和 2 的和的二次方:9
4、综合案例
要求: 将一个目录打压缩包,然后放到另外一个目录中,并且每天执行一次
脚本文件:
#!/bin/bash
# 首先判断参数个数是否为2
if [ $# -ne 2 ]
then
echo "参数个数错误!应该依次传入两个参数,分别是待归档目录路径和归档压缩包存储路径"
exit
fi
# 判断两个参数是否都是目录路径
if [ -d $1 ] && [ -d $2 ]
then
echo
else
echo "请检查两个目录是否存在"
exit
fi
# 获取待归档的目录名称、目录的父级目录绝对路径、归档压缩包所在目录名称、归档压缩包所在目录父目录绝对路径
DIR_NAME=$(basename $1)
DIR_PATH=$(cd $(dirname $1); pwd)
DEST_NAME=$(basename $2)
DEST_PATH=$(cd $(dirname $2); pwd)
# 获取当前日期
DATE=$(date +%y%m%d)
# 定义归档压缩包全路径
FILE=archive_${DIR_NAME}_$DATE.tar.gz
DEST=$DEST_PATH/$DEST_NAME/$FILE
# 开始归档目录文件
echo "开始归档……"
cd $DIR_PATH; tar -czPf $DEST $DIR_NAME
if [ $? -eq 0 ]
then
echo "归档成功"
echo "归档文件所在绝对路径:$DEST"
else
echo "归档失败"
fi
手动单次执行脚本:
# ../0629/:被压缩目录
# ~/shellStudy/:压缩包存储的目录
./test.sh ../0629/ ~/shellStudy/
让脚本文件每天执行一次:
# 每天2点定时执行脚本命令
0 2 * * * /root/shellStudy/0629/test.sh /root/shellStudy/0629/ /root/shellStudy
# 查看定时任务列表
crontab -l