shell编程规范与变量

321 阅读9分钟

一.什么是shell?

1.1.1Shell基本概念

  • 将要执行的命令按顺序保存到一个文本文件;

  • 给该文件可执行权限;

  • 可结合各种Shell控制语句以完成更复杂的操作。

1.1.2Shell脚本应用场景

  • 重复性操作

  • 交互性任务

  • 批量事务处理

  • 服务运行状态监控

  • 定时任务执行

1.1.3Shell作用——翻译官 shell是一个特殊的应用程序,它介于操作系统内核和用户之间,充当了一个“命令解释器”的角色,负责接收用户输入的操作指令并进行解释,将需要执行的操作传递给内核执行,并输出执行结果。

shell是用户与linux内核之间的翻译官与解释器

  • 常见的shell解释器

    • bin/bansh
    • bin/sh
    • bin/csh
    • bin/tcsh
  • 解释器负责将用户的指令翻译为内核可以识别的指令

  • 通过usermodchsh可以更改登录shell


  • 使用usermod命令和chsh命令更改用户的shell环境
[root@localhost ~]# useradd test  ##新建测试用户
[root@localhost ~]# grep test /etc/passwd  ##使用grep命令查看test用户的shell环境,可以看到是默认的/bin/bash
test:x:1001:1001::/home/test:/bin/bash
[root@localhost ~]# cat /etc/shells  ##查看我们本机已经安装的shell解释器,可以理解为翻译软件
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
/bin/csh
[root@localhost ~]# yum install -y tcsh  ##可以安装一个
[root@localhost ~]# usermod -s /bin/tcsh test  ##使用usermod命令切换shell登录环境
[root@localhost ~]# grep test /etc/passwd ##看一下是否修改成功
test:x:1001:1001::/home/test:/bin/tcsh

使用chsh命令更改账户的shell环境
[root@localhost ~]# chsh -s /bin/bash test
Changing shell for test.
Shell changed.
[root@localhost ~]#  grep test /etc/passwd
test:x:1001:1001::/home/test:/bin/bash

二.为什么使用bash?

2.1 bash的基本特性

  • 快捷键、TAB键补齐
  • 历史命令(history)
  • 命令别名(aliase)
  • 标准输入与输出的重定向(>、>>、2>、2>>)
  • 管道

2.2管道符|

1.管道操作符:“|”: 将管道符号“|"左侧的命令输出的结果,作为右侧命令的输入(处理对象),同一行命令中可以使用多个管道.

[root@localhost ~]#ps aux |wc -l   #查看进程数
267
[root@localhost ~]#echo "123123"|passwd --stdin zhangsan #给张三设置密码

2.3 标准输入与输出的重定向(>、>>、2>、2>>)

标准输出的含义就是将原本显示在屏幕上通过命令行发聩的信息输出到其他的文件上。下面说一下这四个符合啥意思

1.交互式硬件设备

类型设备文件文件描述编号默认设备
标准输入/dev/stdin0键盘
标准输出/dev/stdout1显示器
标准错误输出/dev/stderr2显示器

2.重定向

类型操作符用途
重定向输入<从指定文件读取数据
重定向输出将标准输出结果保存到指定的文件,并且覆盖原有文件
追加输入>>将标准输出追加到指定的文件的尾部,不覆盖原有内容
标准错误输出2>将错误信息保存到指定文件,并且覆盖原有文件
标准错误输出追加2>>将错误信息追加到指定文件的尾部,不覆盖原有内容
混合输出&>和2>&1将标准输出,标准错误保存到同—文件中

实例

">" 输出实例

[root@localhost ~]# ls > a.txt
[root@localhost ~]#
[root@localhost ~]# cat a.txt
anaconda-ks.cfg
a.txt
initial-setup-ks.cfg
公共
模板
视频
图片
文档
下载
音乐
桌面

image-20220328225437517


混合输出重定向实例

ls /data  /xxx&> hunhe.txt
   正确     错误 & 同时输出到hunhe.txt

重定向输出修改用户密码实例:

将123456重定向输出到pass.txt文件中,然后将pass.txt的内容重定向输入给用户张三的密码,从pass.txt 文件中取密码,需要注意SELinux 会影响此命令执行,若执行失败可尝试关闭SELinux(setenforce 0)。

[root@localhost ~]#useradd juejin
[root@localhost ~]#echo "123abc" > pass.txt
[root@localhost ~]#passwd --stdin lili < pass.txt 
更改用户 juejin 的密码 。
passwd:所有的身份验证令牌已经成功更新。

混合输入方法实例

这里我们用ls命令输出结果到he.txt ,这里注意,root是真是存在的文件夹,也就是1,xxxx是不存在的,也就是2,下面的两种方法可以使用混合输出将正确和错误命令都导入到he.txt中

方法1 基本方法
[root@localhost mnt]# ls root/ xxxx/ &>he.txt
[root@localhost mnt]# cat he.txt
ls: 无法访问xxxx/: 没有那个文件或目录
root/:
[root@localhost mnt]#


方法2
[root@localhost mnt]# ls root/ xxxx/ 1>he.txt  2>&1 
(将2导入1中,再将1导入he.txt中)
[root@localhost mnt]# cat he.txt
ls: 无法访问xxxx/: 没有那个文件或目录
root/:



三.shell编程规范

shell脚本执行方式

#方法一:./ (指定路径的命令,要求文件必须有x权限)
[root@localhost ~]#chmod +x /root/first.sh 
[root@localhost ~]#cd /root/
[root@localhost ~]#./first.sh 
当前目录位于:
/root

#方法二:bash (指定Shell来解释脚本,不要求文件必须有x权限)
[root@localhost ~]#bash first.sh 
当前目录位于:
/root

#方法三:source或. (脚本路径执行shell脚本)
不建议使用,会影响当前bash环境
[root@localhost ~]#source first.sh 
当前目录位于:
/root


脚本错误调试

1.命令错误:命令出错不会影响接下来的命令继续2.语法错误

2.语法错误:会影响接下来的命令继续

3.逻辑错误:只能自己去筛查

  1. bash -n 脚本名称 (如果不在当前目录下加绝对路径) 检查语法错误
  2. bash -x 脚本名称 (如果不在当前目录下加绝对路径) 检查逻辑错误

命名方法

四.变量

变量基础

shell变量的作用

  1. 用来存放系统和用户需要使用的特定参数(值)
  2. 变量名:使用固定的名称,由系统预设或用户定义
  3. 变量值:能够根据用户设置、系统环境的变化而变化

shell变量的类型

  • **自定义变量:**由用户自己定义、修改和使用;

  • 环境变量:由系统定义,用于设置工作环境;

  • 只读变量:值可以读取不可以更改;

  • 未知变量:通过命令行给脚本传递参数

  • 预定义变量:bash中内置的一类变量,不能修改

    Shell定义变量需要遵循的规则

    Shell编程中,使用变量无需事先声明,同时变量名的命名须遵循如下规则:

    1. 首个字符必须为字母(a-z,A-Z)
    2. 中间不能有空格,可以使用下划线(_)
    3. 不能使用标点符号
    4. 不能使用bash里的关键字(可用help命令查看保留关键字)
    自定义变量
    • {} 可以定义变量的范围

    • "" 可以调用变量(强引用)

    • '' 不可以调用变量

    • `` 可以调用命令的结果 (等于$命令)

    • 变量追加(变量名+ =追加值)

    • read -p :从键盘输入的内容编程变量(类似于标准输入输出)

      image-20220330023019911

    {}:用于约定变量的范围

    [root@localhost mnt]# x=centos
    [root@localhost mnt]#
    [root@localhost mnt]# echo $x
    centos
    [root@localhost mnt]# echo $x6.5 (此时如果我想要输出centos.5是无法成功的,因为系统无法识别出符号)
    .5
    [root@localhost mnt]# echo ${x}.5 如果加上{},就可以成功输出.5,{}用于约定变量的范围
    centos.5
    [root@localhost mnt]# 
    
    
    

    '' 单引号

    单引号的应用,只显示引号中文字的本意,不调用自定义变量
    [root@localhost mnt]# x=centos7
    [root@localhost mnt]# echo '$x'
    $x
    
    

    `` 调用命令的结果

    这里如果我们想要调用系统命令hostname
    [root@localhost mnt]# a=hostname  
    [root@localhost mnt]#
    [root@localhost mnt]# echo $a  (正常只会显示结果hostname)
    hostname
    [root@localhost mnt]# hostname (我们想要调用localhost。localdomain)
    localhost.localdomain
    [root@localhost mnt]# a=`hostname` (可以在加上``符号,则可以调用命令的结果
    [root@localhost mnt]# echo $a
    localhost.localdomain
    
    
    ####第二种方法
    [root@localhost mnt]# a=$(hostname) 定义的时候加上$,也是可以的
    [root@localhost mnt]# echo $a
    
    

    read -p (在脚本中可以让用户和机器进行交互)

    实例:

定义变量和调用变量

[root@localhost mnt]#a=11 定义变量a=11
[root@localhost mnt]#echo $a  调用变量,定义变量后,可以反复调用

重新定义变量后,变量改变
[root@localhost mnt]a=22 
[root@localhost mnt]echo $a

特殊的shell变量

环境变量(/etc/profile/文件)

  • 存储在/etc/profile或~/bash_profile
  • 命令enc可以列出所有的环境变量
  • 常见环境变量:PATH, PWD, USER. UID
[root@localhost mnt]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin (系统会以以上文件夹顺序依次寻找变量)

可以通过在/etc/profile/文件的最后添加export PATH=$PATH:/你想添加到环境变量的文件夹,实现脚本自动补全功能

只读变量(readonly)

  • 用于变量值不允许被修改的情况

    [root@localhost ~]# name=cloud
    [root@localhost ~]# readonly name //readonly设置为只读变量
    [root@localhost ~]# echo $name
    cloud
    [root@localhost ~]# name=yun //只读变量不可以被修改了
    -bash: name: 只读变量
    [root@localhost ~]# unset name
    -bash: unset: name: 无法反设定: 只读 variable  //取消只读变量
    [root@localhost ~]#
    

    位置变量(重要)

  • 当执行命令行操作时,第一个字段表示命令名或脚本程序名,其余的字符串参数按照从左到右的顺序依次赋值给位置变量。

  • nn为数字,n:n为数字,0代表命令本身,1~9代表第一个到第九个参数,

    十以上的参数需要使用大括号表示,比如第十个参数为 ${10}

示例

[root@localhost ~]# cat weizhi.sh 
#!/bin/bash
echo $0
echo $1
echo $2

[root@localhost ~]# bash weizhi.sh a b c 位置和脚本中的0 1 2 相对应
weizhi.sh
a
b
[root@localhost ~]#

预定义变量

  • $? 上一次是否成功,0代表成功,不成功非0
  • $* 返回脚本中所有参数 当整体返回
  • $@ 返回脚本中所有参数 当个体返回
  • $0 脚本本身
  • $# 脚本后面跟着的参数总和

五.整数运算

运算符:+ 加法、- 减法、* 乘法、/除法、% 取余

常见表达式

SHELL 中常用的运算命令

(())    用于整数运算
let     用于整数运算,与(())类似 
bc      liunx下的计算器,适合整数及小数运算
expr    用于整数运算,功能相对较多
$[]     用户整数运算

运算方式及运算符号

+,-,*,/,%  #加,减,乘,除,取余
**         #幂运算
++,--     #自增加,自减少
<,<=,>,>=  #小于,小于等于,大于,大于等于
=,+=,-=,*=,/=,%=  #赋值运算,a+=1 相当于 a=a+1

expr和$[]

expr可以直接计算整数,也可以引用变量值计算

[root@localhost ~]# expr 1 + 2 (使用expr命令计算)
3


[root@localhost ~]# a=$[1+2]  (引用变量值计算)
[root@localhost ~]# echo $a
(以看到两种计算结果是一样的)


expr引用自定义变量值进行计算
[root@localhost ~]# a=3
[root@localhost ~]# b=4
[root@localhost ~]# expr $a + $b
7
[root@localhost ~]# expr $a - $b
-1
[root@localhost ~]#
[root@localhost ~]# expr $a \* $b (需要注意,使用乘法运算时需要添加\转义符)
12

$RADOM(随机数)

linux中$random用于生成0—32767的随机数


[root@localhost ~]# echo $RANDOM
29191
[root@localhost ~]# echo $RANDOM
19116
[root@localhost ~]# echo $RANDOM
1375
[root@localhost ~]# echo $RANDOM
20841
[root@localhost ~]# echo $RANDOM
31117
[root@localhost ~]# echo $RANDOM
22327
[root@localhost ~]# echo $RANDOM
21105
[root@localhost ~]# echo $RANDOM
13874

取0-5随机值

[root@localhost ~]# echo $[$RANDOM%6]  

let和(())的应用

let和(())都是应用于整数计算

[root@localhost ~]# c=$((1+2))
[root@localhost ~]# echo $c
3


[root@localhost ~]# let d=1+2
[root@localhost ~]# echo $d
3

let支持++--,使用较多

  • ++i是加后在赋值

  • i++是先赋值后在加

[root@localhost ~]# i=100;let j=++i;echo $i $j   ++i是加后在赋值
101 101
[root@localhost ~]# i=100;let j=i++;echo $i $j
101 100  i++是先赋值后在加

小数运算(| bc)

echo 1.1+2.3 |bc
3.4

补充

seq命令

seq常见命令参数

  • seq命令可以输出连续的数字,或者输出固定间隔的数字,或者输出指定格式的数字,这样说比较模糊,看示例就很容易理解。

常用选项

-s 指定输出的分隔符,默认为\n,即默认为回车换行

-w 指定为定宽输出,不能和-f一起用

-f 按照指定的格式输出,不能和-w一起使用

实例:使用seq从1依次加到100

[root@localhost ~]# seq -s+ 100
1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20+21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+37+  38+39+40+41+42+43+44+45+46+47+48+49+50+51+52+53+54+55+56+57+58+59+60+61+62+63+64+65+66+67+68+69+70+71+  72+73+74+75+76+77+78+79+80+81+82+83+84+85+86+87+88+89+90+91+92+93+94+95+96+97+98+99+100
可以管道符传输给bc
[root@localhost ~]# seq -s+ 100|bc
5050

实例:使用seq命令从1加到100(只用奇数相加)

[root@localhost ~]# seq -s+ 1 2 100
1+3+5+7+9+11+13+15+17+19+21+23+25+27+29+31+33+35+37+39+41+43+45+47+49+51+53+55+57+59+61+63+65+67+69+71+73+75+77+79+81+83+85+87+89+91+93+95+97+99
[root@localhost ~]# seq -s+ 1 2 100|bc
2500