shell编程之步步为营

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/rdgfdd/article/details/82635262

今天呢,我们主要学习shell编程!

  • 首先,我们先了解下:用户是如何与计算机进行交互的?

  • 答案是:终端+附着在终端上的用户接口程序。

用户接口程序主要有两类:GUI 和 CLI

  • GUI :图形化界面,例如 KDE , GNOME , Xfce

  • CLI : 命令行界面,例如 /etc/shells 包括 bash zsh 和 fish

之前呢,我们已经了解过bash的8大特性了,我们补充一点关于bash特性的内容。


bash基础特性9:命令Hash


**命令hash **

bash会缓存已经执行过的外部命令的完整路径,以及命令执行次数,称为命中(hit)次数。
数据格式为:key-value ,其中,key为搜索键,value为值。


hash : 查看hash列表


用法:

# hash
直接使用会列出hash列表

# hash -d COMMAND
从hash表中删除指定命令

# hash -r
清空hash表

示例:

[root@localhost jeffrey]# hash
hits	command
   6	/bin/mktemp
   2	/bin/whoami
   2	/bin/ls
   
[root@localhost jeffrey]# hash -d ls

[root@localhost jeffrey]# hash
hits	command
   6	/bin/mktemp
   2	/bin/whoami
   
[root@localhost jeffrey]# hash -r

[root@localhost jeffrey]# hash
hash: hash table empty


bash基础特性10:变量


首先,叙述一下一些基础知识:

  • 程序=指令+数据

而指令一般都是程序文件中写好的,数据则由“I/O设备,文件,管道和变量”提供。

  • 编程语言类型

编程语言从变量类型上可分为两类:强类型变量编程语言和弱类型变量编程语言。

强类型变量是指变量有非常明显和严格的类型规范和要求;如C语言

弱类型变量是指变量要求没有严格要求,默认情况下均为同一种类型;如bash


接下来,我们来研究一下bash中的变量


bash中的变量特点如下:

1,bash把所有变量统统视作字符型;

2,bash中的变量无需事先声明,声明与赋值同时完成;声明的是:变量类型和变量名。

3,变量替换:把变量名出现的位置,替换为其所指向的内存空间中的值;

4,变量引用:

  • $ (var_name)
  • $ var_name

5,变量命名

  • 命名规则:变量名为字母、数字、下划线的任意组合,但是不能以数字开头,且不能使用关键字;

  • **命名要求 **:见名知义,命名机制遵循某种法则;

6,bash变量类型

  • 本地变量:作用域为当前shell进程;

  • 环境变量:作用域为当前进程及其子进程;

  • 局部变量:作用域为某个代码片段;

  • 位置参数变量:向执行脚本的shell进程传递的参数;

  • 特殊变量:shell内置的有特殊功能的变量;如 $? 保存命令执行的状态结果;

下面我们对以上变量进行详细的介绍:

本地变量

1,赋值

name=value

2,引用

${name}

$name

" " : 双引号,变量名替换为其值;
‘ ’ :单引号,变量名不替换为其值;

3,查看变量列表

# set

4,撤销变量

# unset name
撤销指定变量

我们设计步骤来证明:本地变量作用域对子进程无效:

//首先在当前shell下创建本地变量myname=jeffrey
[root@localhost jeffrey]# myname=jeffrey

//引用一下以验证本地变量myname的值
[root@localhost jeffrey]# echo $myname
jeffrey

//然后,我们打开子shell进程
[root@localhost jeffrey]# bash

//在子进程里,引用变量myname,发现并没有值,说明在子进程中失效;
[root@localhost jeffrey]# echo $myname

环境变量

bash内嵌了许多环境变量(通常全为大写字母),用于定义bash的工作环境;
如:

PATH HISTSIZE HISTFILE HISTFILESIZE HISTCONTROL SHELL HOME UID PWD OLDPWD

1,赋值

方法1:
# export name=value

方法2:
# name=value
# export name

方法3:
# declare -x name=value

方法4:
# name=value
# declare -x name

2,引用

$ {name}

$ name

3,显示环境变量

以下四种均可:

# export

# declare -x

# printenv

# env

4,撤销环境变量

# unset name

5,定义只读变量

方法1
# declare -r name

方法2
# readonly name

只读变量无法重新赋值,并且不能撤销,存活时间为当前shell进程,随shell进程的终止而终止。


bash基础特性11:多命令执行


用法:

# COMMAND1 ; COMMAND2 ; COMMAND3 ;…

逻辑运算:

运算数为:

  • 真(true yes on 1)
  • 假(false no off 0)

运算类型为:

  • 与(&&)

1&&1=1
1&&0=0
0&&0=0
0&&1=0

  • 或(| |)

1| |1=1
1| |0=1
0| |0=0
0| |1=1

  • 非( !)

! 1 = 0
! 0 = 1


短路法则:

# COMMAND1 && COMMAND2

若COMMAND1执行成功,即为真,则COMMAND2必须执行;
若COMMAND1执行失败,即为假,则COMMAND2不会执行;

# COMMAND1 | | COMMAND2

若COMMAND1执行成功,即为真,则COMMAND2不会执行;
若COMMAND1执行失败,即为假,则COMMAND2必须执行;

示例:

[root@localhost jeffrey]# id user
id: user: no such user
[root@localhost jeffrey]# id user || useradd user
id: user: no such user
[root@localhost jeffrey]# id user
uid=1003(user) gid=1004(user) groups=1004(user)

说了这么多,下面正式进入shell脚本编程的环节!

我们先来从不同角度讨论一下编程语言的类型。

1,编程语言分类

  • 根据运行方式:分为 编译运行 和 解释运行

编译运行:编写源代码 —> 编译器编译 —> 可执行程序文件
解释运行:编写源代码 —> 运行时启动解释器,由解释器边解释边运行

  • 根据编程过程中功能的实现是调用库还是外部文件:分为 shell脚本编程 和 完整编程

shell脚本编程:利用系统命令及编程组件进行编程
完整编程:利用库或编程组件进行编程

  • 根据编程摸型(程序=指令+数据):分为 过程式编程语言 和 面向对象的编程语言

过程式编程语言:以指令为中心来组织代码,数据服务于代码;如:C语言,bash
面向对象的编程语言:以数据为中心来组织代码,围绕数据来组织指令;如:Java,C++,Python


shell脚本编程


1,什么是shell脚本编程?

shell脚本编程是一种过程式编程,边解释边运行,依赖于外部程序文件执行;

2,如何编写shell脚本?

因为shell脚本本身就是一个文件,所以直接用文本编辑器编写即可,文本编辑器有两种:行编辑器和全屏编辑器。所谓行编辑器,就是一次编辑一行,而全屏编辑器就是打开后整个界面完全进入编辑状态,比如 nano 和 vim.

  • 脚本文件第一行,顶格,给出shebang,即解释器路径,用于指明解释执行当前脚本的解释器程序文件;

    >常见的解释器
    

#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl

  • shell脚本中以#作为注释符;#后面的内容会被当做注释

  • shell脚本中的空白行会被解释器忽略;

3,shell脚本中的注意事项

shell脚本是命令的堆积;由于许多命令不具有幂等性(幂等性:重复执行命令时返回相同或相似结果),因此要加入判断语句,以避免发生错误。

示例:

//首先我们编写一个脚本,命名为myfirst.sh
//脚本功能为“若用户user不存在,则创建用户user,并修改其密码为"user":内容如下:
#!/bin/bash
#
useradd user
echo "user" | passwd --stdin user

/接下来,我们来实验一下,id user发现之前不存在用户usr
[root@localhost jeffrey]# id user
id: user: no such user

//然后我们执行脚本(脚本执行方式下面会介绍),根据提示信息可知,密码已修改。
[root@localhost jeffrey]# bash myfirst.sh
Changing password for user user.
passwd: all authentication tokens updated successfully.

//接下来,我们测试一下user是否创建成功,结果显示了user的id信息,说明user已经建立;
[root@localhost jeffrey]# id user
uid=1003(user) gid=1004(user) groups=1004(user)

//此时,我们再次执行脚本,看看会有什么情况发生?
[root@localhost jeffrey]# bash mufirst.sh
bash: mufirst.sh: No such file or directory

//结果显示,用户user已经存在,所以,脚本中的useradd命令执行结果是失败的
//提示密码已修改成功,说名命令passwd的执行是成功的。
//像useradd这种多次执行会报错的,就是不具有幂等性的命令
[root@localhost jeffrey]# bash myfirst.sh
useradd: user 'user' already exists
Changing password for user user.
passwd: all authentication tokens updated successfully.

4,脚本的运行方式

我们需要知道的一点是:脚本实在子shell进程中执行的;

方法1:

赋予脚本文件的执行权限,并直接运行此程序文件

chmod +x myfirst.sh
./myfirst.sh

方法2:

将脚本文件以命令行参数传递给解释器程序

bash  myfirst.sh

好吧,光说不练假把式,我们来做个练习吧!

练习:编写脚本已完成下列功能:

  • 找出/etc目录下,以大写或小写p开头的文件或目录
  • 将/var目录下的所有文件名转换为大写后输出的屏幕上

示例:

#!/bin/bash
#
echo "完成功能1:"
ls -d /etc/[pP]*
echo

echo "完成功能2:"
ls -d /var/* | tr a-z A-Z
echo

执行结果:

[root@localhost jeffrey]# bash myfirst.sh
完成功能1:
/etc/PackageKit    /etc/pinforc   /etc/pnm2ppa.conf  /etc/prelink.conf.d  /etc/pulse
/etc/pam.d	   /etc/pkcs11	  /etc/polkit-1      /etc/printcap	  /etc/purple
/etc/passwd	   /etc/pki	  /etc/popt.d	     /etc/profile	  /etc/python
/etc/passwd-	   /etc/plymouth  /etc/postfix	     /etc/profile.d
/etc/pbm2ppa.conf  /etc/pm	  /etc/ppp	     /etc/protocols

完成功能2:
/VAR/ACCOUNT
/VAR/ADM
/VAR/CACHE
/VAR/CRASH
/VAR/DB
/VAR/EMPTY
/VAR/GAMES
/VAR/GOPHER
/VAR/KERBEROS
/VAR/LIB
/VAR/LOCAL
/VAR/LOCK
/VAR/LOG
/VAR/MAIL
/VAR/NIS
/VAR/OPT
/VAR/PRESERVE
/VAR/RUN
/VAR/SPOOL
/VAR/TARGET
/VAR/TMP
/VAR/Y


bash配置文件


在介绍bash的各个配置文件之前,我们先认识一下:shell登录的类型

shell登陆类型可分为以下两种:

  • 交互式登录shell进程

直接通过某终端输入账号和密码后,登录打开的shell进程;
或者使用su - username 或者使用su -l username 执行的登录切换;

  • 非交互式登录shell进程

su username 执行的登录切换;
图形界面下打开的终端;
运行脚本;

了解了shell登录类型,我们就开始介绍bash的配置文件:

bash配置文件可分为以下两种:

  • profile类

为交互式登录的shell进程提供配置

  • bashrc类

为非交互式登录的shell进程提供配置

接着,我们再详细介绍一下这两种bash配置文件。

profile类配置文件

包括全局配置:对所有用户都有效;

/etc / profile
/etc / profile.d / *.sh

用户个人配置:支队当前用户有效;

~ / .bash_profile

profile类配置文件功能:一是用于定义环境变量,二是运行命令或脚本

bashrc类配置文件

包括全局配置:对所有用户都有效;

/ etc / bashrc

用户个人配置:支队当前用户有效;

~ / . bashrc

bashrc类配置文件功能:一是定义本地变量,二是定义命令别名;

注意,只有管理员才有权限修改全局配置文件。

交互式登录的shell进程读取配置文件顺序

/ etc /profile —> / etc / profile . d / * —> ~ / . bash_profile —> ~ / . bashrc —> / etc / bashrc

非交互式登录shell进程,读取配置文件顺序

~/.bashrc —> /etc/bashrc —> /etc/profile.d/*.sh

bash配置文件特性

命令行中定义的配置特性,如变量和命令别名,作用域为当前shell进程;
bash配置文件中定义的配置特性:只对随后新启动的shell进程有效;

那么,问题来了,如何让配置文件中定义的特性立即生效呢?

如何让配置文件中特性立即生效?

方法1:

通过命令行重新定义一次

方法2:

让当前shell进程重读配置文件

方法1:
# source CONF_FILE
方法2:
#.CONF_FILE

下面我们来示例说明:
在.bashrc配置文件中给命令ls设置别名为list

[root@localhost ~]# cat .bashrc
# .bashrc

# User specific aliases and functions

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias list='ls'

# Source global definitions
if [ -f /etc/bashrc ]; then
	. /etc/bashrc
fi
[root@localhost ~]# list
bash: list: command not found...
[root@localhost ~]# source .bashrc
[root@localhost ~]# list
a_c              b_c      Documents             Music            Public
a_d              b_d      Downloads             original-ks.cfg  Templates
anaconda-ks.cfg  Desktop  initial-setup-ks.cfg  Pictures         Videos

猜你喜欢

转载自blog.csdn.net/rdgfdd/article/details/82635262