技术标签: Linux shell编程 运维 Powered by 金山文档 linux 服务器
Shell是Linux上的一个命令解释器。它的作用是解释执行用户输入的命令,然后调用相应的应用程序,命令行中每键入一个命令,Shell就解释执行一条,并将结果展示到命令行窗口中,这种称为交互式的方式。
Shell俗称壳,存在于操作系统的最外层,负责与用户直接对话。把用户的输入解释给操作系统,并将操作系统输出的结果输出给屏幕返回给用户。
Shell脚本就像早期dos年代的.bat,最简单的功能就是将许多指令汇整在一起,让使用者很容易地 就能够一个操作执行多个命令,主要是方便管理员进行设置或者管理用的。但是它比Windows下的批处 理更强大,它提供了数组、循环、条件以及逻辑判断等重要功能,让使用者可以直接以Shell来写程序, 比用其他编程语言编写的程序效率更高,毕竟它使用了Linux/Unix下的命令。
# cat /etc/shells
#查看当前环境下支持的shell
在 Linux 系统中, Shell 脚本(bash Shell 程序) 通常是在编辑器 vi/vim 中编写的,由 UNIX/Linux 命令、 bash Shell 命令、 程序结构控制语句和注释等内容组成。 这里推荐用 Linux 自带的 功能更强的 vim 编辑器来编写, 可以事先做一个别名 alias vi='vim,,并使其永久生效, 这样以后习惯 输人 vi 的读者也就可以直接调用 vim 编辑器了, 设置方法如下:
# echo "alias vi='vim'" >>/etc/profile
# source /etc/profile
脚本文件一般以.sh结尾;一个规范的 Shell 脚本在第一行会指出由哪个程序(解释器) 来执行脚本中的内容,这一行内容在 Linux bash 的编程一般为,:
#!/bin/bash
在Shell脚本中,除了第一行,跟在#后面的内容均为注释内容,注释部分不会当做程序来执行,仅供开发者和使 用者看,注释可以自成一行也可以跟在代码段后面,在我们学习Shell脚本编程时养成注释的好习 惯,方便别人也为了方便自己,例如:
Shell脚本的执行方法有一下几种:
1、bash script_name或者sh script_name,当脚本没有执行权限时,建议使用此种方法执行脚本,默认情况下LInux不允许文件具有执行权限(从安全上来说,这是一件非常好的事情),所以推荐大家使 用这种方法;
2、./script_name 或者/path/to/script_name,在当前路径或者指定路径下执行脚本,这种方法要求脚本具有执行权限。若没有需要我们给脚本文件增加执行权限。
3、source script_name或者. script_name,了解一下就好。
1、指定解释器,通常为
#!/bin/bash
或者
#!/bin/sh
2、增加版本,作者及脚本描述信息等
#Date: 18:00 2018-10-10
#Author: Little Fatty
#Desc: Clean logs
#Version: 1.0
#Email: [email protected]
3、脚本注释尽量减少中文
4、Shell脚本的扩展名以.sh结尾
5、成对的符号应该一次写完,然后退格在括号增加内容。如[ ]、{ }、“ ”、``、‘ ’、等等
6、流程控制语句应该先写将格式写完,再添加内容,避免嵌套增多时遗漏。代码缩进让代码内容更
清晰。
if 条件语句
then
内容
fi
for
do
内容
done
变量为程序或脚本访问内存中的可被修改的一块数据提供 了简单的方式。Linux Shell中的变量可以被指定为任意的数据类型,比如文本字符串或是数值。
# LittleFatty=" I am LittleFatty "
# echo $LittleFatty
变量可分为两类: 环境变量(全局变量) 和普通变量(局部变量)。
环境变量也可称为全局变量, 可以在创建它们的 Shell 及其派生出来的任意子进程Shell 中使用,环 境变量又可分为自定义环境变量和 bash 内置的环境变量。
普通变量也可称为局部变量, 只能在创建它们的 Shell 函数或 Shell 脚本中使用。 普通变量一般由开 发者在开发脚本程序时创建。
# set (输出所有的变量)
# env
# declare
# typeset
如果想要设置环境变量,就需要给变量赋值之后或在设置变量时使用export命令,除了export之外还可以使用declare带-x选项的方法来定义。 我们在当前shell环境定义的变量只在当前环境有效 ; export和declare命令格式如下:
①export 变量名=value
②变量名=value;export 变量名
③declare -x 变量名=value
注:在赋值操作符“=”的周围,不要有任何空格。本地变量定义也需要遵循。
(1)用户的环境变量配置
.bashrc
.bash_profile
(2)全局的环境变量配置 ,所有用户生效;
/etc/profile
/etc/bashrc
/etc/profile.d/
在这三个文件中优先推荐在/etc/bashrc中设置,如果要在登陆后初始化或者显示加载内容,我们可以将写好的脚本文件放在/etc/profile.d/下即可(无需加执行权限) 。
第一种:
# vim /etc/motd
# cat /etc/motd
第二种:
在/etc/profile.d/下增加脚本
# cd /etc/profile.d/
# echo "echo hello world" > login.sh
格式:unset 变量名
# env |grep bbb
# a=123
# echo $a
123
# unset a
# echo $a
#
用户登录系统环境变量文件生效顺序
/etc/profile
/etc/profile.d/
.bash_profile
.bashrc
/etc/bashrc
非交互式登录(不用用户登录)环境变量文件生效顺序 ;
只会加载家目录下.bashrc,/etc/bashrc ;
/etc/bashrc是最后加载的,但也是最先生效的;所以一般定义环境变量定义到这个文件中就可以了。
普通变量也叫局部变量或者本地变量,顾名思义,本地环境变量只在定义它们的本地进程中可见Linux系统中默认定义了标准的本地环境变量。目前来说还没有那个命令只显示出本地变量,我们可以使用set命令显示出所有的变量,其中包括执行env显示的全局环境变量,剩下的变量即为本地变量。
1.本地变量的赋值
变量名=value
变量名='value'
变量名="value"
2.变量名及赋值要求
变量名一般由字母、数字、下划线组成,要能做到见名知义。
变量的值可以用单引号,双引号或者不加引号,三者含义有所不同。
3.变量定义示例
# a=1
# b='2'
# c="3"
# echo $a $b $c
1 2 3
# echo ${a} ${b} ${c}
1 2 3
输出变量时,若加上单引号,如果引号里有变量则该变量不会被替换,例如:
通过上面例子我们来总结一下,三种不同定义方式的结果
第一种定义变量a的方式是不加任何引号,直接定义内容,当内容为简单的连续数字,字符串等时可 以这样用,例如a=1,a=abc等,不加引号,值里有变量时,会被解析出变量值再一同输出。
第二种定义变量b的方式是加了单引号,这种定义的方式的特点是,输出变量的值的时候,引号内的值是什么就输出什么,不会解析,当值中有变量或者命令(命令用反引号)也只会原样输出,这种方式比较适合定义显示纯字符的情况,不希望有解析的场景。
第三种定义变量c的方式是用双引号,这种方式在输出变量的值的时候,会将值中的变量和命令解析后再输出,而不是原样输出,这种方式比较适合希望将变量值中的变量及命令解析出来的场景。加双引号的方式是最常见的定义变量方式。
变量名=`commond` <---此处使用的反引号,Tab键上的符号
变量名=$(commond) <---把命令使用$()括起来
此方式在企业生产场景中很常见,例如以当前日期时间命令的备份压缩等操作。
例如打包备份文件
[root@nebulalinux ~]# echo `date +%F`.tar.gz
2018-11-04.tar.gz
[root@nebulalinux ~]# tar zcf etc_$(date +%F).tar.gz /etc
tar: Removing leading `/' from member names
[root@nebulalinux ~]# ls
etc_2018-11-04.tar.gz
环境变量的一个非常好的特性就是能够当做数组使用,数组是能够保存多个值的变量,数组中的值 既可以分别引用,也可以作为整体引用。
要为某个环境变量设置多个值,只需要将他们列到圆括号内,各个值之间用空格分割
# myvariable=(one two 3 4 5 6 7)
# echo $myvariable
one
显示变量值的时候大家发现并没有将所有的变量值都显示出来,而是只显示了第一个值,要想显示数组的中的值,我们需要使用数值索引号;
echo ${myvariable[1]}
索引的值以0开始,大家要注意,第一个值的索引号是0。
显示整个数值的变量,可以用*号通配
# echo ${myvariable[*]}
one two 3 4 5 6 7
位置变量 |
作用说明 |
$0 |
获取脚本文件名 |
$n |
获取脚本的第n个参数 如果n>9, ${10} |
$# |
获取当前脚本的参数总个数 |
$* |
获取脚本所有传递的参数,把参数当作一个整体字符串,如果不加引号结果与$@相同 |
$@ |
获取脚本所有传递的参数,把参数当作独立的字符串 |
在Shell中存在一些特殊的环境变量,例如 #,#*,我们称为位置参数变量,要给命令,脚本等传递参数时,就需要在Shell脚本中使用位置参数变量;
在执行脚本的时候,脚本后面的值可以当作脚本的参数来执行;
# vi mytest1.sh
#!/bin/bash
echo "当前脚本文件名:$0"
n=1
echo "使用\$@的参数列表为:$@"
echo "总共有$#个参数"
for i in "$@"
do
echo "第$n个参数的值是:$i"
let n+=1
done
# bash mytest1.sh 1 2 3 4 5
# vi mytest2.sh
#!/bin/bash
echo "当前脚本文件名:$0"
n=1
echo "使用\$*的参数列表为:$*"
echo "总共有$#个参数"
for i in "$*"
do
echo "第$n个参数的值是:$i"
let n+=1
done
# bash mytest2.sh 1 2 3 4 5
#vi mytest3.sh
#!/bin/bash
echo "当前脚本文件名:$0"
n=1
echo "使用\$*的参数列表为:$*"
echo "总共有$#个参数"
for i in $*
do
echo "第$n个参数的值是:$i"
let n+=1
done
# bash mytest3.sh 1 2 3 4 5
总结:$@ "$*" $*的区别:
$@将传递的参数看作一个一个的的单个字符串;
"$*"将传递的参数看作是一个整体;
$*和$@一样,将传递的参数看作一个一个的的单个字符串;
变量功能演示 :
[root@nebulalinux ~]# pwd
/root
[root@nebulalinux ~]# echo $?
0 #<---0表示执行成功
[root@nebulalinux ~]# cmd
-bash: cmd: command not found
[root@nebulalinux ~]# echo $?
127 #<---127表示命令执行失败
[root@nebulalinux ~]# echo $$
21457 #<---显示当前shell进程号
[root@nebulalinux ~]# top & #<-----在后台执行
[1] 21475
[root@nebulalinux ~]# echo $!
21475 #<---显示上一个后台工作的进程的进程号
[1]+ Stopped top
[root@nebulalinux ~]# ls -ld /root/
dr-xr-x---. 2 root root 4096 Oct 12 05:36 /root/
[root@nebulalinux ~]# echo $_
/root/ #<---获取上个命令的最后一个参数
[root@nebulalinux ~]#
Shell中包含了一些内置命令,如echo,printf,export,read,shift等 ;
1.echo命令用于在屏幕上输出数据,常用选项有:
[root@nebulalinux ~]# echo hello;echo world
hello
world
[root@nebulalinux ~]# echo -n hello;echo world
helloworld
[root@nebulalinux ~]# echo "hello\tworld\nhello\tworld"
hello\tworld\nhello\tworld
[root@nebulalinux ~]# echo -e "hello\tworld\nhello\tworld"
hello world
hello world
[root@nebulalinux ~]# echo -e "hello\vworld\vhello\vworld"
hello
world
hello
world
[root@nebulalinux ~]# echo -e "hello \bworld"
helloworld
#printf功能和echo类似
2.exec命令
exec命令可以在不创建子进程的情况下去执行指定命令,并在命令执行结束后进程终止;
[root@nebulalinux ~]# su - nebula
hello world
[nebula@nebulalinux ~]$ exec date
Sun Nov 4 13:16:24 EST 2018
[root@nebulalinux ~]#
3.read命令
从标准输入中读取字符串信息,传给Shell内部定义的变量;
语法格式:read [选项] 变量名
选项:
-t:等待时间,
-p:设置提示信息
[root@nebulalinux ~]# read -t 10 -p "please input one number: " num
please input one number: 1
[root@nebulalinux ~]# echo $num
1
4.shift命令
shift语句会重新命名所有的位置参数;每使用一次shift,所有位置参数依次向左诺一位,并且位置参数$#会减一。
表达式 |
说明 |
${parameter:-word} |
如果parameter的变量值为空或者未赋值,则会返回word字符串代替变 量值 |
${parameter:=word} |
如果parameter的变量值为空或者未赋值,则设置这个变量值为word, 返回值也是word |
${parameter:?word} |
如果parameter的变量值为空或者未赋值,那么word字符串会被当做标 准错误输出,否则输出变量的值 |
${parameter:+word} |
如果parameter的变量值为空或者未赋值,则输出空值,否则word字 符串将被替代变量的值 |
[root@nebulalinux03 ~]# echo $test #变量未设置输出为空
[root@nebulalinux03 ~]# res=${test:-unset} #使用特殊变量
[root@nebulalinux03 ~]# echo $res 打印res,返回unset
unset
[root@nebulalinux03 ~]#
#当变量test没有定义值时,就返回变量结尾设置的unset字符串
#可以用来判断变量是否已定义
[root@nebulalinux03 ~]# unset res
[root@nebulalinux03 ~]# echo $res
[root@nebulalinux03 ~]# unset test
[root@nebulalinux03 ~]# echo $test
[root@nebulalinux03 ~]# res=${test:=unset}
[root@nebulalinux03 ~]# echo $res
unset
[root@nebulalinux03 ~]# echo $test
unset
#test原本没有定义,现在已经被赋值unset
[root@nebulalinux03 ~]#
#当变量res值中的变量test值没有定义时,会给变量res赋值“:=”后面的值,同时会把“:=”后面的值赋
值给变量test
#可以用来解决变量没有定义的问题,并确保没有定义的变量的始终有值
[root@nebulalinux03 ~]# unset test
[root@nebulalinux03 ~]# echo ${test:? not defined}
-bash: test: not defined
[root@nebulalinux03 ~]# echo ${test? not defined}
-bash: test: not defined
[root@nebulalinux03 ~]# test=hello
[root@nebulalinux03 ~]# echo ${test:? not defined}
hello
[root@nebulalinux03 ~]# echo ${test? not defined}
hello
[root@nebulalinux03 ~]# unset test
[root@nebulalinux03 ~]# echo ${test? not defined}
-bash: test: not defined
[root@nebulalinux03 ~]#
#用来设定由于由于变量未定义而报错的内容
[root@nebulalinux03 ~]# res=${test:+replace}
[root@nebulalinux03 ~]# echo $res
[root@nebulalinux03 ~]# test=hello
[root@nebulalinux03 ~]# res=${test:+replace}
[root@nebulalinux03 ~]# echo $res
replace
[root@nebulalinux03 ~]#
#测试变量是否存在,如果变量值为replace,则证明变量test有值
文章浏览阅读1.1k次。docker启动redis命令_linux docker 重启 redis
文章浏览阅读325次。插头DP小结_dp插头模型
文章浏览阅读3.5k次。关于测试工作效率低的一些思考和改进方法引子 汇总统计了一下项目组近期测试项目实际工作量与基线工作量的对比,发现一个严重问题。就是工作效率特别低下。下面简单列举一下几个项目预期工作量和实际工作量以及时间耗费严重的地方、项目简要背景。 1、B版本测试。版本预期工作量15人天,实际耗费工作量在30人天。更为严重的是测试人员并没有因为测试周期延长和工作量投入加大而测试的更轻松,反而是测试期..._测试人员不足与改进
文章浏览阅读173次。级联样式表 CSS-难以成熟 (CSS — Difficult to maturation)Unlike software, the CSS specifications are developed by successive versions, which would allow a browser to refer to a particular version. CSS was devel..._级联样式表是哪年产生的
文章浏览阅读1.7k次。目录批处理语句1、批处理语句简介示例一:示例二:存储过程一、什么是存储过程1、存储过程的简介2、存储过程包含的内容3、存储过程的优点4、存储过程的分类系统存储过程:用户定义存储过程5、常用的系统储存过程(1)一般常用的存储过程(2)xp_cmdshell二、创建存储过程1、定义存储过程的语法2、不带参数的存储过程3、带参数..._sql的批处理
上次,我们解除了css的内外边距、鼠标悬停及其练习。现在我们学习css元素练习和定位。
文章浏览阅读7.6k次。在Android中我们可以用visibility来控制控件的显示和隐藏,那在Flutter中我们怎么控制呢?其实,在Flutter中控制Widget显示和隐藏有3中方法:不过3种方法的核心思想都是根据变量的值去判断的,所以先定义一个变量:bool visible = true;变量的值可以在事件中去控制,比如: onPressed: () { setS..._flutter判断控制是否被遮住
文章浏览阅读673次。有没有师兄师姐有meganv2.04以上的版本小弟只有低版本的 需要高版本运行一下有偿!_megan v2.04
文章浏览阅读32次。springboot基于springboot的小型超市库存管理系统。springboot基于SpringBoot的校园失物招领系统。springboot基于springboot的残障人士社交平台。springboot基于springboot的酒店管理系统。springboot基于springboot的电商购物系统。springboot基于微信小程序的Sunmoon口红商城。springboot基于云平台的便民物流速递信息管理系统。springboot基于微服务的固定资产管理系统。
文章浏览阅读3.1k次。还在用PPT、Word和Excel画企业组织结构图吗?对于人力资源的同事来说,画组织结构图是一键非常头疼的事情,尤其是对于一些大公司和人员变动较大的公司来说,需要经常更换组织结构图,每次变动都要耗费大量的时间和精力去重新绘图。其实绘制织结构图很简单,之所以难是因为没有找对工具和方法!今天小编就教你如何用亿图图示轻松绘制一个既美观又专业的组织结构图!下图是一个简单的组织结构图例子,小编就以此为例,详细讲解一下好看清晰、实用的公司组织结构图是怎么画出来的。1、新建组织结构图2、创建组织结构_书本里印刷的结构图是用什么软件做的
文章浏览阅读1.8k次,点赞4次,收藏5次。BLE5.0 扩展蓝牙名称长度_蓝牙广播名称过长
文章浏览阅读3.5k次。centos8安装NVIDIA显卡驱动,docker模式运行机器学习_centos8安装显卡驱动