linux编写脚本之快速入门
前言
在进行Linux测试时编写脚本是必不可少的。最近经常使用Linux,感觉太频繁地敲击键盘有些累了,于是想到了Shell脚本。可以把太多的命令写成一个脚本,这样每次执行一遍 shell文件,就可以省去了敲击键盘的时间。于是在网上搜了一些有关Linux下脚本编程的内容。
Shell不仅仅是命令的收集,而且是一门非常棒的编程语言。您可以通过使用shell使大量的任务自动化,shell特别擅长系统管理任务,尤其适合那些易用性、可维护性和便携性比效率更重要的任务。
用户可以使用任何文本编辑器编辑shell脚本文件,例如VI、gedit等。
Shell脚本的名称可以随便定义,也不要什么后缀名,例如可以写abc,smartzip这类名称。
1、创建脚本并运行Shell脚本
1.1 首先创建一个名为 script
的新目录,它将托管我们所有的 bash
脚本。
脚本文件新建可以用touch命令,也可以直接用文本编辑器如vi、vim、gedit等新建并编辑,文件名为*.sh
shell脚本文件的名称可以任意,但为了避免被误认为是普通文件,后缀名为.sh代表是一个shell脚本文件(例如后缀名为.py代表是一个python文件)
1.2 编写内容
echo 'Hello, World!'
1.3 启动shell脚本
跳转到script路径,输入 bash script.sh 启动shell脚本
你就会看到Hello, World!
打印在屏幕上。
2、将 shell 脚本转换为 bash 脚本
Bash是“Bourne-Again shell”的缩写,它只是 Linux 中许多可用 shell 的一种。
shell 是一个命令行解释器,它接受并运行命令。如果你以前运行过任何 Linux 命令,那么你已经使用过 shell。当你在 Linux 中打开终端时,你已经在运行系统的默认 shell。
Bash 通常是大多数 Linux 发行版中的默认 shell。这就是为什么 bash 通常是 shell 的同义词。Shell 只是一个程序,而 bash 是它的一个实现。还有其他这样的 shell 程序,如 ksh、zsh等。如果你安装了其他 shell,你也可以使用它来代替 bash。
shell 脚本通常具有几乎相同的语法,但有时也会有所不同。例如,数组索引在 Zsh 中从 1 开始,而不是在 bash 中从 0 开始。如果为Zsh shell编写的脚本有数组,则它在 bash 中将无法正常工作。
为了避免这种错误,你应该告诉解释器你的 shell 脚本是为 bash shell 编写的。你是怎样做的?你可以用shebang来实现这一点。
3、Shell 脚本的使用
1、 “#!/bin/bash”
这一行被称为shebang 行,在某些文献中,它被称为hashbang 行,这是因为它以两个字符hash ‘#’ 和bang ‘!’ 开头。
#!/bin/sh (必须放在文件的第一行)
符号#!用来告诉系统它后面的参数是用来执行该文件的程序。在这个例子中我们使用/bin/sh来执行程序。
2、 注释
在进行shell编程时,以#开头的句子表示注释,直到这一行的结束。如同其他编程语言一样,我们在编写脚本时也应该尽可能地添加注释,那么即使相当长的时间内没有使用该脚本,我们也能在很短的时间内明白该脚本的作用及工作原理。
3.、变量
在其他编程语言中您必须使用变量。在shell编程中,所有的变量都由字符串组成,并且您不需要对变量进行声明。要赋值给一个变量,您可以这样写:变量名=值
取出变量值可以加一个美元符号($)在变量前面:
#!/bin/sh
#对变量赋值
a=“hello world”
#现在打印变量a的内容
echo “A is:”
echo $a
文件内容如下:
4、Shell命令和流程控制
在shell脚本中可以使用三类命令:
4.1 Unix 命令:
虽然在shell脚本中可以使用任意的Unix命令,但是还是由一些相对更常用的命令。这些命令通常是用来进行文件和文字操作的。
常用命令语法及功能
指定欲显示的文件内容范围,并将它们输出到标准输出设备比如:输出每行第5个到第9个字符cut -b5-9 file.txt千万不要和cat命令混淆,这是两个完全不同的命令
cat file.txt: 输出文件内容到标准输出设备(屏幕)上
file somefile: 得到文件类型
read var: 提示用户输入,并将输入赋值给变量
sort file.txt: 对file.txt文件中的行进行排序
uniq: 删除文本文件中出现的行列比如: sort file.txt | uniq
expr: 进行数学运算Example: add 2 and 3expr 2 "+" 3
find: 搜索文件比如:根据文件名搜索find . -name filename -print
tee: 将数据输出到标准输出设备(屏幕) 和文件比如:somecommand | tee outfile
basename file: 返回不包含路径的文件名比如: basename /bin/tux将返回 tux
dirname file: 返回文件所在路径比如:dirname /bin/tux将返回/bin
head file: 打印文本文件开头几行
tail file : 打印文本文件末尾几行
sed:
Sed是一个基本的查找替换程序。可以从标准输入(比如命令管道)读入文本,并将结果输出到标准输出(屏幕)。该命令采用正则表达式(见参考)进行搜索。不要和shell中的通配符相混淆。比如:将linuxfocus 替换为 LinuxFocus :cat text.file | sed ‘‘s/linuxfocus/LinuxFocus/’’ > newtext.fileawk: awk
用来从文本文件中提取字段。缺省地,字段分割符是空格,可以使用-F指定其他分割符。cat file.txt | awk -F, ‘’{print $1 “,” $3 }''这里我们使用,作为字段分割符,同时打印第一个和第三个字段。如果该文件内容如下: AdamBor, 34, IndiaKerry Miller, 22, USA命令输出结果为:AdamBor, IndiaKerry Miller, USA
4.2 概念: 管道, 重定向和 backtick
这些不是系统命令,但是他们真的很重要。管道 (|) 将一个命令的输出作为另外一个命令的输入。
grep "hello" file.txt | wc -l
在file.txt中搜索包含有”hello”的行并计算其行数。
在这里grep命令的输出作为wc命令的输入。当然您可以使用多个命令。
重定向:将命令的结果输出到文件,而不是标准输出(屏幕)。
写入文件并覆盖旧文件
加到文件的尾部,保留旧文件内容。
反短斜线
使用反短斜线可以将一个命令的输出作为另外一个命令的一个命令行参数。
命令: find . -mtime -1 -type f -print 用来查找过去24小时(-mtime –2则表示过去48小时)内修改过的文件。如果您想将所有查找到的文件打一个包,则可以使用以下脚本:
#!/bin/sh
The ticks are backticks (`) not normal quotes (‘’):
tar -zcvf lastmod.tar.gz `find . -mtime -1 -type f
-print`
4.3 流程控制
“if” 表达式 如果条件为真则执行then后面的部分:
if ....; then
....
elif ....; then
....
else
....
fi
大多数情况下,可以使用测试命令来对条件进行测试。比如可以比较字符串、判断文件是否存在及是否可读等等…通常用" [ ] "来表示条件测试。注意这里的空格很重要。要确保方括号的空格。
[ -f "somefile" ] :判断是否是一个文件
[ -x "/bin/ls" ] :判断/bin/ls是否存在并有可执行权限
[ -n "$var" ] :判断$var变量是否有值
[ "$a" = "$b" ] :判断$a和$b是否相等
4.4 执行脚本 Linux下的sh文件默认是有执行权限的。
我们可以用命令:ls -l file_name来查看用户对文件的权限。如果没有执行权限,可以执行以下命令添加:chmod +x file_name 。然后可以通过运行:sh XX.sh这样的命令来运行脚本。当然不同的系统可能不完全相同,需要根据实际情况来。例如有的Linux下是./XX.sh就可以运行。
概括地来说,shell对shell脚本的调用可以采用3种方式:
(1)一种是将文件名作为shell命令的参数,其调用格式为:
$ Bash script_file
当要被执行的脚本文件没有可执行权限时,只能使用这种调用方式。
(2)另一种调用的方法是先将脚本文件的访问权限更改为可执行,以便该文件可以作为执行文件调用。
具体的方法是:$chmod +x script_file
$PATH=$PATH:$PWD
$script_file
(3)当执行一个脚本文件时,Shell就产生了一个Shell(即一个子进程)去执行文件中的命令。因此,脚本文件的变量值不能传递到当期Shell(即父进程)。为了使脚本文件中的变量值传递到当前Shell,必须在命令文件名前面加“.”。即:
$./script_file
“.”命令的功能是在当前shell中执行脚本文件中的命令,而不是产生一个子shell执行命令文件中的命令。
当你在脚本的最顶部包含“#!/bin/bash”行时,系统知道你想使用 bash 作为脚本的解释器。因此,你现在可以直接运行 hello.sh 脚本,而无需在其前面加上 bash。
使用 #!/bin/bash 表示该脚本是 bash shell 脚本,无论系统上正在使用什么 shell,都应该使用 bash 作为解释器运行。如果你使用的是 zsh 特定的语法,你可以通过添加 #! /bin/zsh 作为脚本的第一行。
#! 和 /bin/bash 之间的空格无关紧要。你也可以使用 #!/bin/bash。
4.5 参数详解
像上面这样的脚本程序只能执行一些预先定义好的功能,太过死板。为了让 Shell 脚本程序更好地满足用户的一些实时需求,以便灵活完成工作,必须要让脚本程序能够像之前执行命令时那样,接收用户输入的参数。
Linux 系统中的 Shell 脚本语言内设了一些用于接收参数的变量,变量之间可以使用空格间隔。例如:
$0 对应的是当前 Shell 脚本程序的名称
$# 对应的是总共有几个参数(参数个数)
$* 对应的是所有位置的参数值
$? 对应的是显示上一次命令的执行返回值
$N对应的是第 N 个位置的参数值
例子:
[root@wz lucky]# cat exam.sh
#!/bin/bash
echo "sh name: $0"
echo "total parameters $#, is $*"
echo "the first parm is $1, the fifth parm is $5"
[root@wz lucky]# bash exam.sh 1 2 3 4 5 6
sh name: exam.sh
total parameters 6, is 1 2 3 4 5 6
the first parm is 1, the fifth parm is 5
1. 条件测试语句
系统在执行mkdir命令时会判断用户输入的信息,即判断用户指定的文件夹名称是否已经存在,如果存在则提示报错;反之则自动创建。Shell 脚本中的条件测试语法可以判断表达式是否成立,若条件成立则返回数字 0,否则便返回其他随机数值。 条件测试语法的执行格式如下:
[ condition ]
注意:条件表达式两边均应有一个空格。
按照测试对象来划分,条件测试语句可以分为 4 种:
文件测试语句;
逻辑测试语句;
整数值比较语句;
字符串比较语句。
文件测试语句
文件测试即使用指定条件来判断文件是否存在或权限是否满足等情况的运算符。 具体的参数如下表:
运算符 | 作用 |
---|---|
-d | 测试文件是否为目录类型 |
-e | 测试文件是否存在 |
-f | 判断是否为一般文件 |
-r | 测试当前用户是否有权限读取 |
-w | 测试当前用户是否有权限写入 |
-x | 测试当前用户是否有权限执行 |
使用文件测试语句来判断/etc/fstab是否为一个目录类型的文件,然后通过 Shell 解释 器的内设$?变量显示上一条命令执行后的返回值。如果返回值为 0,则目录存在;如果返回值为非零的值,则意味着目录不存在:
[root@wz lucky]# [ -d /etc/fstab ]
[root@wz lucky]# echo $?
127
使用文件测试语句来判断/etc/fstab是否为一般文件,如果返回值为 0,则代表文件存在,且为一般文件:
[root@wz lucky]# [ -f /etc/fstab ]
[root@wz lucky]# echo $?
0
2. 逻辑测试语句
逻辑语句用于对测试结果进行逻辑分析,根据测试结果可实现不同的效果。例如在 Shell 终端中逻辑“与”的运算符号是&&,它表示当前面的命令执行成功后才会执行它后面的命令, 因此可以用来判断/dev/cdrom文件是否存在,若存在则输出Exist字样。
[root@wz lucky]# [ -e /dev/cdrom ] && echo "Exist"
Exist
除了逻辑“与”外,还有逻辑“或”,它在 Linux 系统中的运算符号为||,表示当前面的命令执行失败后才会执行它后面的命令,因此可以用来结合系统环境变量USER来判断当前登录的用户是否为非管理员身份:
[root@wz lucky]# [ $USER = root ] || echo "user"
[root@wz lucky]# su lucky
[lucky@wz ~]$ [ $USER = root ] || echo "user"
user
第三种逻辑语句是“非”,在 Linux 系统中的运算符号是一个叹号(!),它表示把条件测试中的判断结果取相反值。也就是说,如果原本测试的结果是正确的,则将其变成错误的; 原本测试错误的结果则将其变成正确的。
[lucky@wz ~]$ [ ! $USER = root ] || echo "user"
[lucky@wz ~]$ [ $USER = root ] || echo "user"
user
看个复杂的例子:
[lucky@wz ~]$ [ ! $USER = root ] && echo "user" || echo "root"
user
[root@wz ~]# [ ! $USER = root ] && echo "user" || echo "root"
root
先判断当前登录用户的USER变量名称是否等于root,然后用逻辑运算符“非”进行取反操作,效果就变成了判断当前登录的用户是否为非管理员用户了。最后若条件成立则会根据逻辑“与”运算符输出user字样;或条件不满足则会通过逻辑“或”运算符输出root字样,而如果前面的&&不成立才会执行后面的||符号。
3. 整数值比较语句
整数比较运算符仅是对数字的操作,不能将数字与字符串、文件等内容一起操作,而且不能想当然地使用日常生活中的等号、大于号、小于号等来判断。因为等号与赋值命令符冲突,大于号和小于号分别与输出重定向命令符和输入重定向命令符冲突。因此一定要使用规范的整数比较运算符来进行操作。可用的整数比较运算符如表所示:
运算符 | 作用 |
---|---|
-eq | 是否等于 |
-ne | 是否不等于 |
-gt | 是否大于 |
-lt | 是否小于 |
-le | 是否等于或小于 |
-ge | 是否大于或等于 |
记法:
-eq:equal
-ne:not equal
-gt:greater than
-lt:lower than
-le:lower equal
-ge:greater than
例子:
[lucky@wz ~]$ [ 10 -gt 10 ]
[lucky@wz ~]$ echo $?
1
[lucky@wz ~]$ [ 10 -eq 10 ]
[lucky@wz ~]$ echo $?
0
free 命令可以用来获取当前系统正在使用及可用的内存量信息。 接下来先使用 free -m 命令查看内存使用量情况(单位为 MB),然后通过 grep Mem:命令过滤出剩余内存量的行,再用 awk '{print $4}'命令只保留第四列,最后用FreeMem=语句``的方式把语句内执行的结果赋值给变量。
[lucky@wz ~]$ free -m
total used free shared buff/cache available
Mem: 1806 1204 118 7 483 435
Swap: 2047 60 1987
[lucky@wz ~]$ free -m | grep Mem
Mem: 1806 1204 117 7 483 434
[lucky@wz ~]$ free -m | grep Mem | awk '{print $4}'
117
[lucky@wz ~]$ FreeMem=free -m | grep Mem | awk '{print $4}'
[lucky@wz ~]$ echo $FreeMem
104
使用整数运算符来判断内存可用量的值是否小于 1024,若小于则提示“Insufficient Memory”的字样:
[lucky@wz ~]$ [ $FreeMem -lt 1024 ] && echo "Insufficient Memory"
Insufficient Memory
4. 字符串比较语句
字符串比较语句用于判断测试字符串是否为空值,或两个字符串是否相同。它经常用来判断某个变量是否未被定义(即内容为空值)。字符串比较中常见的运算符如下表所示:
运算符 | 作用 |
---|---|
= | 比较字符串内容是否相同 |
!= | 比较字符串内容是否不同 |
-z | 判断字符串内容是否为空 |
通过判断 String变量是否为空值,进而判断是否定义了这个变量:
[lucky@wz ~]$ [ -z $String ]
[lucky@wz ~]$ echo $?
0
当用于保存当前语系的环境变量值LANG不是英语(en.US)时,则会满足逻辑测试条件并输出“Not en.US”的字样:
[lucky@wz ~]$ echo $LANG
en_US.UTF-8
[lucky@wz ~]$ [ $LANG != "en.US" ] && echo "Not en.US"
Not en.US
5. 流程控制语句
5.1 if 条件测试语句
if条件测试语句可以让脚本根据实际情况自动执行相应的命令。从技术角度来讲,if 语句分为单分支结构、双分支结构、多分支结构,其复杂度随着灵活度一起逐级上升。
5.2 单分支结构
if 条件语句的单分支结构由 if、then、fi 关键词组成,而且只在条件成立后才执行预设的命令,相当于口语的“如果…那么…”。单分支的 if 语句属于最简单的一种条件判断结构, 语法格式为:
if condition
then ...
fi
例子:使用单分支的if 条件语句来判断/media/cdrom 目录是否存在,若存在就结束条件判断和整个 Shell 脚本,反之则去创建这个目录:
[lucky@wz ~]$ cat mkcdrom.sh
#!/bin/bash
DIR="/media/cdrom"
if [ ! -e $DIR ]
then
mkdir -p $DIR
fi
5.3 双分支结构
if 条件语句的双分支结构由 if、then、else、fi 关键词组成,它进行一次条件匹配判断, 如果与条件匹配,则去执行相应的预设命令;反之则去执行不匹配时的预设命令,相当于口语的“如果…那么…或者…那么…”。if条件语句的双分支结构也是一种很简单的判 断结构,语法格式如下:
if condition
then ...
else ...
fi
例子:使用双分支的 if 条件语句来验证某台主机是否在线,然后根据返回值的结果,要么显示主机在线信息,要么显示主机不在线信息。这里的脚本主要使用ping 命令来测试与对方主机的网络联通性,而 Linux 系统中的ping命令不像 Windows 一样尝试 4 次就结束,因此为了避免用户等待时间过长,需要通过-c 参数来规定尝试的次数,并使用-i参数定义每个数据包的发送间隔,以及使用-W参数定义等待超时时间。
[lucky@wz ~]$ cat chkhost.sh
#!/bin/bash
ping -c 3 -i 0.2 -W 3 $1 &> /dev/null
if [ $? -eq 0 ]
then
echo "Host $1 is On-line"
else
echo "Host $1 is Off-line"
fi
/dev/null:黑洞文件
5.4 多分支结构
if 条件语句的多分支结构由if、then、else、elif、fi 关键词组成,它进行多次条件匹配判断,这多次判断中的任何一项在匹配成功后都会执行相应的预设命令,相当于口语的“如果…那么…如果…那么…”。if条件语句的多分支结构是工作中最常使用的一种条件判断结构,尽管相对复杂但是更加灵活,语法格式如下:
if condition1
then ...
elif condition2
then ...
else ...
fi
例子:判断用户输入的分数在哪个成绩区间内,然后输出如 Excellent、Pass、Fail等提示信息。在 Linux 系统中,read是用来读取用户输入信息的命令,能够把接收到的用户输入信息赋值给后面的指定变量,-p参数用于向用户显示一定的提示信息。
[lucky@wz ~]$ cat chkscore.sh
#!/bin/bash
read -p "Enter your score(0 - 100):" GRADE
if [ $GRADE -ge 85 ] && [ $GRADE -le 100 ]
then
echo "$GRADE is Excellent"
elif [ $GRADE -ge 70 ] && [ $GRADE -le 84 ]
then
echo "$GRADE is Pass"
else
echo "$GRADE is Fail"
fi
5.5 for 条件循环语句
for的语法格式为:
for x in xx
do ...
done
例子:使用 for循环语句从列表文件中读取多个用户名,然后为其逐一创建用户账户并设置密码。首先创建用户名称的列表文件users.txt,每个用户名称单独一行。
[lucky@wz ~]$ cat users.txt
andy
barry
carl
duke
eric
george
在脚本中使用 read 命令读取用户输入的密码值,然后赋值给 PASSWD 变量,并通过-p参数向用户显示一段提示信息,告诉用户正在输入的内容即将作为账户密码。在执行该脚本后,会自动使用从列表文件 users.txt中获取到所有的用户名称,然后逐一使用“id 用户名”命令查看用户的信息,并使用$?判断这条命令是否执行成功,也就是判断该用户是否已经存在。
[root@wz lucky]# cat Exam.sh
#!/bin/bash
read -p "Enter The Users Password: " PASSWD
for UNAME in cat users.txt
do
id $UNAME &> /dev/null
if [ $? -eq 0 ]
then
echo "Already exists"
else
useradd $UNAME &> /dev/null
echo "$PASSWD" | passwd --stdin $UNAME &> /dev/null
if [ $? -eq 0 ]
then
echo "$UNAME Create success"
else
echo "$UNAME Create failure"
fi
fi
done
执行批量创建用户的 Shell 脚本 Exam.sh,在输入为账户设定的密码后将由脚本自 动检查并创建这些账户。由于已经将多余的信息通过输出重定向符转移到了/dev/null 黑洞文件中,因此在正常情况下屏幕窗口除了“用户账户创建成功”(Create success)的提示后不会有其他内容。
[root@wz lucky]# tail -6 /etc/passwd
andy:x:1001:1001::/home/andy:/bin/bash
barry:x:1002:1002::/home/barry:/bin/bash
carl:x:1003:1003::/home/carl:/bin/bash
duke:x:1004:1004::/home/duke:/bin/bash
eric:x:1005:1005::/home/eric:/bin/bash
george:x:1006:1006::/home/george:/bin/bash
让脚本从文本中自动读取主机列表,然后自动逐个测试这些主机是否在线。 首先创建一个主机列表文件 ipadds.txt:
lucky@LAPTOP-G2DIO3FV:~$ cat ipadds.txt
www.baidu.com
www.google.com
双分支 if条件语句与 for循环语句相结合,让脚本从主机列表文件 ipadds.txt中自动读取 IP 地址并将其赋值给 HLIST变量,从而通过判断 ping命令执 行后的返回值来逐个测试主机是否在线。脚本中出现的$是一种完全类似于转义字符中反引号命令的 Shell 操作符,效果同样是执行括号或双引号括起来的字符串中的命令。
[lucky@wz ~]$ cat CheckHosts.sh
#!/bin/bash
HLIST=$(cat ~/ipadds.txt)
for IP in $HLIST
do ping -c 3 -i 0.2 -W 3 $IP &> /dev/null
if [ $? -eq 0 ]
then echo "Host $IP is On-line"
else echo "Host $IP is Off-line"
fi
done
[lucky@wz ~]$ bash CheckHosts.sh
Host www.baidu.com is On-line
Host www.google.com is Off-line
while 条件循环语句
while条件循环语句是一种让脚本根据某些条件来重复执行命令的语句,它的循环结构往往在执行前并不确定最终执行的次数,完全不同于 for循环语句中有目标、有范围的使用场景。 while循环语句通过判断条件测试的真假来决定是否继续执行命令,若条件为真就继续执行, 为假就结束循环。
while语句的语法格式如下:
while condition
do ...
done
经典的猜数字:
lucky@LAPTOP-G2DIO3FV:~$ cat Guess.sh
#!bin/bash
PRICE=expr $RANDOM % 1000
TIMES=0
echo "商品实际价格为0-999之间,猜猜看是多少?"
while true
do
read -p "请输入您猜测的价格数目:" INT
let TIMES++
if [ $INT -eq $PRICE ]
then
echo "恭喜您答对了,实际的价格是 $PRICE"
echo "您总共猜测了 $TIMES 次"
exit 0
elif [ $INT -gt $PRICE ]
then
echo "太高了"
else
echo "太低了"
fi
done
$RANDOM 变量来调取出一个随机的数值(范围为 0~32767)
将这个随机数对 1000 进行取余操作,并使用 expr命令取得其结果,
再用这个数值与用户通过 read命令输入的数值进行比较判断。这个判断语句分为三种情况,分别是判断用户输入的数值是等于、 大于还是小于使用 expr命令取得的数值。
case 条件测试语句
case条件测试语句和 switch语句的功能非常相似!case语句是在多个范围内匹配数据,若匹配成功则执行相关命令并结束整个条件测试;而如果数据不在所列出的范围内, 则会去执行星号(*)中所定义的默认命令。case语句的语法结构如下
case 变量值 in
模式1)
命令序列1
;;
模式1)
命令序列1
;;
*)
默认命令序列
esac
提示用户输入一个字符并将其赋值给变量 KEY, 然后根据变量 KEY的值向用户显示其值是字母、数字还是其他字符。
#!/bin/bash
read -p "please input a char: " KEY
case $KEY in
[a-z]|[A-Z])
echo "character!"
;;
[0-9])
echo "number!"
;;
*)
echo "space or others"
esac
计划任务服务程序
计划任务分为一次性计划任务与长期性计划任务:
一次性计划任务:今晚 11 点 30 分开启网站服务。
长期性计划任务:每周一的凌晨 3 点 25 分把/home/wwwroot 目录打包备份为 backup.tar.gz。
一次性计划任务只执行一次,一般用于满足临时的工作需求。
用 at命令实现这种功能,只需要写成“at 时间”的形式就可以。
查看已设置好但还未执行的一次性计划任务,可以使用“at -l”命令;
要想将其删除,可以用“atrm 任务序号”。
在使用 at命令来设置一次性计划任务时,默认采用的是交互式方法。例如,使用下述命令将系统设置为在今晚 23:30 分自动重启网站服务。
lucky@LAPTOP-G2DIO3FV:~$ at 23:30
at > systemctl restart httpd
at > 此处请同时按下 Ctrl + D 组合键来结束编写计划任务
job 3 at Mon Apr 27 23:30:00 2017
利用管道符,让 at命令接收前面 echo命令的输出信息,以达到通过非交互式的方式创建计划一次性任务的目的。
lucky@LAPTOP-G2DIO3FV:~$ echo “systemctl restart httpd” | at 23:30
job 4 at Mon Apr 27 23:30:00 2017
使用下面的命令删除其中一个:
lucky@LAPTOP-G2DIO3FV:~$ at -l
3 Mon Apr 27 23:30:00 2017 a root
4 Mon Apr 27 23:30:00 2017 a root
lucky@LAPTOP-G2DIO3FV:~$ atrm 3
lucky@LAPTOP-G2DIO3FV:~$ at -l
4 Mon Apr 27 23:30:00 2017 a root
如果我们希望 Linux 系统能够周期性地、有规律地执行某些具体的任务,那么 Linux 系统中默认启用的 crond服务简直再适合不过了。创建、编辑计划任务的命令为“crontab -e”,查看当前计划任务的命令为“crontab -l”,删除某条计划任务的命令为“crontab -r”。另外,如果您是以管理员的身份登录的系统,还可以在 crontab命令中加上-u参数来编辑他人的计划任务。
crond服务设置任务的参数格式:分、时、日、月、星期、命令。 如果有些字段没有设置,则需要使用星号占位。
假设在每周一、三、五的凌晨 3 点 25 分,都需要使用 tar命令把某个网站的数据目录进行打包处理,使其作为一个备份文件。我们可以使用 crontab -e命令来创建计划任务。为自己创建计划任务无需使用-u参数,具体的实现效果的参数如 crontab -l 命令结果所示:
lucky@LAPTOP-G2DIO3FV:~$ crontab -e
no crontab for root - using an empty one
crontab: installing new crontab
lucky@LAPTOP-G2DIO3FV:~$ crontab -l
25 3 * * 1,3,5 /usr/bin/tar -czvf backup.tar.gz /home/wwwroot
逗号表示多个时间段,例如“8,9,12”表示 8 月、9 月 和 12 月。
减号表示一段连续的时间周期(例如字段“日”的取值为“12-15”, 则表示每月的 12~15 日)。
除号表示执行任务的间隔时间(例如“/2”表示每隔 2 分钟执行一次任务)之外。
如果在 crond服务中需要同时包含多条计划任务的命令语句,应每行仅写一条。例如我们再添加一条计划任务,它的功能是每周一至周五的凌晨 1 点钟自动清空/tmp目录内的所有文件。
尤其需要注意的是,在 crond服务的计划任务参数中,所有命令一定要用绝对路径的方式来写,如果不知道绝对路径,请用 whereis命令进行查询,rm命令路径为下面输出信息中加粗部分。
lucky@LAPTOP-G2DIO3FV:~$ whereis rm
rm: /usr/bin/rm /usr/share/man/man1/rm.1.gz /usr/share/man/man1p/rm.1p.gz
lucky@LAPTOP-G2DIO3FV:~$ crontab -e
crontab: installing new crontab
lucky@LAPTOP-G2DIO3FV:~$ crontab -l
25 3 * * 1,3,5 /usr/bin/tar -czvf backup.tar.gz /home/wwwroot
0 1 * * 1-5 /usr/bin/rm -rf /tmp/*
注意:
在 crond服务的配置参数中,可以像 Shell 脚本那样以#号开头写上注释信息,这样在日后回顾这段命令代码时可以快速了解其功能、需求以及编写人员等重要信息。
计划任务中的“分”字段必须有数值,绝对不能为空或是*号,而“日”和“星期” 字段不能同时使用,否则就会发生冲突。
4、将 shell 脚本添加到 PATH
(以便它可以从任何目录运行)
前面使用 ./scripts.sh
来运行脚本;如果省略前导 ./
;./ 代表当前目录
Bash
认为你正在尝试运行名为 scripts.sh
的命令。当你在终端上运行任何命令时,shell
就在存储在 PATH
变量中的一组目录中查找该命令。
若显示权限不足,赋予权限
chmod u+x xxx.sh
问题原因:
由于windows系统下换行符为 \r\n,linux下换行符为 \n,所以导致在windows下编写的文件会比linux下多回车符号 \r。
解决办法:
只需要去掉多余的 \r 回车符 即可**。**操作办法可以用sed命令进行全局替换,
sed 's/\r//' -i scripts.sh
可以使用 echo
查看该 PATH
变量的内容:echo $PATH
冒号字符 (😃 分隔每次运行命令时 shell 扫描的每个目录的路径。
像 echo、cat 等 Linux 命令可以从任何地方运行,因为它们的可执行文件存储在 bin 目录中。bin 目录包含在 PATH 中。当你运行命令时,系统会检查 PATH 以查找它应该寻找的所有可能位置,以找到该命令的可执行文件。
如果你想从任何地方运行你的 bash 脚本,就像它是一个常规的 Linux 命令,需要将你的 shell 脚本的位置添加到 PATH 变量中。
首先,获取脚本目录的位置(假设在同一目录中),使用 PWD 命令:
pwd
使用 export
命令将脚本目录添加到 PATH
变量。
export PATH=$PATH:/scripts
至此我们的脚本学习就结束了
参考文章:https://blog.csdn.net/m0_46278037/article/details/120457468
https://blog.csdn.net/m0_72429728/article/details/127070148
更多推荐
所有评论(0)