1.bash特性及bash脚本编程初步
终端:附着在终端的接口程序
- GUI: KDE, GNome, Xfce
- CLI: /etc/shells
bash的特性:
-
命令行展开: ~, {}
-
命令别名:alias, unlias
-
命令历史:history
-
文件名通配:glob
-
快捷键: Ctrl + a, e, u, k, l
-
命令补全: $PATH
-
路径补全
1.bash特性之:命令哈希hash
缓存此前命令查找的结果: key-value
key: 搜索键
value:值
hash命令:
hash:列出
hash -d COMMAND: 删除
hash -r : 清空
[lemon@VM-4-10-centos ~]$ help hash
hash: hash [-lr] [-p 路径名] [-dt] [名称 ...]
记住或显示程序位置。
确定并记住每一个给定 NAME 名称的命令的完整路径。如果
不提供参数,则显示已经记住的命令的信息。
选项:
-d 忘记每一个已经记住的命令的位置 # 删除指定值
-l 以可作为输入重用的格式显示
-p pathname 使用 pathname 路径作为 NAME 命令的全路径
-r 忘记所有记住的位置 # 清空哈希表
-t 打印记住的每一个 NAME 名称的位置,如果指定了多个
NAME 名称,则每个位置前面会加上相应的 NAME 名称
参数:
NAME 每个 NAME 名称会在 $PATH 路径变量中被搜索,并
且添加到记住的命令的列表中。
退出状态:
返回成功,除非 NAME 命令没有找到或者使用了无效的选项。
测试:
[rhino@rhino010 lxc]$ rm -rf test
[rhino@rhino010 lxc]$ mkdir test
[rhino@rhino010 lxc]$ hash
hits command
1 /usr/bin/tty
1 /usr/bin/install
1 /usr/sbin/ifconfig
2 /usr/bin/rm
1 /usr/bin/who
3 /usr/bin/mkdir
1 /usr/bin/ls
[rhino@rhino010 lxc]$ hash -d ls
[rhino@rhino010 lxc]$ hash
hits command
1 /usr/bin/tty
1 /usr/bin/install
1 /usr/sbin/ifconfig
2 /usr/bin/rm
1 /usr/bin/who
3 /usr/bin/mkdir
[rhino@rhino010 lxc]$ hash -r
[rhino@rhino010 lxc]$ hash
hash: hash table empty
2.bash特性之:变量
-
程序:指令+数据
-
指令:由程序文件提供
-
数据:IO设备(通过键盘输入等)、文件、管道
-
-
程序:算法+数据结构
-
变量赋值:name=value
-
变量类型(数据类型):存储格式、表示数据范围、参与的运算
- 编程语言:
- 强类型变量: C语言等
- 弱类型变量:bash
- bash把所有变量统统视作字符型
- bash中的变量无需事先声明,相当于把声明和复制过程同时实现(python也无需声明,但还是算强类型变量,毕竟不能执行
1+'2')
-
变量替换:把变量名出现的位置转换为其所指向的内存空间中数据的过程
-
变量引用:
${var_name}, $var_name -
变量名命名方式:所有编程语言变量命名基本上规范一致,只能包含数字、字母、下划线,不能以数字开头
-
bash变量类型:
- 本地变量:作用域仅为当前shell进程
- 环境变量:作用域为当前shell进程及其子进程(再键入一次
bash则进入子shell进程,新开的终端是不行的,可以who查看终端情况) - 局部变量:作用域仅为某代码片段(函数上下文)
- 未知参数变量:就是向执行脚本shell进程传递的参数
- 特殊变量:通常是shell内置的有特殊公用的变量
-
$?保存上一个命令的执行状态结果(0表示成功,1-255表示失败)
-
bash变量赋值方式:
-
本地变量赋值:
name=value -
变量引用:
${name}, $name-
"":变量名会替换为其值 -
'':变量名不会替换为其值
-
-
查看变量:
set -
撤销变量:
unset name注意,此处非变量引用 -
环境变量:
-
变量赋值(四种方式):
-
export name=value -
name = value export name -
declare -x name=value -
name=value declare -x name
-
-
变量引用:
${name}, $name,注意,bash内嵌了许多环境变量(通常为全大写字符,如PATH, HISTFILE,HISTZISE,HISTFILESIZE,HISTCONTROL,SHELL,HOME,UID,OWD,OLDPWD),用于定义bash的工作环境 -
查看环境变量
printenvdeclare -xenvexport
-
撤销环境变量:
unset name -
只读变量:无法重新赋值,并且不支持撤销:存活时间为当前shell进程的生命周期,岁shell进程终止而终止
-
declare -r name -
readonly name
-
3. bash特性之:多命令执行
-
~]# COMMAND1; COMMAND2; COMMAND3; -
逻辑运算:
-
运算数:
-
真(
true, yes, on, 1) -
假(false, no, off, 0)
-
与:
&&可用于乘法
1 && 1 = 1 0 && 1 = 0 0 && 0 = 0 1 && 0 = 0- 或:
||
1 || 1 = 1 0 || 1 = 1 0 || 0 = 0 1 || 0 = 1- 非:
!
!1 = 0 !0 = 1- 异或:
-
-
短路法则:
~]# COMMAND1 && COMMAND2
COMMAND1为假,则COMMAND2不会再执行;否则必须执行
~]# COMMAND1 || COMMAND2
COMMAND1为真,则COMMAND2不会再执行;否则必须执行
- 示例:查看某用户id,如果查看失败(即不存在该用户),那么创建之
~]# id $username || useradd $username
2.shell脚本编程
1.概述
编程语言的分类:根据运行方式
- 编译运行:源代码 --> 编译器 ( 编译)-> 程序文件;
- 解释运行:源代码 -> 运行时启动解释器,由解释器边解释边运行
根据其编程过程中功能的实现是调用库还是调用外部的程序文件:
- shell脚本编程:利用系统上的命令及编程组件进行编程;
- 完整编程:利用库或给程组件进行编程:
编程模型:过程式编程语言,面向对象的编程语言
-
过程式:以指令为中心来组织代码,数据是服务于代码;
顺序执行、选择执行、循环执行 ... ...
代表:C,bash
-
对象式:以数据为中心来组织代码,围绕数据来组织指令;
- 类(class):实例化对象,method;
代表: Java,C++,Python
shell脚本编程:过程式编程,解释运行,依赖于外部程序文件运行;
shell脚本是什么:命令的堆砌,自上而下执行;但由于很多命令不具有幂等性,需要用程序逻辑来判断运行条件是否满足,以避免其运行中发生错误。
2.如何编写
脚本文件的第一行,顶格:给出shebang,解释器路径,用于指明解释执行当前脚本的解释器程序文件
常见的解释器:
#!/bin/bash#!/usr/bin/python#!/usr/bin/perl
文本编辑器:nano
行编辑器:sed
全屏幕编辑器:nano, vi, vim
尝试用nano编写一个shell脚本:
nano myfirst.sh
看见大概长这样:

使用Ctrl+X退出,Ctrl+O写入
执行:
[root@VM-4-10-centos ~]# sh myfirst.sh
更改用户 user3 的密码 。
passwd:所有的身份验证令牌已经成功更新。
/tmp/test.uFOOSC
# 或者使用路径,./myfirst.sh, /root/myfirst.sh, bash myfirst.sh
刚刚的shell脚本中,如果再次执行,创建会失败,但是后两步并不会终止
如果想要判断用户存在,若存在则不再创建,只执行后续的改密码等操作,可以使用||与,COMMAND1成功则不再执行COMMAND2
#!/bin/bash
# 添加用户并设置密码
id user3 || useradd user3
echo "user3" | passwd --stdin user3
mktemp -d /tmp/test.XXXXXX
[root@VM-4-10-centos ~]# sh myfirst.sh
uid=1005(user3) gid=1005(user3) 组=1005(user3)
更改用户 user3 的密码 。
passwd:所有的身份验证令牌已经成功更新。
/tmp/test.t6oD2U
3.执行脚本的方法
-
赋予执行权限,并直接运行此程序文件:
chmod +x /PATH/TO/SCRIPT_FILE /PATH/TO/SCRIPT_FILE -
直接运行解释器,将脚本以命令行参数传递给解释器程序
bash /PATH/TO/SCRIPT_FILE sh /PATH/TO/SCRIPT_FILE
4.简单练习
练习1:显示/etc目录下所有以大写P或者小写p开头的文件或目录本身;
#!/bin/bash
ll /etc/P* # 大写
ll /etc/p* # 小写
ll /etc/[Pp]* # 不区分大小写
练习2:显示/var目录下的所有文件或者目录本身,并将显示结果中的小写字母转换为大写后显示;
#!/bin/bash
ls -d /var/* | tr 'z-z' 'A-Z'
练习3:创建临时文件/tem/myfile.XXXX;
#!/bin/bash
mkdir /tem/myfile.XXXX
综合
#!/bin/bash
echo "Show some under /etc"
ls -d /etc/[pP]*
echo "Traslate lower to upper"
ls -d /var/*tr 'a-z''A-Z'
echo "Create a temp file"
mktemp /tmp/myfile.XXXX
5.bash的配置文件
1. 配置文件类型
配置文件主要分为两类:
profile类:为交互式登录的shelli进程提供配置
bashrc类:为非交互式登录的shelli进程提供配置
登录类型:
-
交互式登录shelli进程:
直接通过某终端输入账号和密码后登录打开的shelli进程:
使用su命令:Su - USERNAME,或者使用su -I USERNAME执行的登录切换: -
非交互式登录shel进程
su USERNAME执行的登录切换:
图形界面下打开的终端:
运行脚本
profile类:
-
全局:对所有用户生效
/etc/profile /etc/profild.d/*.sh -
用户个人:仅对当前用户有效
~/.bash_profile -
功用:
- 用于定义环境变量
- 运行命令或脚本
bashrc类:
-
全局:
/etc/bashrc -
用户个人:
~/.bashrc -
功用:
- 定义本地变量
- 定义命令别名
注意:仅管理员可修改全局配置文件
2.shell读取配置顺序
- 交互式登录shell进程:
/etc/profile-->/etc/profile.d/*-->~/.bash_profile ->~/.bashrc-->/etc/bashrc - 非交互式登录shell:进程:
-/.bashrc-->/etc/bashrc-->/etc/profile.d/*
命令行中定义的特性,例如变量和别名作用域为当前shl进程的生命周期;
配置文件定义的特性,只对随后新启动的shell进程有效:
让通过配置文件定义的特性立即生效:
-
通过命令行重复定义一次:
-
让shelli进程重读配置文件:
source /PATH/FROM/CONF_FILE /PATH/FROM/CONF_FILE
3.实验
别名测试:将clear写到配置文件中别名为cls
直接敲cls是无该命令的ll,将clear别名成cls
[lemon@VM-4-10-centos ~]$ cls
-bash: cls: 未找到命令
[lemon@VM-4-10-centos ~]$ vim .bashrc
添加alias cls=clear:
[lemon@VM-4-10-centos ~]$ cat .bashrc
# .bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
export WORKON_HOME=$HOME/.virtualenvs
source /home/lemon/.local/bin/virtualenvwrapper.sh
alias cls=clear
# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=
# User specific aliases and functions
再执行cls,就OK了。实测有效,但是root是执行不了的,全局的话去修改/etc/profile
比如写个欢迎登陆的全局变量脚本:
[root@VM-4-10-centos ~]# vim /etc/profile.d/welcome.sh
[root@VM-4-10-centos ~]# cat /etc/profile.d/welcome.sh
echo "天上人间理疗会所全体佳丽,欢迎贵宾光临!"
也可以用重定向写:echo 'echo "welcome!"' > /etc/profile.d/welcome.sh
export:导出环境变量