赞
踩
学习shell语法之前最好拥有一些linux基础知识,掌握一定的linux命令。
在hello.sh中编写shell程序:
#!/bin/bash
# first command
echo hello world!
cat ~/hello.txt
其中hello.txt的文件内容为:
Hello world!1 Helao world!2 Hello world!3 Hello world!4 Hello world!5 Hello world!6 abc!7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
这时,如果我们直接执行hello.sh文件,则报错:-bash: ./hello.sh: Permission denied
,原因是文件没有执行权限,此时执行chmod u+x hello.sh
赋予权限,如下:
[root@bigData01 test]# ./hello.sh
-bash: ./hello.sh: Permission denied
[root@bigData01 test]# chmod u+x ./hello.sh
[root@bigData01 test]# ./hello.sh
hello world!
Hello world!1
Helao world!2
Hello world!3
Hello world!4
Hello world!5
Hello world!6
abc!7
其实也可以通过bash ./hello.sh
或sh ./hello.sh
执行文件,因为在执行的时候前面指定bash
或者sh
,表示把hello.sh这个脚本中的内容作为参数直接传给了bash或者sh命令来执行,所以这个脚本有没有执行权限都无所谓了。
shell中的变量不需要声明,初始化也不需要指定类型,shell是一门弱类型的语言。shell中变量的命名要求:只能使用数字、字母和下划线,且不能以数字开头。
变量赋值是通过"="进行赋值,在变量、等号和值之间不能出现空格!如下:(执行成功是没有反馈的,只有执行错误的报错)
[root@bigData01 test]# name=cql
[root@bigData01 test]# name= cql
bash: cql: command not found...
[root@bigData01 test]# name =cql
bash: name: command not found...
[root@bigData01 test]# name_=cql
[root@bigData01 test]# name2_=cql
[root@bigData01 test]# 1name2_=cql
bash: 1name2_=cql: command not found...
[root@bigData01 test]# 1name2$=cql
bash: 1name2$=cql: command not found...
输出变量时使用echo
命令,参数格式为echo $<变量名>
,例如输出name
变量内容,就可以使用echo $name
命令,但如果要在变量内容后面无缝链接另一个字符串haha
,则需要使用命令echo ${name}haha
。如下:
[root@bigData01 test]# echo $name
cql
[root@bigData01 test]# echo ${name}
cql
[root@bigData01 test]# echo ${name}haha
cqlhaha
[root@bigData01 test]# echo $name haha
cql haha
本地变量的格式是VAR_NAME=VALUE
,其实就是我们刚才在shell中那样直接定义的变量,这种变量一般用于在shell脚本中定义一些临时变量,只对当前shell进程有效,关闭shell进程之后就消失了,对当前shell进程的子进程和其它shell进程无效。
举个例子就可以证明上述描述,在当前shell进程下定义本地变量name=cql
,然后在其他进程和当前进程的子进程中分别输出该变量,若变量不存在则可以证明。如下:
首先在当前进程定义本地变量,输出正常:
[root@bigData01 test]# name=cql
[root@bigData01 test]# echo $name
cql
在另一个新的shell进程中输出该变量内容,输出为空:
[root@bigData01 ~]# cd "/test"
[root@bigData01 test]# echo $name
进入当前shell进程的子进程中输出该变量内容,输出为空:
[root@bigData01 test]# bash
[root@bigData01 test]# echo $name
[root@bigData01 test]# exit
exit
环境变量的定义格式为:export VAR_NAME=VALUE
,环境变量的这种格式主要用于设置临时环境变量,当你关闭当前shell进程之后环境变量就消失了,对子shell进程有效,对其它shell进程无效。如下:
[root@bigData01 test]# export age=18
[root@bigData01 test]# echo $age
18
[root@bigData01 test]# bash
[root@bigData01 test]# echo $name
[root@bigData01 test]# exit
exit
若要环境变量永久生效,就将export VAR_NAME=VALUE
写入/etc/profile文件中,并执行source /etc/profile
加载文件中的命令。
用于接收给shell脚本传递的参数,类似与$1、$2、$3等等。举一个浅显易懂的例子:
首先,编写hello.sh文件内容为:
#!/bin/bash
echo $0
echo $1
echo $2
echo $3
执行shell脚本:
[root@bigData01 test]# hello.sh a b c d
./hello.sh
a
b
c
发现$0表示当前文件的名称,$1表示脚本后的第一个参数,$2表示脚本后的第二个参数,等等。理论上来说,脚本后面有多少个参数,在脚本中就可以通过$和角标获取对应参数的值。
$# 是传给脚本的参数个数
$@ 是传给脚本的所有参数的列表
$* 是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个
$$ 是脚本运行的当前进程ID号
$? 是显示最后命令的退出状态,0表示没有错误,其他表示有错误
shell脚本为:
#!/bin/bash
echo $0
echo $#
echo $@
echo $$
echo $?
执行结果如下:
[root@bigData01 test]# hello.sh a b c
./hello.sh
3
a b c
5346
0
输出时不解析单引号中的变量,如下:
[root@bigData01 test]# echo $name
cql
[root@bigData01 test]# echo '$name'
$name
输出时解析双引号中的变量,如下:
[root@bigData01 test]# echo $name
cql
[root@bigData01 test]# echo "$name"
cql
输出时解析单引号中的变量并执行,如下:
反引号与
$()
的效果一致。
[root@bigData01 /]# name=pwd
[root@bigData01 /]# echo $name
pwd
[root@bigData01 test]# echo `$name`
/test
[root@bigData01 test]# echo $($name)
/test
for((exp1; exp2; exp3))
do
statements
done
例如:
数学算式要用(())括住。
[root@bigData01 test]# cat hello.sh
#!/bin/bash
for((i=0;i<10;i++))
do
((sum+=i))
done
echo $sum
[root@bigData01 test]# hello.sh
45
for variable in value_list
do
statements
done
例如:
[root@bigData01 test]# cat hello.sh #!/bin/bash # first for i in 1 2 3 4 5 6 7 8 9 do ((sum+=i)) done echo $sum sum=0 # second for i in {1..9} do ((sum+=i)) done echo $sum sum=0 #third for i in `seq 1 1 9` do ((sum+=i)) done echo $sum [root@bigData01 test]# hello.sh 45 45 45
while循环格式为:
while condition
do
statements
done
例如:
[root@bigData01 test]# cat while.sh
#!/bin/bash
i=1
sum=0
while ((i <= 100))
do
((sum += i))
((i++))
done
echo "The sum is: $sum"
[root@bigData01 test]# while.sh
The sum is: 5050
if判断分为三个类型:单分支、双分支、多分支。
它的语法格式为:
if condition
then
statement(s)
fi
例如:
[root@bigData01 test]# cat if.sh
#!/bin/bash
read a
read b
if (( $a == $b ))
then
echo "a和b相等"
fi
[root@bigData01 test]# bash if.sh
12
12
a和b相等
它的语法格式为:
if condition
then
statement1
else
statement2
fi
例如:
[root@bigData01 test]# cat if.sh
#!/bin/bash
read a
read b
if (( $a == $b ))
then
echo "a和b相等"
else
echo "a和b不相等,输入错误"
fi
[root@bigData01 test]# bash if.sh
12
13
a和b不相等,输入错误
它的语法格式为:
if condition1
then
statement1
elif condition2
then
statement2
elif condition3
then
statement3
······
else
statementn
fi
例如:
[root@bigData01 test]# cat if.sh #!/bin/bash printf "Input integer number: " read num if ((num==1)); then echo "Monday" elif ((num==2)); then echo "Tuesday" elif ((num==3)); then echo "Wednesday" elif ((num==4)); then echo "Thursday" elif ((num==5)); then echo "Friday" elif ((num==6)); then echo "Saturday" elif ((num==7)); then echo "Sunday" else echo "error" fi [root@bigData01 test]# bash if.sh Input integer number: 5 Friday
若需要在后台执行shell脚本,则需要在命令后加&
字符,例如sh while2.sh &
。
但这样操作,当关闭shell窗口后文件将停止运行,因此若要使该程序永久在后台运行,则使用nohup
命令,如下:
[root@bigData01 test]# cat while.sh #!/bin/bash while ((1>0)) do # echo "yes" sleep 1 done [root@bigData01 test]# while.sh ^C [root@bigData01 test]# while.sh & [1] 2700 [root@bigData01 test]# ps -ef | grep while.sh root 2700 2612 0 10:45 pts/1 00:00:00 /bin/bash ./while.sh root 2709 2612 0 10:45 pts/1 00:00:00 grep --color=auto while.sh [root@bigData01 test]# kill 2700 [root@bigData01 test]# ps -ef | grep while.sh root 2717 2612 0 10:45 pts/1 00:00:00 grep --color=auto while.sh [1]+ Terminated while.sh [root@bigData01 test]# nohup while.sh & [1] 2727 [root@bigData01 test]# nohup: ignoring input and appending output to ‘nohup.out’ [root@bigData01 test]# ll total 12 -rwxr--r--. 1 root root 199 Jan 16 21:53 hello.sh -rw-r--r--. 1 root root 364 Jan 16 22:50 if.sh -rw-------. 1 root root 0 Jan 17 10:45 nohup.out -rwxr--r--. 1 root root 55 Jan 17 10:44 while.sh [root@bigData01 test]# kill 2727
nohup
命令下在后台运行的脚本只能先使用ps -ef | grep <关键字>
查询pid,然后通过kill
命令去终止。
标准输出:表示是命令或者程序输出的正常信息。
标准错误输出:表示是命令或者程序输出的错误信息。
重定向就是将标准输出导向一个文件或者追加到一个文件中。
其中,标准输出可以使用文件描述符1来表示,标准错误输出可以使用文件描述符2来表示。针对标准输出和标准错误输出,可以使用重定向操作将这些输出信息保存到文件中。
例如:
ll 1>a.txt
表示将ll
命令的标准输出重定向到a.txt文件中,其中>
在重定向时会覆盖文件原有内容,>>
表示会追加到原有内容之后。ll 1>a.txt
的1
可以省略,因为默认情况下不写也是1
。
lk
是一个不存在的错误命令,lk 2>b.txt
表示会将lk
命令的标准错误输出重定向到b.txt中。
[root@bigData01 test]# ll 1>a.txt [root@bigData01 test]# cat a.txt total 12 -rw-r--r--. 1 root root 0 Jan 17 10:59 a.txt -rwxr--r--. 1 root root 199 Jan 16 21:53 hello.sh -rw-r--r--. 1 root root 364 Jan 16 22:50 if.sh -rw-------. 1 root root 0 Jan 17 10:45 nohup.out -rwxr--r--. 1 root root 55 Jan 17 10:44 while.sh [root@bigData01 test]# ll 1>>a.txt [root@bigData01 test]# cat a.txt total 12 -rw-r--r--. 1 root root 0 Jan 17 10:59 a.txt -rwxr--r--. 1 root root 199 Jan 16 21:53 hello.sh -rw-r--r--. 1 root root 364 Jan 16 22:50 if.sh -rw-------. 1 root root 0 Jan 17 10:45 nohup.out -rwxr--r--. 1 root root 55 Jan 17 10:44 while.sh total 16 -rw-r--r--. 1 root root 254 Jan 17 10:59 a.txt -rwxr--r--. 1 root root 199 Jan 16 21:53 hello.sh -rw-r--r--. 1 root root 364 Jan 16 22:50 if.sh -rw-------. 1 root root 0 Jan 17 10:45 nohup.out -rwxr--r--. 1 root root 55 Jan 17 10:44 while.sh [root@bigData01 test]# lk bash: lk: command not found... [root@bigData01 test]# lk 2>b.txt [root@bigData01 test]# cat b.txt bash: lk: command not found...
最后再看一个综合案例:
nohup hello.sh >/dev/null 2>&1 &
这条命令中各部分的含义:
nohup和&:可以让程序一直在后台运行
/dev/null:是linux中的黑洞,任何数据扔进去都找不到了
/dev/null:把标准输出重定向到黑洞中,表示脚本的输出信息不需要存储
2>&1 :表示是把标准错误输出重定向到标准输出中
因此这条命令的意思是把脚本放在后台一直运行,并且把所有输出都扔到黑洞里面。
crontab
服务状态:[root@bigData01 test]# systemctl status crond
crond.service - Command Scheduler
Loaded: loaded (/usr/lib/systemd/system/crond.service; enabled)
Active: active (running) since Tue 2023-01-17 10:38:35 CST; 1h 37min ago
Main PID: 830 (crond)
CGroup: /system.slice/crond.service
└─830 /usr/sbin/crond -n
Jan 17 10:38:35 bigData01 systemd[1]: Started Command Scheduler.
Jan 17 10:38:36 bigData01 crond[830]: (CRON) INFO (RANDOM_DELAY will be scaled with factor 2% if used.)
Jan 17 10:38:37 bigData01 crond[830]: (CRON) INFO (running with inotify support)
看到里面的active(running)
说明这个服务是启动的,如果服务没有启动可以使用systemctl start crond
来启动,如果想要停止可以使用systemctl stop cron
。
crontab -l
,如下:[root@bigData01 test]# crontab -l
no crontab for root
crontab -e
,随后会进入一个定时任务配置文件,在文件中按照格式输入命令即可。写入文件后保存退出即可,若要取消该定时任务则需进入文件将命令行删除。
crontab
的命令格式为:
* * * * * <username> <command>
这五个*
分别表示分钟(0~59)、小时(0~23)、日期(1~31)、月份(1~12)、星期数(0~6),如果哪一项要求每个该时间点都要执行,那么就将该项数据置为*
,否则改为间隔时间数据。例如:
每小时的第3分钟执行一次a.sh脚本文件(文件地址最好写为绝对地址):
7 * * * * sh /test/a.sh
每天3点执行一次a.sh脚本文件:
0 3 * * * sh /test/a.sh
每天18点30分执行一次a.sh脚本文件:
30 18 * * * sh /test/a.sh
每个月的1号的12点15分执行一次a.sh脚本文件:
15 12 1 * * sh /test/a.sh
每年的3月1号的11点45分执行一次a.sh脚本文件:
45 11 1 3 * sh /test/a.sh
每周三的16点30分执行一次a.sh脚本文件:
30 16 * * 3 sh /test/a.sh
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。