RHCE笔记

一 准备

本地仓库-->网络仓库

本地仓库配置

挂载

下载(yum/dnf)

eg:   lrz*        主机与linux的上传与下载

                      sz   linux传至主机

                      rz   主机传至linux

                       (也可以直接用Xftp)

systemctl  +  start    + 某服务

                  restart

                  status

                  stop

                  enable

(重启操作系统时就要进行的操作)

eg   :reload    重载命令                poweroff  关闭系统

eg :  如果nmcli出现问题

vim时出现问题

日志查询

二  web

搭建基础web

1  启用httpd    2  关闭防火墙     3 写入页面数据

                                                                                           (/var/www/html为默认路径)

httpd主配置文件

路径

监听

将某个应用绑定在某个(ip+端口)套接字socket 上用于对外提供服务,用户可以直接通过套接字直接访问某个服务

(配置端口号)配置完后要restart重启httpd

.dll   

动态共享对象(动态链接库  windows)

只有在应用调用他们是才会运行,否则不运行

用户 用户组

主配置文件

容器(控制块)   控制根目录

是否能再此定义

是否能访问

   eg:     不允许

              允许

定义网站内容所在目录

                                                  ( 要不要索引 /  跟踪软链接)

如果有这个模块,则执行下列语句

(错误)日志与日志级别

脚本别名

子配置文件路径(自己所写

建立配置文件

1 进入路径位置

or

2 写配置文件

<directory /www>       (控制根目录)

allowoverride none

require all granted

</directory>

<virtualhost  192.168.150.128:80>     格式 文件名+套接字

documentroot  /www              (定义网站内容所在目录)

servername  192.168.150.128       (定义服务名)

</virtualhost>

3 重启httpd服务,并关闭SELinux(setenforce 0)

4 写入

echo  _________  > /www/index.html

一次创建多个

IP不同端口号相同的多个虚拟主机

/www                     为父目录

/www/130     /www/131   为子目录

建目录,写入内容,增加相应IP,重启服务

IP相同端口号不同的多个虚拟主机

写入对应的监听,创建对应的文件夹并写入内容后重启服务即可

搭建基于本地解析的两台主机通过主机名进行访问(IP与端口相同)

eg: 一个IP与一个端口可以划分进行多种服务(多个虚拟主机)

主机名

本地解析文件(解析自己)

(此文件将主机名本地解析成IP地址)

修改主机名

Nameserver=名称服务器=dns服务器(外部访问)(本地解析文件中有,走本地解析,如果没有,再在名称服务器中查找)

如果是主机浏览器,需要对主机的hosts文件进行修改

如果权限不够

基于用户认证的虚拟主机

创建保密的用户账户与密码

创建与写入保密内容

       

alias 脚本别名       访问/hehe =访问 /usr/local/mysecret

authtype  类型             authname  名称

authuserfile  链接账号文件

写入内容,本地解析文件

http服务器添加TLS加密

对称加密      明文——————————————>密文

                                     (加密算法)

非对称加密

默认IP与443端口

认证文件(证书)与验签(钥匙)

建立密钥

建立证书

移动与修改

基于Python的动态虚拟主机

写入脚本

更新主配置文件

更新本地解析文件

验证

三 DNS

域名解析    名称服务器  

(udp协议) 

根DNS服务器:全球有13组,每组由多台服务器组成,它们不存储具体域名记录,但知道所有顶级域服务器的位置

网卡         IP      n个

                mac   固化  不能改变

                          修改  可以改变

主机名  描述一个主机

域名      描述一堆主机

搭建dns服务器

vim /etc/named.conf

删改至如下

listen-on  监听  {DNS服务器的地址}

zone ----> 定义区域(域名)

 "."  --->  根域

IN 为关键字

   

type    :         hint  根服务器

                    master 主服务器   正常服务器

                    slave  从服务器    正常服务器 (备胎)

正向解析

添加配置

TTL    超时时间

@     代表域名         eg:haha.com

SOA  起始授权记录

admin.haha.com. (区域文件变化的序列号)   邮箱地址 

CNAME  别名                      10  邮箱前的为优先级

区域文件 eg:named.haha

               SOA       起始授权记录

               NS          区域----->主机名  

               A             主机名------>IPV4

              A AAA       主机名------>IPV6

              CNAME      别名

               MX         区域----->邮件服务器

              PTR        ip------>主机名

进行正向解析服务

(从192.168.150.128服务器中查haha.com的DNS服务器)

                                                                          (所指定服务器地址)

正向解析    主机名----->ip

                   www,baidu.com ----> ip 

反向解析     IP------>主机名   

反向解析

eg:192.168.150.128------>192.168.150------->150.168.192.in-addr.arpa

转发服务器实验

建立两个虚拟机,客户端配置转发器的IP为自己的DNS,对转发器进行文件配置,从而实现客户端通过转发器进行域名解析的作用。

服务端

IP :114.114.114.114 / 61.134.1.4    (指定)

客户端

解析Web服务器

主从DNS服务器

服务端区分主从服务器,客户端不做区分

主master

从slave

(不用写区域文件)

(named.haha区域文件从主服务器传至从服务器的/var/named/slaves/named.haha路径)

全量传输  AXFR   :将区域文件内容全部传输(一般为第一次传输)

增量传输  IXFR    :将区域文件中改动的内容进行传输

四 防火墙firewalld

硬件防火墙

软件防火墙

运行模式     runtime  运行时(临时的)

                    permanent  永久的

定义

区域zones

区域分配

开关

状态查询

(图形化查看与管理)

列出所有信息

控制流量

panic-off    解禁网络流量

(查看)

添加新服务

添加服务

控制端口

删除改为remove

五 SELinux

定义

 

状态转换:

文件修改

Eg:

禁用

禁用后启用

访问Web

eg:

标签不一致,改标签

定义新端口

六 NFS

 

配置NFS

(x)

(开机自启+auto自动挂载即可)=开机自动挂载

eg:

主机和远程主机创建的文件都是1001(只转了root用户的)

全部都转为规定的gid

* 标识任何人都可以连接我

all_squash   所有创建的文件都是nobody 65534

no_root_squash   除了root创建的都是65534

不做规定    谁创建的就是谁

anonuid     anongid       全部都转为规定的gid

如果远程主机为root用户,那么创建的文件就为65534(nobody)

                      为普通用户,那么创建的就为用户名文件

配置autofs自动挂载

定义

修改远程主机(客户端)

添加要监测的目录与执行动作目录

写入进行的操作

访问子目录(需要提前知道)

结果

七 时间服务器

加时间服务器

一个客户端,一个服务端

八 计划任务书

延迟性任务

指令查看

删除

权限

附加  : echo ____ >> /路径/ / / /

命令输出保存:———— > /路径

删除后用户不能使用(root除外)

周期性任务

指令

eg:

权限

周期性系统作业

命令---->文件

九 SSH

定义

过程

实现

基于密钥的身份认证

Linux-Linux

Windows--Linux

 

进行链接

提升Openssh安全性

1.

2.

3.密钥类型

eg:

4.更改端口

5.禁ROOT远程登陆

6.

免认证登陆(互免)

# # 安排两个主机,一个主机为 128,一个为 141

1 、在主机 128 创建密钥对。
[root@128 ~ # ssh- keygen
[root@128 ~ # ll .ssh
total 8
rw- - - - - - - . 1 root root 2590 Mar 17 12 : 58 id_rsa
rw- r - r - . 1 root root 562 Mar 17 12 : 58 id_rsa.pub
2 、将公钥传送并注册到主机 141
[root@128 ~ # ssh- copy- id root@192.168.115.141
3 、使用密钥连接到主机 141
[root@128 ~ # ssh root@192.168.115.141
4 、将公钥注册给主机 128
[root@128 ~ # ssh- copy- id root@192.168.115.128
5 、使用密钥连接到主机自己。
[root@128 ~ # ssh root@192.168.115.128
6 、在主机 141 上创建密钥对
[root@141 ~ # ssh- keygen
[root@141 ~ # ll .ssh
total 8
rw- - - - - - - . 1 root root 2590 Mar 17 12 : 59 id_rsa
rw- r - r - . 1 root root 562 Mar 17 12 : 59 id_rsa.pub
7 、将公钥注册到主机 128
[root@141 ~ # ssh- copy- id root@192.168.115.128
8 、连接到主机 128
[root@141 ~ # ssh root@192.168.115.128
9 、将公钥注册到主机自己
[root@141 ~ # ssh- copy- id root@192.168.115.141
10 、连接主机自己
[root@141 ~ # ssh root@192.168.115.141

SSH协议

SSH协议是建⽴在不安全的⽹络之上的进⾏远程安全登陆的协议。它是⼀个协议族,其中有三
个⼦协议,分别是:
1、传输层协议[SSH-TRANS]:提供服务器验证、完整性和保密性功能,建⽴在传统的TCP/IP协
议之上。
2、验证协议[SSH-USERAUTH]:向服务器验证客⼾端⽤⼾,有基于⽤⼾名密码和公钥两种验证
⽅式,建⽴在传输层协议[SSH-TRANS]之上。
3、连接协议[SSH-CONNECT]:将加密隧道复⽤为若⼲逻辑信道。它建⽴在验证协议之上。

十 Shell脚本

    Shell 不仅仅是充当用户与 UNIX 或者 localhost 交互的角色,还可以作为一种程序设计语言来使
用。通过 Shell 编程,可以实现许多非常实用的功能,提高系统管理的自动化水平。
    如果有一系列经常需要使用的命令,把它存储在一个文件里, shell 可以读取这个文件并顺序执
行其中的命令,我们把这样的文件就叫 shell 脚本。 shell 脚本按行解释文件里的命令。

基础

基本元素

1. 声明:声明用哪个命令解释器来解释并执行当前脚本文件中的语句,一般写的解释器为
#!/bin/bash
2. 命令:可执行语句,实现程序的功能。
3. 注释:说明某些代码的功能,通过在代码中增加注释可以提高程序的可读性。

编写规范

1 )脚本文件名应见名知意,例如 backup_mysql.sh
2 文件开头 指定脚本解释器 #!/bin/sh #!/bin/bash
3 )开头加版本特权等信息
4 )脚本中尽量不要用中文注释
5 )多使用内部命令
      常用的内部命令有: echo eval exec export read shift exit
      
export 设置或者显示环境变量
[root@kittod ~] # mingzi=hehe
[root@kittod ~] # echo $mingzi
hehe
[root@kittod ~] # bash
[root@kittod ~] # echo $mingzi
[root@kittod ~] # exit
exit
[root@kittod ~] # export mingzi
[root@kittod ~] # bash
[root@kittod ~] # echo $mingzi
hehe
read 命令可从标准输入读取字符串等信息,传给 shell 程序内部定义的变量。
read 是一个重要的 bash 命令,用于从键盘或标准输入读取文本,我们可以使用 read 命令以交互
形式读取来自用户的输入,不过 read 能做的远不止这些
通常我们按下回车键表示命令输入完成,但是很特殊情况下,我们需要基于字符数或者特定字符来
表示命令输入完成
-p prompt :设置提示信息
-t timeout :设置输入等待时间,单位默认为秒
[root@kittod ~] # read -t 10 -p "please input your name:" name
please input your name:hehe
[root@kittod ~] # echo $name
hehe
[root@kittod ~] # echo -n "please input your name:": read name1 name2
please input your name:: read name1 name2[root@kittod ~] #
[root@kittod ~] #
[root@kittod ~] #
[root@kittod ~] # echo -n "please input your name:"; read name1 name2
please input your name:hehe haha
[root@kittod ~] # echo $name1
hehe
[root@kittod ~] # echo $name2
haha
# 读取指定个数字符
[root@kittod ~] # read -n 3 var1
sss[root@kittod ~] #
[root@kittod ~] # echo $var1
sss
# 小案例
[root@kittod ~] # cat read01.sh
#!/bin/bash
#read yes or no
read -n1 -p "Do you want to continue [Y/N]?" answer
case $answer in
Y|y)
echo "fine,continue" ;;
N|n)
echo "ok,good bye" ;;
*)
echo "error choice" ;;
esac
exit 0
[root@kittod ~] # bash read01.sh
Do you want to continue [Y/N]?yfine,continue
[root@kittod ~] # bash read01.sh
Do you want to continue [Y/N]?nok,good bye
[root@kittod ~] # bash read01.sh
Do you want to continue [Y/N]?ferror choice
# 输入不回显
[root@kittod ~] # read -s var
[root@kittod ~] # echo $var
heheheheheheh
# 用定界符输入
[root@kittod ~] # read -d ":" haha
heheheheeheheheh:[root@kittod ~] #
[root@kittod ~] # echo $haha
heheheheeheheheh
shift ,在程序中每使用一次 shift 语句,都会使所有的位置参数依次向左移动一个位置,并使位置参
$# 1 ,直到减到 0 为止。
exit ,退出 shell 程序。在 exit 之后可以有选择地指定一个数作为返回状态

6)没有必要使用cat命令

eg cat /etc/passwd | grep guru
使用以下方式即可
eg grep guru etc/passwd

7)快速生成脚本开头的版本版权注释信息

[root@localhost ~] # vim ~/.vimrc
autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()"
func SetTitle()
if expand( "%:e" ) == 'sh'
call setline(1, "#!/bin/bash" )
call setline(2, "#########################" )
call setline(3, "#File name:" .expand( "%" ))
call setline(4, "#Version:v1.0" )
call setline(5, "#Email:admin@test.com" )
call setline(6, "#Created time:" .strftime( "%F %T" ))
call setline(7, "#Description:" )
call setline(8, "#########################" )
call setline(9, "" )
endif
endfunc

执行方式

1 )交互式执行
[root@localhost ~] # for filename in `ls /etc`
> do
> if echo " $filename " | grep "passwd"
> then
> echo " $filename "
> fi
> done
2 )作为程序文件执行(常用)
对于一组需要经常重复执行的 Shell 语句来说,将它们保存在一个文件中来执行。我们通常称这
种包含多个 Shell 语句的文件为 Shell 脚本,或者 Shell 脚本文件。脚本文件是普通的文本文件,可使用任何
的文本编辑器查看或修改 Shell 脚本
[root@localhost ~] # mkdir /test
[root@localhost ~] # cd /test
[root@localhost test] # vim test1.sh
#!/bin/bash
for filename in `ls /etc`
do
if echo " $filename " | grep "passwd"
then
echo " $filename "
fi
done

执行方法

1 bash ./ filename.sh (产生子进程,再运行,使用当前指定的 bash shell 去运行)
2 ./ filename.sh (产生子进程,再运行,使用脚本里面指定的 shell 去运行。使用该种方式执行需要 x 权限)
3 source ./ filename.sh source 命令是一个 shell 内部命令,其功能是读取指定的 shell 程序文件并
且依次执行其中的所有的语句,并没有创建新的子 shell 进程,所以脚本里面所有创建的变量都会保存到 当前的shell 里面)
4 . filename.sh (和 source 一样,也是使用当前进程执行)
[root@localhost test] # vim test2.sh
#!/bin/bash
cd /tmp
pwd
[root@localhost test] # ls -l test2.sh
-rw-r--r-- . 1 root root 24 Apr 30 20 :09 test2.sh
(1) [root@localhost test] # bash test2.sh
/tmp
(2) [root@localhost test] # ./test2.sh
-bash : ./test2.sh: Permission denied
[root@localhost test] # chmod a+rx test2.sh
[root@localhost test] # ./test2.sh
/tmp
(3) [root@localhost test] # source test2.sh
/tmp
[root@localhost tmp] #
(4) [root@localhost test] # . test2.sh
/tmp
[root@localhost tmp] #
执行 shell 脚本时,如果使用 1和2这种方式执行会在当前的进程下产生一个新的bash子进程 ,所以子进程切换到了/tmp 目录,当脚本结束,子进程也就结束了,所以当前进程的目录不会发生变化; 3和4方式执行时,不会产生新的进程 ,所以脚本执行结束后当前的目录会变成/tmp

[root@localhost test] # echo 'userdir=`pwd`' > test3.sh
[root@localhost test] # cat test3.sh
userdir = `pwd`
(1)[root@localhost test] # bash test3.sh
[root@localhost test] # echo $userdir
[root@localhost test] #
(2)[root@localhost test] # chmod a+rx test3.sh
[root@localhost test] # ./test3.sh
[root@localhost test] # echo $userdir
[root@localhost test] #
(3)[root@localhost test] # source test3.sh
[root@localhost test] # echo $userdir
/test
(4)[root@localhost test] # . test3.sh
[root@localhost test] # echo $userdir
/test

shell脚本的退出状态

UNIX 或者 Linux 中,每个命令都会返回一个退出状态码。退出状态码是一个整数,其有效范
围为 0~255 。通常情况下,成功的命令返回 0 ,而不成功的命令返回非 0 值。非 0 值通常都被解释成一个错 误码。行为良好的UNIX 命令,程序和工具都会返回 0 作为退出码来表示成功。
Shell 脚本中的函数和脚本本身也会返回退出状态码。在脚本或者是脚本函数中执行的最后的命令会决定退出状态码。另外,用户也可以在脚本中使用exit 语句将指定的退出状态码传递给 Shell

变量

从本质上讲,变量就是在程序中保存 用户数据的一块内存空间,而变量名就是这块内存空间的地址。
在程序的执行过程中,保存数据的内存空间的内容可能会不断地发生变化,但是,代表内存地址的变量名却保持不变。
Shell 中,变量名可以由字母、数字或者下划线组成,并且只能以字母或者下划线开头。对于变量名的长度,Shell 并没有做出明确的规定。因此,用户可以使用任意长度的字符串来作为变名。
     

根据数据类型分类

       Shell 是一种动态类型语言和弱类型语言 ,即在 Shell 中,变量的数据类型毋需显示地声明,变量的数据类型会根据不同的操作有所变化。准确地讲,Shell 中的变量是不分数据类型的,统一地按照字符串存储。
强类型语言,当你定义一个变量是某个类型,如果不经过代码显式转换(强制转化)过,它就永远
都是这个类型,如果把它当做其他类型来用,就会报错
弱类型语言,你想把这个变量当做什么类型来用,就当做什么类型来用,语言的解析器会自动(隐
式)转换。
比如:
C 语言定义变量, int+ 变量名,实则前面的 int 就是给变量内存划分了等级, int 定义整型所以空间里
只能存放整型,这就是强类型。 php C# Python 等都是强类型语言。

# 声明整数型变量
[root@kittod ~] # declare -i ab
[root@kittod ~] # ab=33
[root@kittod ~] # echo $ab
33
# 改变变量属性
[root@kittod ~] # declare -i ef
[root@kittod ~] # ef=1
[root@kittod ~] # echo $ef
1
[root@kittod ~] # ef="wer"
[root@kittod ~] # echo $ef
0
[root@kittod ~] # declare +i ef
[root@kittod ~] # ef="wer"
[root@kittod ~] # echo $ef
wer
# 设置变量只读
[root@kittod ~] # declare -r ab
[root@kittod ~] # ab=22
-bash : ab : readonly variable
[root@kittod ~] # echo $ab
33
# 声明数组变量
[root@kittod ~] # declare -a cd='([0]="a" [1]="b" [2]="c")'
[root@kittod ~] # echo ${cd[1]}
b
[root@kittod ~] # echo ${cd[@]}
a b c

根据作用域分类

根据作用域可将变量分为环境变量(全局变量)和普通变量(局部变量)

# 先自定义一下 vim 编辑器
[root@kittod ~] # cat .vimrc
# 按下 Tab 键时, Vim 显示的空格数。
set tabstop = 4
# 由于 Tab 键在不同的编辑器缩进不一致,该设置自动将 Tab 转为空格。
set expandtab
#Tab 转为多少个空格。
set softtabstop = 4
[root@kittod ~] # vim vartest.sh
#!/bin/bash
# 定义函数
func()
{
# 输出全局变量 v1 的值
echo "global variable v1 is $v1 "
# 定义局部变量 v1
local v1 = 2
# 输出局部变量 v1 的值
echo "local variable v1 is $v1 "
}
# 定义全局变量 v1
v1 = 1
# 调用函数
func
# 输出全局变量 v1 的值
echo "global variable v1 is $v1 "
[root@kittod ~] # chmod a+x vartest.sh
[root@kittod ~] # ./vartest.sh
global var v1 is 1
local var v1 is 2
global var v1 is 1

定义

Shell 中,通常情况下用户可以直接使用变量,而毋需先进行定义,当用户第一次使用某个变量名时,实际上就同时定义了这个变量,在变量的作用域内,用户都可以使用该变量。
# 定义变量 a
a = 1
# 定义变量 b
b = "hello"
# 定义变量 c
c = "hello world"
# 定义备份路径
bak_dir = /data/backup
# 把一个命令的结果赋值变量
变量名 = `ls`
变量名 = $(ls)
“=”前后不能有空格
字符串类型建议用引号括起来,尤其是特殊字符或有空格

引用变量 $ 变量名 或者 ${ 变量名 }
查看变量 echo $ 变量名, set (可查看所有变量:包括自定义变量和环境变量), env 显示全局变量,
declare 输出所有的变量、函数、整数和已经导出的变量。
取消变量 unset 变量名
作用范围:仅在当前 shell 中有效

注:可使用export指令将变量转换成环境变量

位置参数和预定义变量

$?   :

ping两个包,取第一个变量,结果放入/dev/null

shift  换挡符  用$1遍历整组数据

shell中的引用

把命令的输出赋予变量,则命令必须使用反引号包含,这条命令才会执行,反引号的作用和 $ (命令) 是一样的,但是反引号非常容易和单引号搞混,所以推荐大家使用 $ (命令) 的方式引用命令的输出。

[root@kittod ~] # echo "current user is: $USER"
current user is: root
[root@kittod ~] # echo 'current user is: $USER'
current user is: $USER
[root@kittod ~] # echo "current user is: `whoami`"
current user is: root
[root@kittod ~] # echo 'current user is: `whoami`'
current user is: `whoami

变量的运算

Shell 和其他编程语言一样,支持多种运算符,包括:
算数运算符
关系运算符
布尔运算符
字符串运算符
文件测试运算符

原生 bash 不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk expr expr 最常用。
expr 是一款表达式计算工具,使用它能完成表达式的求值操作。 

    表达式和运算符之间要有空格 ,例如 2+2 是不对的,必须写成 2 + 2 ,这与我们熟悉的大多数编程语言不一样。

测试
      为了能够正确处理 Shell 程序运行过程中遇到的各种情况, Linux Shell 提供了一组测试运算符。通过这些运算符,Shell 程序能够判断某种或者几个条件是否成立。条件测试在各种流程控制语句,例如判断语句和循环语句中发挥了重要的作用,所以,了解和掌握这些条件测试是非常重要的。
       在 shell 程序中,用户可以使用测试语句来测试指定的条件表达式的条件的真或假。当指定的条
件为真时,整个条件测试的返回值为 0 ;反之,如果指定的条件为假,则条件测试语句的返回值为非 0值

算术运算符

eg:

[root@kittod ~] # cat suanshu.sh
#!/bin/bash
a = 10
b = 20
echo "a $a ,b $b "
val = `expr $a + $b `
echo "a + b : $val "
val = `expr $a - $b `
echo "a - b : $val "
val = `expr $a \* $b `
echo "a * b : $val "
val = `expr $b / $a `
echo "b / a : $val "
val = `expr $b % $a `
echo "b % a : $val "
if [ $a == $b ]
then
echo "a 等于 b"
fi
if [ $a ! = $b ]
then
echo "a 不等于 b"
fi
[root@kittod ~] # bash suanshu.sh
a 10,b 20
a + b : 30
a - b : -10
a * b : 200
b / a : 2
b % a : 0
a 不等于 b
乘号(*)前边必须加反斜杠()才能实现乘法运算;

字符串运算符

test 示例
[root@kittod ~] # test -n abc;echo $?
0
[root@kittod ~] # test -n "";echo $?
1
[root@kittod ~] # test -n " ";echo $?
0
[root@kittod ~] # test -z '';echo $?
0
[root@kittod ~] # test -z abc;echo $?
1
[root@kittod ~] # test -z ' ';echo $?
1
[root@kittod ~] # test abc = abcd ;echo $? # 注意等号两边需要有空格
1
[root@kittod ~] # test abc=abcd ;echo $?
0

[] 示例
[root@kittod ~] # [ -n '' ];echo $?
1
[root@kittod ~] # [ -n ' ' ];echo $?
0
[root@kittod ~] # [ -z '' ];echo $?
0
[root@kittod ~] # [ abc=abcd ];echo $?
0
[root@kittod ~] # [ abc = abcd ];echo $? # 注意等号两边需要有空格
1
[[]] 示例
[root@kittod ~] # [[ -n abc ]];echo $?
0
[root@kittod ~] # [[ -n ' ' ]];echo $?
0
[root@kittod ~] # [[ -n '' ]];echo $?
1
[root@kittod ~] # [[ abc=acd ]] ;echo $?
0
[root@kittod ~] # [[ abc = acd ]] ;echo $? # 注意等号两边需要有空格
1

注意:测试对象是变量时, 变量需要加引号
[root@kittod ~] # test -n $name;echo $?
0
[root@kittod ~] # test -n "$name";echo $?
1
[root@kittod ~] # [ -n $name ];echo $?
0
[root@kittod ~] # [ -n "$name" ];echo $?
1

文件测试运算符
检测 Unix 文件的各种属性

其他检查符:
-S : 判断某文件是否 socket
-L : 检测文件是否存在并且是一个符号链接。
    测试文件的读、写、执行等属性,不光是根据文件属性 rwx 的标识来判断,还要看当前执行测试的用户是否真的可以按照对应的权限操作文件。

Eg:变量 file 表示文件 /test.sh,它的大小为 100 字节,具有 rwx 权限。下面的代码,将检测该文件的各种属性

[root@kittod ~] # touch /test.sh
[root@kittod ~] # cat file.sh
#!/bin/bash
file = "/test.sh"
if [ -r $file ]
then
echo " 文件可读 "
else
echo " 文件不可读 "
fi
if [ -w $file ]
then
echo " 文件可写 "
else
echo " 文件不可写 "
fi
if [ -x $file ]
then
echo " 文件可执行 "
else
echo " 文件不可执行 "
fi
if [ -f $file ]
then
echo " 文件为普通文件 "
else
echo " 文件为特殊文件 "
fi
if [ -d $file ]
then
echo " 文件是目录 "
else
echo " 文件不是目录 "
fi
if [ -s $file ]
then
echo " 文件不为空 "
else
echo " 文件为空 "
fi
if [ -e $file ]
then
echo " 文件存在 "
else
echo " 文件不存在 "
fi
[root@kittod ~] # bash file.sh
文件可读
文件可写
文件不可执行
文件为普通文件
文件不是目录
文件为空
文件存在

关系运算符
只支持数字,不支持字符串,除非字符串的值是数字

eg:

[root@kittod ~] # cat guanxi.sh
#!/bin/bash
a = 10
b = 20
if [ $a -eq $b ]
then
echo " $a -eq $b : a 等于 b"
else
echo " $a -eq $b : a 不等于 b"
fi
if [ $a -ne $b ]
then
echo " $a -ne $b : a 不等于 b"
else
echo " $a -ne $b : a 等于 b"
fi
[root@kittod ~] # bash guanxi.sh
[root@kittod ~] # test 2 -eq 3;echo $?
1
[root@kittod ~] # test 2 -eq 2;echo $?
0
[root@kittod ~] # [ 2 -ne 3 ];echo $?
0
[root@kittod ~] # [ 2 -ne 2 ];echo $?
1
[root@kittod ~] # [[ 2 != 3 ]];echo $?
0
[root@kittod ~] # [[ 2 != 2 ]];echo $?
1

[root@kittod ~] # (( 2!=3 ));echo $?
0
[root@kittod ~] # ((2!=3));echo $?
0
[root@kittod ~] # ((2=3));echo $?
-bash : ((: 2 = 3 : attempted assignment to non-variable (error token is "=3" )
1
[root@kittod ~] # ((2==3));echo $?
1
[root@kittod ~] # ((2>3));echo $?
1
[root@kittod ~] # ((2<3));echo $?
0
布尔运算符

[root@kittod ~] # cat bool.sh
#!/bin/bash a = 10
b = 20
if [ $a ! = $b ]
then
echo " $a != $b : a 不等于 b"
else
echo " $a == $b : a 等于 b"
fi
if [ $a -lt 100 -a $b -gt 15 ]
then
echo " $a 小于 100 $b 大于 15 : 返回 true"
else
echo " $a 小于 100 $b 大于 15 : 返回 false"
fi
if [ $a -lt 100 -o $b -gt 100 ]
then
echo " $a 小于 100 $b 大于 100 : 返回 true"
else
echo " $a 小于 100 $b 大于 100 : 返回 false"
fi
if [ $a -lt 5 -o $b -gt 100 ]
then
echo " $a 小于 5 $b 大于 100 : 返回 true"
else
echo " $a 小于 5 $b 大于 100 : 返回 false"
fi
[root@kittod ~] # bash bool.sh
10 ! = 20 : a 不等于 b
10 小于 100 20 大于 15 : 返回 true
10 小于 100 20 大于 100 : 返回 true
10 小于 5 20 大于 100 : 返回 false
[root@kittod ~] # touch ceshi
[root@kittod ~] # touch file
[root@kittod ~] # ll
total 0
-rw-r--r-- . 1 root root 0 Apr 26 15 :42 ceshi
-rw-r--r-- . 1 root root 0 Apr 26 15 :42 file
[root@kittod ~] # [ -f ceshi -a -f file ];echo $?
0
[root@kittod ~] # [ -e ceshi -a -f file ];echo $?
0
[root@kittod ~] # [ -f ceshi -o -f file ];echo $?
0
[root@kittod ~] # [ -f ceshi ];echo $?
0
[root@kittod ~] # ! [ -f ceshi ];echo $?
1
[root@kittod ~] # ll
total 4
-rw------- . 1 root root 1263 Dec 16 19 :11 anaconda-ks.cfg
-rwxr-xr-x . 1 root root 0 Apr 25 22 :14 file
[root@kittod ~] # [ ! -f ceshi ];echo $?
1
逻辑运算符

[root@kittod ~] # ll
total 0
-rw-r--r-- . 1 root root 0 Apr 26 15 :42 ceshi
-rw-r--r-- . 1 root root 0 Apr 26 15 :42 file
[root@kittod ~] # test -f file && echo 1 || echo 0
1
[root@kittod ~] # test -f file1 && echo 1 || echo 0
0
[root@kittod ~] # ! test -f file;echo $?
1
注:命令1 && 命令2,如果命令1执行不成功,则命令2不执行。
命令3 || 命令4,如果命令3成功,不执行命令4;如果命令3不成功,则执行命令4
[root@kittod ~] # [ -f ceshi && -f file ];echo $?
-bash : [: missing `]'
2
[root@kittod ~] # [ -f ceshi || -f file ];echo $?
-bash : [: missing `]'
-bash : -f : command not found
127
[root@kittod ~] # [ -f file ] && [ -f ceshi ];echo $?
0
[root@kittod ~] # [ -f file ] || [ -f ceshi ];echo $?
0
[root@kittod ~] # [ -f file ] || [ -d ceshi ];echo $?
0
[root@kittod ~] # [ -f file1 ] || [ -d ceshi ];echo $?
1
[root@kittod ~] # touch file
[root@kittod ~] # touch ceshi
[root@kittod ~] # [[ -f file && -f ceshi ]];echo $?
0
[root@kittod ~] # [[ -f file || -f ceshi ]];echo $?
0
[root@kittod ~] # [[ -f file && -d ceshi ]];echo $?
1
[root@kittod ~] # ((2>3&&3>4));echo $?
1
[root@kittod ~] # ((2<3&&3<4));echo $?
0
实验:

实验2:通过read读入两个整数,并比较他们的大小

[root@kittod ~] # cat 2.sh
#!/bin/bash
read -p "please input two number:" a b
[ -z " $a " -o -z " $b " ] && {
echo "please input 'two' number"
exit 1
}
expr $a + 10 &>/dev/null
return_a = $?
expr $b + 10 &>/dev/null
return_b = $?
[ " $return_a " -eq 0 -a " $return_b " -eq 0 ] || {
echo "please input two 'number'"
exit 2
}
[ " $a " -lt " $b " ] && {
echo " $a < $b "
exit 0
}
[ " $a " -eq " $b " ] && {
echo " $a = $b "
exit 0
}
[ " $a " -gt " $b " ] && {
echo " $a > $b "
exit 0
}
[root@kittod ~] # bash 2.sh
please input two number:0 0
0 = 0
[root@kittod ~] # bash 2.sh
please input two number:0 1
0 < 1
[root@kittod ~] # bash 2.sh
please input two number:1 0
1 > 0
[root@kittod ~] # bash 2.sh
please input two number:0
please input 'two' number
[root@kittod ~] # bash 2.sh
please input two number:1 2
1 < 2
[root@kittod ~] # bash 2.sh please input two number:a b
please input two 'number'
实验 3 :假设执行一个可以携带参数的 script ,执行该脚本后屏幕会显示如下的数据:
程序的文件名;共有几个参数;若参数的个数小于 2 个则告知用户参数数量太少;全部的参数内容;第一
个参数;第二个参数
[root@kittod ~] # cat 3.sh
#!/bin/bash
echo "the script name is $0 "
echo "the parameter number is $# "
[ " $# " -lt 2 ] && echo "the number of parameter is less than 2." && exit 0
echo "your whole parameter is ' $@ '"
echo "the 1st parameter is $1 "
echo "the 2nd parameter is $2 "
[root@kittod ~] # bash 3.sh
the script name is 3 .sh
the parameter number is 0
the number of parameter is less than 2 .
[root@kittod ~] # bash 3.sh 1
the script name is 3 .sh
the parameter number is 1
the number of parameter is less than 2 .
[root@kittod ~] # bash 3.sh 1 2
the script name is 3 .sh
the parameter number is 2
your whole parameter is '1 2'
the 1st parameter is 1
the 2nd parameter is 2
[root@kittod ~] # bash 3.sh 1 2 3
the script name is 3 .sh
the parameter number is 3
your whole parameter is '1 2 3'
the 1st parameter is 1
the 2nd parameter is 2
在方括号内的每个组件都需要由空格键来分隔(特别注意中括号的两端需要有空格符来分隔);在方括 号内的变量,最好都要以双引号括起;在方括号内的常量最好都以单或双引号括起来。(中括号的使用 方法与test几乎一模一样)
特殊条件测试表达式案例:
[ 条件 1 ] &&
命令 1
命令 2
命令 3
[[ 条件 1 ]] &&
命令 1
命令 2
命令 3
test 条件 1 &&
命令 1
命令 2
命令 3
if [ 条件 1 ]
then
命令 1
命令 2
命令 3
fi
运算表达式

流控  条件判断

if条件语句

单分支

第一种语法:
if < 条件表达式 >
then
指令
fi
第二种语法:
if < 条件表达式 >;then
指令
fi
tr 可以对来自标准输入的字符进行替换、删除以及压缩。该命令只接受标准输入
[root@kittod ~] # echo "HELLO WHO IS THIS" | tr 'A-Z' 'a-z'
hello who is this
[root@kittod ~] # echo "Hello 123 world 456" | tr -d '0-9'
Hello world
[root@kittod ~] # echo "GNU is not UNIX. Recursive right ?" | tr -s ' '
GNU is not UNIX. Recursive right ?
[root@kittod ~] # echo hehe | tr '[:lower:]' '[:upper:]'
HEHE

crontab ----计划任务

示例 2:编写脚本,判断当前脚本执行者,如果不是root 用户,提示用户脚本需要 root 用户来执行,并退出。
分析:判断当前脚本执行者
[root@kittod ~] # whoami
root
[root@kittod ~] # id -u
0
[root@kittod ~] # echo $USER
root
[root@kittod ~] # echo $UID
0
[root@kittod ~] # cat test_user.sh
#!/bin/bash
if [ " $USER " ! = "root" ];then
echo "Please use user root "
fi
[root@kittod ~] # chmod a+rx test_user.sh
[root@kittod ~] # ./test_user.sh
[root@kittod ~] # mkdir /data
[root@kittod ~] # cp test_user.sh /data/
[root@kittod ~] # su - redhat
[redhat@kittod ~] $ cd /data/
[redhat@kittod data] $ ./test_user.sh
Please use user root

双分支

if < 条件表达式 >
then
指令序列 1
else
指令序列 2
fi

示例 1 :判断 sshd 进程是否运行,如果服务未启动则启动相应服务。

[root@kittod ~] # chmod a+rx sshd_running.sh
[root@kittod ~] # ./sshd_running.sh
ssh server is running

示例 2 :检查主机是否存活,并输出结果

[root@kittod ~] # chmod a+rx ping.sh
[root@kittod ~] # ./ping.sh
host 192 .168.132.128 is active.

多分支结构

以此类推。如果所有的条件表达式的值都为假,则执行最后的else子句中的语句。

示例 1 :两个整数比较大小。
[root@kittod ~] # cat compare.sh
#!/bin/bash
if [ " $1 " -eq " $2 " ];then
echo " $1 equal $2 "
elif [ " $1 " -gt " $2 " ]
then
echo " $1 greater than $2 "
else
echo " $1 less than $2 "
fi  

[root@kittod ~] # chmod a+rx compare.sh
[root@kittod ~] # ./compare.sh 20 20
20 equal 20
[root@kittod ~] # ./compare.sh 10 20
10 less than 20
[root@kittod ~] # ./compare.sh 20 10
20 greater than 10
示例 2 :根据用户输入成绩,判断优良中差。
85-100 优秀 --A
70-84 良好 --B
60-79 合格 --C
60 分以下不合格 --D

示例 3 :根据用户输入,判断是数字、字母或其他字符。

[root@kittod ~] # ./input.sh
please enter a character,pree enter to continue: 2
input is number
[root@kittod ~] # ./input.sh
please enter a character,pree enter to continue: a
input is letter
[root@kittod ~] # ./input.sh
please enter a character,pree enter to continue: $
input is other
示例 4 :判断当前主机的 CPU 生产商,其信息在 /proc/cpuinfo 文件中 vendor_id 一行中。
如果其生产商为 GenuineIntel ,就显示其为 Intel 公司;
如果其生产商为 AuthenticAMD ,就显示其为 AMD 公司;
否则,就显示无法识别;
[root@kittod ~] # chmod +rx vendor.sh
[root@kittod ~] # ./vendor.sh
inter
说明:=~表示对后面的正则表达式进行匹配

exit退出程序
终止 Shell 程序的执行
除此之外, exit 语句还可以带一个可选的参数,用来指定程序退出时的状态码。
exit status
其中, status 参数表示退出状态,该参数是一个整数值,其取值范围为 0~255 。与其他的 Shell 命令一样,Shell程序的退出状态也 储存在系统变量$? 中,因此,用户可以通过该变量 取得 Shell 程序返回给父进程的 退出状态码
示例 1 :演示在不同的情况下,程序返回不同的状态码
[root@kittod ~] # cat exit.sh
#!/bin/bash
echo hello world
echo $?
aa
echo $?
exit 120
[root@kittod ~] # chmod +rx exit.sh
[root@kittod ~] # ./exit.sh
hello world
0
./exit.sh: line 4 : aa: command not found
127
[root@kittod ~] # echo $?
120
示例 2 :使用 if exit 语句,使得程序在适当的时候退出
[root@kittod ~] # chmod +rx file_create.sh
[root@kittod ~] # ./file_create.sh hehe
file hehe has been created
[root@kittod ~] # ./file_create.sh hehe
file hehe exists

多条件判断语句case

case 语句会将该变量的值与每个值相比较,如果与某个值相等,则执行该 value 所对应的一组语句。当遇到“;;” 符号时,就跳出 case 语句,执行 esac 语句后面的语句。如果没有任何一个值与 variable 的值相匹配,则执行* 后面的一组语句。
示例 1 :由用户从键盘输入一个字符,并判断该字符是否为字母、数字或者其他字符, 并输出相应的提示信息。
示例 2 :将判断分数范围多分支语句用 case 语句实现

8 、计算用户输入的任意两个整数的和、差、乘积、商、余数,
      判断用户输入的参数是否是两个,如果不是,提示用法;
      判断用户输入的是否是整数,如果不是,则给出提示终止运行。

[root@localhost test4] # ./2.sh 1
usage: ./2.sh num1 num2
[root@localhost test4] # ./2.sh 1 x
you must input two number
[root@localhost test4] # ./2.sh 3 2
a + b = 5
a-b = 1
a *b = 6
a /b = 1
a %b = 1

流控   循环

带列表的for循环语句

list中的数值依次赋值给循环变量variable进行循环

示例 1 :直接列出变量列表所有元素

[root@kittod ~] # chmod a+rx list2.sh
[root@kittod ~] # ./list2.sh
192 .168.132.128
192 .168.132.129

eg : seq  
[root@kittod ~] # seq 1 5
1
2
3
4
5
[root@kittod ~] # seq 1 2 10
1
3
5
7
9
选项:
-s 指定输出的分隔符,默认为 \n ,即默认为回车换行
[root@kittod ~] # seq -s + 1 10
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10
[root@kittod ~] # seq -s "`echo -e "\t"`" 9 11
9 10 11
-w 指定为定宽输出,不能和 -f 一起用
[root@kittod ~] # seq -w 8 11
08
09
10
11
[root@kittod ~] # seq -w 99 103
099
100
101
102
103
-f 按照指定的格式输出,不能和 -w 一起使用 , 在没有使用 -f 选项指定格式时,默认格式为 %g
[root@kittod ~] # seq 8 11
8
9
10
11
[root@kittod ~] # seq -f '%g' 8 11
8
9
10
11
[root@kittod ~] # seq -f '%3g' 8 11
  8
  9
10
11
[root@kittod ~] # seq -f '%03g' 8 11
008
009
010
011
[root@kittod ~] # seq -f "dir%g" 1 5
dir1
dir2
dir3
dir4
dir5
[root@kittod ~] # mkdir $(seq -f 'dir%03g' 1 10)
[root@kittod ~] # ll
total 10
drwxr-xr-x. 2 root root 6 May 4 15 :59 dir001
drwxr-xr-x. 2 root root 6 May 4 15 :59 dir002
drwxr-xr-x. 2 root root 6 May 4 15 :59 dir003
drwxr-xr-x. 2 root root 6 May 4 15 :59 dir004
drwxr-xr-x. 2 root root 6 May 4 15 :59 dir005 drwxr-xr-x. 2 root root 6 May 4 15 :59 dir006
drwxr-xr-x. 2 root root 6 May 4 15 :59 dir007
drwxr-xr-x. 2 root root 6 May 4 15 :59 dir008
drwxr-xr-x. 2 root root 6 May 4 15 :59 dir009
drwxr-xr-x. 2 root root 6 May 4 15 :59 dir010

示例 2 :获取当前目录下的文件名作为变量列表打印输出
[root@kittod ~] # chmod a+rx list4.sh
[root@kittod ~] # ./list4.sh
list2.sh
list3.sh
list4.sh
list.sh
示例 3 :打印出下面语句中字符数不大于 6 的单词
rabbit is favorite to eat cabbage
[root@kittod ~] # chmod a+rx 3.sh
[root@kittod ~] # ./3.sh
rabbit
is
to
eat
Shell允许用户指定for语句的步长。当用户需要另外指定步长时,其基本语法如下:

step  步长

示例:通过 for 循环,计算 100 以内奇数的和

[root@kittod ~] # chmod a+rx 4.sh
[root@kittod ~] # ./4.sh
the sum is 2500
eg : let用法
应用变量时不需要使用 $
[root@kittod ~] # no1=2
[root@kittod ~] # no2=4
[root@kittod ~] # let result=no1+no2
[root@kittod ~] # echo $result
6
自加:
[root@kittod ~] # let no1++
[root@kittod ~] # echo $no1
3
自减:
[root@kittod ~] # let no1--
[root@kittod ~] # echo $no1
2
[root@kittod ~] # a=2
[root@kittod ~] # let "a+=1"
[root@kittod ~] # echo $a
3
[root@kittod ~] # let "a-=1"
[root@kittod ~] # echo $a
2
[root@kittod ~] # let "a*=2"
[root@kittod ~] # echo $a
4
[root@kittod ~] # let "a/=2"
[root@kittod ~] # echo $a
2
[root@kittod ~] # let "a=$a**3"
[root@kittod ~] # echo $a
8
不带列表的for循环语句

示例:

[root@kittod ~] # bash 5.sh {1..6}
1
2
3
4
5
6
C风格的for循环语句

示例 1 :批量创建用户:
             用户名以 test 开头,按数字序号变化;
             一共添加 30 个账号,即 test01 tes02...,test30
             用户初始密码为 123456

[root@kittod ~] # bash add_user.sh
[root@kittod ~] # grep test /etc/passwd | cut -d ":" -f1
注意:可以简化写法, 直接用for带列表的循环 ,这样就不用 for 里面嵌套 if 判断
比如 for i in {01..30}
示例 2 :编写一个 Shell 程序,实现判断当前网络(假定为 192.168.1.0/24 ,根据实际情况实现)里,当前在线用户的IP 有哪些。

while循环语句

使得用户重复执行一系列的操作,直到某个条件的发生
while 循环读取文件
 

示例 1 :猜商品价格
             通过变量 RANDOM 获得随机数价格
             提示用户猜测并记录次数,猜中后退出循环

通用的算法公式 %random%%%(max-min + 1 ) + min 产生[min,max]区间里的随机数 ,最大值和最小值均能取到。
示例 2 while 读取文件
             工作过程中遇到要从一个 ip 列表中获取 ip port ,然后 ssh ip 到目标机器进行特定的操作
[root@kittod ~] # cat iplist
192 .168.132.128 22
192 .168.132.129 22
192 .168.132.130 22
[root@kittod ~] # bash ssh_port.sh
IP: 192 .168.132.128, PORT: 22
IP: 192 .168.132.129, PORT: 22
IP: 192 .168.132.130, PORT: 22

eg :

如果在 while 循环中调用了 ssh 命令,那么 ssh 就会把当前输入中所有的数据读走,也就是重定向给 while 命令的数据,都被ssh 命令读走了,以至于下次循环的时候, read 读到的内容为空,导致循环提前结束

示例 3 :将之前用 for 语句创建的 test01-test30 用户删除

until循环语句

   将循环体重复执行,直到某个条件成立为止

    while 不为0退出   ;   until  为0时退出    

示例:将之前用 for 语句创建的 test01-test30 用户删除

select循环语句
      主要功能是创建菜单,在执行带有 select 循环语句脚本时,输出会按照数字顺序的列表显示一个菜单,并显示提示符(默认是# ?),同时等待用户输入数字选择。

示例:

嵌套循环

  示例1:打印九九乘法表

示例 2 :打印三角形

利用breakcontinue语句控制循环
break 语句的作用是立即跳出某个循环结构。 break 语句可以用在 for while 或者 until 等循环语句的循环体中。
continue 语句则比较有趣,它的作用不是退出循环体。而是跳过当前循环体中该语句后面的语句,重新从循环语句开始的位置执行。
[root@kittod ~] # cat for_break.sh #!/bin/bash
for i in `seq 10`
do
if [ $i -eq 4 ]
then
break
fi
echo $i
done
[root@kittod ~] # bash for_break.sh
1
2
3
[root@kittod ~] # cat for_continue.sh
#!/bin/bash
for i in `seq 10`
do
if [ $i -eq 4 ]
then
continue
fi
echo $i
done
[root@kittod ~] # bash for_continue.sh
1
2
3
5
6
7
8
9
10

函数

从本质上讲,函数是一个函数名到某个代码块的映射。也就是说,用户在定义了函数之后,就可以
通过函数名来调用其所对应的一组代码。
eg : 
函数的返回值
使用 return 语句来返回某个数值,这与绝大部分的程序设计语言是相同的。但是,在
Shell 中, return 语句只能返回某个 0~255 之间的整数值。
函数案例

示例1:写一个脚本,判定192.168.33.120-192.168.33.130之间的主机哪些在线。 

示例 2 :写一个脚本,使用函数完成
1 、函数能够接受一个参数,参数为用户名;
   判断一个用户是否存在
   如果存在,就返回此用户的 shell UID ;并返回正常状态值;
   如果不存在,就说此用户不存在;并返回错误状态值;
2 、在主程序中调用函数;
[root@kittod ~] # bash userms.sh
please input username:redhat
1000 :/bin/bash
please input again:root
0 :/bin/bash
please input again:dakuang
dakuang does not exist
no dakuang,Please input again:hehe
hehe does not exist
no hehe,Please input again:quit
 函数库文件

以创建一些可重用的函数。这些函数可以单独地放在函数库文件中

脚本与库文件之间的唯一区别在于函数库文件通常只包括函数,而脚本中则可以既包括函数和变量的定义,又包括可执行的代码。此处所说的可执行代码,是指位于函数外部的代码,当脚本被载入后,这些代码会立即被执行,毋需另外调用

载入库文件的命令为. ,即一个圆点,其语法如下:
. filename
其中,参数 filename 表示库文件的名称,必须是一个合法的文件名。库文件可以使用相对路径,也
可以使用 绝对路径 。另外,圆点命令和库文件名之间有一个空格
递归函数
  递归函数的调用过程就是反复地调用其自身,每调用一次就进入新的一层。
函数可以直接或者间接地调用自身。在函数的递归调用中,函数既是调用者,又是被调用者。

示例:根据用户输入的数值计算该数的阶乘

[root@kittod ~] # bash fact.sh 0
Factorial of 0 is 1 [root@kittod ~] # bash fact.sh 5
Factorial of 5 is 120

eg : 

默认情况下,除了与函数参数关联的特殊变量之外,其他所有的变量都有全局的有效范围。另
外,在函数内部,如果没有使用local关键字进行修饰,那么函数中的变量也是全局变量
1 :函数的变量是全局变量
[root@kittod ~] # cat global.sh
#!/bin/bash
var = "hello world"
func()
{
var = "orange"
echo $var
var2 = "hello"
}
echo " $var "
func
echo " $var "
echo " $var2 "
[root@kittod ~] # bash global.sh
hello world
orange
orange
hello
2 :函数的变量使用 local 指定为局部变量
[root@kittod ~] # cat global02.sh
#!/bin/bash
var = "hello world"
func()
{
local var = "orange"
echo $var
local var2 = "hello"
}
echo " $var "
func
echo " $var "
echo " $var2 "
[root@kittod ~] # bash global02.sh
hello world
orange
hello world

数组
指将具有相同类型的若干变量按照一定的顺序组织起来的一种数据类型。

数组操作
获取所有元素:
[root@kittod ~] # echo ${array[*]} # * @ 都是代表所有元素
banana apple
获取元素下标:
[root@kittod ~] # echo ${!array[@]}
shuju2 shuju1
[root@kittod ~] # echo ${!array[*]}
shuju2 shuju1
获取数组长度:
[root@kittod ~] # echo ${#array[*]}
2
[root@kittod ~] # echo ${#array[@]}
2
获取元素:
[root@kittod ~] # echo ${array[shuju1]}
apple
[root@kittod ~] # echo ${array[shuju2]}
banana
添加元素:
[root@kittod ~] # array[3]=d
[root@kittod ~] # echo ${array[3]}
d
删除一个元素:
[root@kittod ~] # unset array[shuju1]
[root@kittod ~] # echo ${array[shuju1]}
删除数组:
[root@kittod ~] # unset array
[root@kittod ~] # mkdir /array
[root@kittod ~] # touch /array/{1..5}.txt
[root@kittod ~] # ll /array/
total 0
-rw-r--r-- . 1 root root 0 May 18 18 :03 1 .txt
-rw-r--r-- . 1 root root 0 May 18 18 :03 2 .txt
-rw-r--r-- . 1 root root 0 May 18 18 :03 3 .txt
-rw-r--r-- . 1 root root 0 May 18 18 :03 4 .txt
-rw-r--r-- . 1 root root 0 May 18 18 :03 5 .txt
[root@kittod ~] # array2=($(ls /array/))
[root@kittod ~] # echo ${array2[@]}
1 .txt 2 .txt 3 .txt 4 .txt 5 .txt
[root@kittod ~] # echo ${array2[*]}
1 .txt 2 .txt 3 .txt 4 .txt 5 .txt
[root@kittod ~] # echo ${array2[1]}
2 .txt
[root@kittod ~] # echo ${array2[0]}
1 .txt
[root@kittod ~] # echo ${array2[4]}
5 .txt
遍历数组

示例:
[root@kittod ~] # bash str.sh
Please input strings... 1
s
s
Please input strings... 2
e
e
Please input strings... 3
eeeeeeeeeeeeeeee
eeeeeeeeeeeeeeee
Please input strings... 4
ggggggggggggggggggggggwewe
ggggggggggggggggggggggwewe
Please input strings... 5
ddddd ddddd

[root@kittod ~] # bash number.sh
8
16
24

[root@kittod ~] # bash word.sh
cat
is
to
eat
fish
通配符
    通配符是由 shell 处理的 , 它只会出现在 命令的 参数 里。当 shell 参数 中遇到了通配符时, shell 会将其当作路径或文件名去在磁盘上搜寻可能的匹配:若符合要求的匹配存在,则进行代换( 路径扩展 ) ;否则就将该通配符作为一个普通字符传递给“ 命令 ,然后再由命令进行处理。总之,通配符 实际上就是一种shell实现的路径扩展功能。在 通配符被处理后 , shell 会先完成该命令的重组,然后再继续处理重组后的命令,直至执行该命令。

示例 :

   遵循ASCII码排序规则

正则表达式

    在文本过滤命令中这些元字符是用做正则表达式 ,比如像 awk sed grep 等,主要是针对 文件内容 的。然而 通配符 多用在 文件名 上,比如查找find ls cp mv 等等。没有特殊说明,正则表达式就是指基础正则表达式。
    简单的说,正则表达式就是用在字符串的处理上面的一项表示式。
    当一个正则表达式完成之后,并不能够保证这个表达式一定是准确的,需要不断地测试才可以确定其正确与否。在不同的环境下,用户需要不同的工具来帮助他完成测试的过程。如果是在Shell 命令行中,用户可以使用 grep 命令来测试。
grep :
grep 家族有三大成员分别为:
       grep :支持使用基本正则表达式。
       egrep :支持使用扩展正则表达式。
       fgrep :不支持使用正则表达式,即所有的正则表达式中的元字符都将作为一般字符,仅仅拥有其字面意义,不再拥有特殊意义

 grep命令的基本语法如下:grep [options] pattern [file…]

grep 命令根据用户指定的 ”pattern (过滤条件) 对目标文本 逐行进行匹配检查 ;打印出符合条件的行,即文本搜索工具。注:PATTERN 即过滤条件指由文本字符及正则表达式元字符所编写的字符串。
options :

基本正则表达式(BRE)

pattern :

示例 :

1 ^word 表示搜索以 word 开头的内容。
[root@kittod ~] # grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@kittod ~] # grep ^root /etc/passwd
root:x:0:0:root:/root:/bin/bash
2 word$ 表示搜索以 word 结尾的内容。
[root@kittod ~] # grep bash passwd
root:x:0:0:root:/root:/bin/bash
redhat:x:1000:1000:redhat:/home/redhat:/bin/bash
bash :x:33
[root@kittod ~] # grep bash$ passwd
root:x:0:0:root:/root:/bin/bash
redhat:x:1000:1000:redhat:/home/redhat:/bin/bash
3 ^$ 表示空行,不是空格。
[root@kittod ~] # grep ^$ passwd
[root@kittod ~] # grep ^$ passwd -n
45 :
49 :
4). 代表且只能代表一个任意字符。
[root@kittod ~] # grep r.t passwd
operator:x:11:0:operator:/root:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
rngd:x:975:974:Random Number Generator Daemon:/var/lib/rngd:/sbin/nologin
rot
[root@kittod ~] # grep r..t passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
clevis:x:981:981:Clevis Decryption Framework unprivileged
user:/var/cache/clevis:/sbin/nologin
root
[root@kittod ~] # grep r...t passwd
rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin
unbound:x:994:988:Unbound DNS resolver:/etc/unbound:/sbin/nologin
rooot
5 * 重复 0 个或多个前面的字符
[root@kittod ~]# grep r*t passwd
6 [] 匹配字符集合内任意一个字符,如 [a-z]
[root@kittod ~] # grep r[a-z]t passwd
operator:x:11:0:operator:/root:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
rngd:x:975:974:Random Number Generator Daemon:/var/lib/rngd:/sbin/nologin
rot
[root@kittod ~] # grep r[a-z]*t passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin
libstoragemgmt:x:995:989:daemon account for
libstoragemgmt:/var/run/lsm:/sbin/nologin
setroubleshoot:x:991:984::/var/lib/setroubleshoot:/sbin/nologin
clevis:x:981:981:Clevis Decryption Framework unprivileged
user:/var/cache/clevis:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
rngd:x:975:974:Random Number Generator Daemon:/var/lib/rngd:/sbin/nologin
redhat:x:1000:1000:redhat:/home/redhat:/bin/bash
rt
rot
root
rooot
7. [^abc] 在中括号里表示非,不包含 a b c
[root@kittod ~]# grep r[^a-z]*t passwd
rtkit:x:172:172:RealtimeKit:/proc:/sbin/nologin
rt
r.t
r..t
r...t
8 {n,m} 匹配 n m 次,前一个字符。
{n,} 至少 N 次,多了不限。
{n} n
{,m} 至多 m 次,少了不限。
注意: grep 要将 {} 转义, {},egrep 不需要转义
[root@kittod ~] # grep 'r[^a-z]\{3,\}' passwd
[root@kittod ~] # grep -E 'r[^a-z]{3,}' passwd
扩展正则表达式

扩展正则表达式(Extended Regular ExpressionERE)支持比基本正则表达式更多的元字符

但是扩展正则表达式对有些基本正则表达式所支持的元字符并不支持。接下来重点介绍一下在扩展正则表达式中新增加的一些元字符。

示例 :

实时CPU 内存等信息 (内存中的)

sed编辑
定义
流编辑器( stream editor )则会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流

处理时,把当前处理的行存储在临时缓冲区中,称为模式空间,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变。sed编辑器要比交互式编辑器快得多

sed 编辑器可以根据命令来处理数据流中的数据,这些命令要么从命令行中输入,要么存储在一个命令文本文件中。 sed 编辑器会执行下列操作。
(1) 一次从输入中读取一行数据。
(2) 根据所提供的编辑器命令匹配数据。
(3) 按照命令修改流中的数据。
(4) 将新的数据输出到 STDOUT

替换标记
    替换命令在替换多行中的文本时能正常工作,但默认情况下它只替换每行中出现的第一处。要让替换命令能够替换一行中不同地方出现的文本必须使用替换标记( substitution flag

替换字符

     替换文件中的路径,用C shell 替换 /etc/passwd 文件中的 bash shell
sed 编辑器允许选择其他字符来作为替换命令中的字符串分隔符:

使用地址

    默认情况下,在sed编辑器中使用的命令会作用于文本数据的所有行。如果只想将命令作用于特定行或某些行,则必须用行寻址( line addressing)。

1、数字方式的行寻址
      在命令中指定的地址可以是单个行号,或是用起始行号、逗号以及结尾行号指定的一定区间范围内的行。这里有个sed 命令作用到指定行号的例子。

2、使用文本模式过滤器

正则表达式允许创建高级文本模式匹配表达式来匹配各种数据。这些表达式结合了一系列通配符、特殊字符以及固定文本字符来生成能够匹配 几乎 任何形式文本的简练模式。
3、命令组合
    如果需要在单行上执行多条命令,可以用花括号将多条命令组合在一起。 sed 编辑器会处理地址行处列出的每条命令。

删除行

    sed编辑器不会修改原始文件。你删除的行只是从sed编辑器的输出中消失了。原始文件仍然包含 那些“删掉的行。
插入和附加文本

       
    同样的方法也适用于要在数据流起始位置增加一个新行。只要在第一行之前插入新行即可。要插入或附加多行文本,就必须对要插入或附加的新文本中的每一行使用反斜线,直到最后一行。

修改行

转换命令

[address]y/inchars/outchars/

打印行

打印行号

列出行

使用 sed 处理文件

如果你要在数据流的末尾添加文本,只需用美元符地址符就行了。

[root@kittod ~] # cat notice.std
Would the following people:
LIST
please report to the ship 's captain.
示例 :
1 、把 /etc/passwd 复制到 /root/test.txt ,用 sed 打印所有行;
[root@localhost ~] # sed -n '1,$p' test.txt
[root@localhost ~] # sed -n p test.txt
2 、打印 test.txt 3 10 行;
[root@localhost ~] # sed -n '3,10'p test.txt
3 、打印 test.txt 中包含 ’root’ 的行;
[root@localhost ~] # sed -n '/root/p' test.txt
4 、删除 test.txt 15 行以及以后所有行;
[root@localhost ~] # sed -i '15,$d' test.txt
[root@localhost ~] # sed -e '15,$d' test.txt( 只会在命令行删除,不会真的删除原文件内容 )
同于 [root@localhost ~]# sed '15,$d' passwd
5 、删除 test.txt 中包含 ’bash’ 的行;
[root@localhost ~] # sed '/bash/'d test.txt
6 、替换 test.txt ’root’ ’toor’
[root@localhost ~] # sed 's/root/toor/g' test.txt
7 、替换 test.txt ’/sbin/nologin’ ’/bin/login’
[root@localhost ~] # sed 's#/sbin/nologin#/bin/login#' test.txt
8 、删除 test.txt 5 10 行中所有的数字;
[root@localhost ~] # sed '5,10s/[0-9]//g' test.txt
9 、删除 test.txt 中所有特殊字符(除了数字以及大小写字母);
[root@localhost ~] # sed 's/[^0-9a-zA-Z]//g' test.txt
10 、在 test.txt 20行到末行最前面 ’aaa:’
[root@localhost ~] # sed '20,$s/ ^.*$/aaa:&/g ' test.txt
11 、复制 /etc/grub2.cfg /root/grub2.cfg, 删除文件中所有以空白开头的行行首的空白字符;
[root@localhost ~] # sed 's/^[[:space:]]//' grub2.cfg
12 、删除 /etc/fstab 文件中所有以 # 开头,后面至少跟一个空白字符的行的行首的 # 和空白字符
[root@localhost ~] # sed 's/^#[[:space:]]*//' /etc/fstab
13 、给文件 /root/anaconda-ks.cfg 每一行行首 增加 #
[root@localhost ~] # sed 's/ ^.*$/#& /' /root/anaconda-ks.cfg
14 、在 /etc/fstab 文件中不以 # 开头的行的行首增加 # 号;
[root@localhost ~] # sed 's/^[^#]/#&/' /etc/fstab
15 、处理 /etc/sysconfig/network-scripts/ 路径 , 使用 grep sed 命令取出其目录名和基名
[root@localhost ~] # echo "/etc/sysconfig/network-scripts/" |sed -r
's#^/(.*)/(.*)/#\1#' etc/sysconfig
[root@localhost ~] # echo "/etc/sysconfig/network-scripts/" |sed -r
's#^/(.*)/(.*)/#\2#'
network-scripts
[root@localhost ~] # echo "/etc/httpd/conf.d/host.conf" | sed -r 's#(^/.*/)
[^/].*#\1#'
/etc/httpd/conf.d/
[root@localhost ~] # echo "/etc/httpd/conf.d/host.conf" | sed -r
's#^/.*/([^/].*)#\1#'
host.conf
[root@localhost ~] # basename /etc/httpd/conf.d/host.conf
host.conf
[root@localhost ~] # dirname /etc/httpd/conf.d/host.conf
/etc/httpd/conf.d
[root@localhost ~] # echo "/etc/sysconfig/network-scripts/"|grep -o -E "[^/]+/?
$"|grep -o -E "^[^/]+"
network-scripts
[root@localhost ~] # echo "/etc/sysconfig/network-scripts/"|grep -o -E "
(^/([^/]+/)*[^[:space:]])|^/"|grep -o -E "^/([^/]+/)*"|grep -o -E "(/[^/]+)+|^/"
/etc/sysconfig
16 、利用 sed 取出 ifconfig 命令中本机的 IPv4 地址
[root@localhost ~] # ifconfig |sed -n '2p' | sed -r "s/.*inet[[:space:]]*//" | sed -r   "s/[[:space:]]*netmask.*//"
192 .168.168.128
17 、统计 centos 安装光盘中 Package 目录下的所有 rpm 文件的以 . 分隔倒数第二个字段的重复次数
[root@localhost ~] # ls /mnt/Packages/|grep "rpm$"|sed -r 's@.*\. (.*)\.rpm@\1@'|sort|uniq -c
       1085 i686
       1216 noarch
       2319 x86_64

awk

定义变量来保存数据;
使用算术和字符串操作符来处理数据;
使用结构化编程概念(比如 if-then 语句和循环)来为数据处理增加处理逻辑;
通过提取数据文件中的数据元素,将其重新排列或格式化,生成格式化报告。
        awk 程序的报告生成能力通常用来从大文本文件中提取数据元素,并将它们格式化成可读的报告。其中最完美的例子是格式化日志文件。在日志文件中找出错误行会很难, awk 程序可以让你从日志文件中过滤出需要的数据元素,然后你可以将其格式化,使得重要的数据更易于阅读。

运用

从命令行读取程序脚本

awk程序脚本用一对花括号来定义。你必须将脚本命令放到两个花括号( {})中。

由于 awk 命令行假定脚本是单个文本字符串,你还必须将脚本放到单引号中。下面的例子在命令行上指定了一个简单的awk 程序脚本:
如果你输入一行文本并按下回车键, awk 会对这行文本运行一遍程序脚本。跟 sed 编辑器一样, awk 程序会针对数据流中的每行文本执行程序脚本。由于程序脚本被设为显示一行固定的文本字符串,因此不管你在数据流中输入什么文本,都会得到同样的文本输出

使用数据字段变量
    awk 的主要特性之一是其处理文本文件中数据的能力。它会自动给一行中的每个数据元素分配一个变量。默认情况下, awk 会将如下变量分配给它在文本行中发现的数据字段:
$0 代表整个文本行;
$1 代表文本行中的第 1 个数据字段;
$2 代表文本行中的第 2 个数据字段;
$n 代表文本行中的第 n 个数据字段。
    在文本行中,每个数据字段都是通过字段分隔符划分的。 awk 在读取一行文本时,会用预定义的字段分隔符划分每个数据字段。 awk 中默认的字段分隔符是任意的空白字符(例如空格或制表符)。在下面的例子中, awk 程序读取文本文件,只显示第 1个数据字段的值。

在脚本中使用多个命令
只要在命令之间放个分号即可。

从文件中读取程序

在处理数据前运行脚本   在处理数据后运行脚本

eg:F=" "  (F=":")    在程序内指定分隔符

高级运用
所有编程语言共有的一个重要特性是使用变量来存取值。 awk 编程语言支持两种不同类型的变
量:
            内建变量
            自定义变量   

内建变量

内建变量 FS 是一组内建变量中的一个,这组变量用于控制 awk 如何处理输入输出数据中的字段
和记录。下表列出了这些内建变量
(字段和记录分隔符变量)

awk OFS 设成一个空格,所以如果你用命令:

数据变量
        ARGC和ARGV 变量允许从 shell中获得命令行参数的总数以及它们的值。但这可能有点麻烦,因为awk并不会将程序脚本当成命令行参数的一部分,
        ARGC 变量表明命令行上有两个参数。这包括 awk 命令和 data1 参数(记住,程序脚本并不算参数)。 ARGV 数组从索引 0 开始,代表的是命令。第一个数组值是 awk 命令后的第一个命令行
参数。
注意:跟 shell 变量不同,在脚本中引用 awk 变量时,变量名前不加美元符。
        ENVIRON 变量看起来可能有点陌生。它使用关联数组来提取 shell 环境变量。关联数组用文本
作为数组的索引值,而不是数值。数组索引中的文本是shell 环境变量名,而数组的值则是 shell 环境变量的值。
        ENVIRON["PATH"] 提取了 PATH 环境变量的值。可以用这种方法来从 shell 中提取任何环境
变量的值,以供 awk 程序使用。
NF 变量可以让你在不知道具体位置的情况下指定记录中的最后一个数据字段
FNR 变量含有当前数据文件中已处理过的记录数, NR 变量则含有已处理过的记录总数。
自定义变量
    awk允许你定义自己的变量在程序代码中使用 awk 自定义变量 名可以是任意数目的字母、数字和下划线,但不能以数字开头,awk 变量名区分大小写。
在脚本中给变量赋值

在命令行上给变量赋值

数组
    关联数组跟数字数组不同之处在于它的索引值可以是任意文本字符串。你不需要用连续的数字
来标识数组中的数据元素。 

遍历

索引值不会按任何特定顺序返回,但它们都能够指向对应的数据元素值

删除数组变量
使用模式
支持多种类型的匹配模式来过滤数据记录

eg:

也可以用 ! 符号来排除正则表达式的匹配

数学表达式

这个功能在匹配数据字段中的数字值时非常方便。举个例子,如果你想显示所有属于root 用户组(组 ID 0 )的系统用户,可以用这个脚本
结构化命令

if

[root@kittod ~] # cat data4
10
5
13
50
34

while

[root@kittod ~] # cat data5
130 120 135
160 113 140
145 170 215

do while

for

内建函数

数学函数

[root@kittod ~] # awk 'BEGIN{x=exp(100); print x}'
26881171418161356094253400435962903554686976

字符串函数

时间函数

自定义函数

eg:

function printthird()
{
print $3
}
eg:
function myrand(limit)
{
return int(limit * rand())
}

创建函数库

附:脚本调试

    echo 命令是最有用的调试脚本的工具之一。一般应在可能出现的问题的脚本重要的部分加echo命令(在变量读取或修改操作的前后加入 echo 命令,并紧挨着退出命令 exit )。此调试
方法不仅适用于 shell ,在 php Python 语言中经常使用。
使用 bash 命令参数调试
    -n: 不会执行该脚本,仅查询脚本语法是否有问题,并给出错误提示
    -v: 在执行脚本时,先将脚本的内容输出到屏幕上,然后执行脚本。如果有错误,也会给出错误提示。
    -x:将执行的脚本内容及输出显示到屏幕上,这是对调试很有用的参数
注:参数 -x 是追踪脚本执行过程一种非常好的方法,他可以在执行前列出所执行的所有程序段。
如果是程序段落,在输出时,最前面会加上 + 符号,表示程序代码。
如果执行脚本发生问题(非语法问题时),利用 -x 参数,就可以知道问题出在哪一行。一般情况下如果是调试逻辑错误的脚本,用-x 的参数效果更佳。
    缺点:加载系统函数库等很多我们不想查看其整个过程的脚本时,会有太多输出,导致
很难查看所需要的内容
使用 set 命令调试部分脚本内容
set 命令也可以用于辅助脚本调试。
set 命令常用的调试选项:
     set -n : 读取命令但并不执行
     set -v : 显示读取的所有行
     set -x : 显示所有命令及其参数
提示:通过 set -x 命令开启调试功能,而通过 set +x 关闭调试功能。
set 命令最大优点是,和 bash -x 相比, set -x 可以缩小调试的作用域。

附:cockpit控制台

端口 : 9090

附:CDN

   CDN英文全称Content Delivery Network,中文翻译即为内容分发网络。它是建立并覆盖在承载网之上,由分布在不同区域的边缘节点服务器群组成的分布式网络。

附:指令

init 

rebot

cat:

cat(英文全拼:concatenate)命令用于连接文件并打印到标准输出设备上,它的主要作用是用于查看和连接文件。

  • -n:显示行号,会在输出的每一行前加上行号。
  • -b:显示行号,但只对非空行进行编号。
  • -s:压缩连续的空行,只显示一个空行。
  • -E:在每一行的末尾显示 $ 符号。
  • -T:将 Tab 字符显示为 ^I
  • -v:显示一些非打印字符。

查看文件内容:显示文件 filename 的内容。

cat filename

创建文件:将标准输入重定向到文件 filename,覆盖该文件的内容。

cat > filename

追加内容到文件:将标准输入追加到文件 filename 的末尾。

cat >> filename

连接文件:将 file1 和 file2 的内容合并到 file3 中。

cat file1 file2 > file3

显示多个文件的内容:同时显示 file1 和 file2 的内容。

cat file1 file2

使用管道:将 cat 命令的输出作为另一个命令的输入。

cat filename | command

查看文件的最后几行:显示文件 filename 的最后 10 行。

cat filename | tail -n 10

使用 -n 选项显示行号:显示文件 filename 的内容,并在每行的前面加上行号。

cat -n filename

netstat

命令用于显示网络状态。

  • -l或--listening 显示监控中的服务器的Socket。(套接字)
  • -i或--interfaces 显示网络界面信息表单。
  • -a或--all 显示所有连线中的Socket
  • -s或--statistics 显示网络工作信息统计表。

tail

可用于查看文件的内容,有一个常用的参数 -f 常用于查阅正在改变的日志文件。

tail -f filename                  会把 filename 文件里的最尾部的内容显示在屏幕上,并且不断刷新,只要 filename 更新就可以看到最新的文件内容。

要显示 notes.log 文件的最后 10 行,请输入以下命令:

tail notes.log         # 默认显示最后 10 行
  • -n<行数> 显示文件的尾部 n 行内容
  • -c<数目> 显示的字节数

 grep

(global regular expression) 用于查找文件里符合条件的字符串或正则表达式

  • -i:忽略大小写进行匹配。
  • -v:反向查找,只打印不匹配的行。
  • -n:显示匹配行的行号。
  • -r:递归查找子目录中的文件。
  • -l:只打印匹配的文件名。
  • -c:只打印匹配的行数。

管道符 ’ | ’ 操作详解

管道符主要用于多重命令处理,前面命令的打印结果作为后面命令的输入。简单点说就是,就像工厂的流水线一样,进行完一道工序后,继续传送给下一道工序处理…

eg:对hello.sh文件进行排序去重以后找出包含"better"的行

命令为:cat hello.sh | sort | uniq | grep 'better’

  • 查看文本
  • 排序
  • 去重
  • 过滤

read

用来从标准输入读取单行数据。这个命令可以用来读取键盘输入,当使用重定向的时候,可以读取文件中的一行数据

  • -a 后跟一个变量,该变量会被认为是个数组,然后给其赋值,默认是以空格为分割符。
  • -d 后面跟一个标志符,其实只有其后的第一个字符有用,作为结束的标志。
  • -p 后面跟提示信息,即在输入前打印提示信息。
  • -e 在输入的时候可以使用命令补全功能。
  • -n 后跟一个数字,定义输入文本的长度,很实用。
  • -r 屏蔽\,如果没有该选项,则\作为一个转义字符,有的话 \就是个正常的字符了。
  • -s 安静模式,在输入字符时不再屏幕上显示,例如login时输入密码。
  • -t 后面跟秒数,定义输入字符的等待时间。
  • -u 后面跟fd,从文件描述符中读入,该文件描述符可以是exec新开启的。
#!/bin/bash

#这里默认会换行  
echo "输入网站名: "  
#读取从键盘的输入  
read website  
echo "你输入的网站名是 $website"  
exit 0  #退出

测试结果为:

输入网站名: 
www.runoob.com
你输入的网站名是 www.runoob.com
​​​​​​​#!/bin/bash

read -p "输入网站名:" website
echo "你输入的网站名是 $website" 
exit 0

测试结果为:

输入网站名:www.runoob.com
你输入的网站名是 www.runoob.com 

echo 

与 PHP 的 echo 指令类似,都是用于字符串的输出

显示变量

read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量

#!/bin/sh
read name 
echo "$name It is a test"
以上代码保存为 test.sh,name 接收标准输入的变量,结果将是:

[root@www ~]# sh test.sh
OK                     #标准输入
OK It is a test        #输出
 

显示换行

echo -e "OK! \n" # -e 开启转义
echo "It is a test"
输出结果:

OK!

It is a test

显示不换行

#!/bin/sh
echo -e "OK! \c" # -e 开启转义 \c 不换行
echo "It is a test"

输出结果:

OK! It is a test

原样输出字符串,不进行转义或取变量(用单引号)

echo '$name\"'

输出结果:

$name\"

显示命令执行结果

echo `date`

注意: 这里使用的是反引号 `, 而不是单引号 '。

结果将显示当前日期

Thu Jul 24 10:08:46 CST 2014

显示结果定向至文件

echo "It is a test" > myfile

其他:

“>”

可将结果输出到文件中,该文件原有内容会被删除

“>>”

则将结果附加到文件中,原文件内容不会被删除

“<”

可以改变标准输入

附:网关

  • 34
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值