0%

管道符、重定向和环境变量

管道符、重定向与环境变量

管道命令符”|”

管道命令符“|”的作用是将前一个命令的标准输出当做后一个命令的标准输入,格式为”命令A|命令B“。

例如前面学习的grep命令匹配关键词(/sbin/login)找出所有被限制登录系统的用户,如果我们希望统计所有不允许登录系统的用户个数,该怎么做呢:

首先理清思路:

找出被限制登录用户的命令:grep “/sbin/nologin” /etc/passwd

统计文本行数的命令则是:wc -l

现在要做的事就是将搜索命令的输出值传递给统计命令,其实只要把管道符夹在中间就可以了。

因此结果即为:grep “/sbin.nologin/” /etc/passwd | wc -l

以下为部分管道符使用例子:

1、用翻页的形式查看/etc目录中又哪些文件

ls -l /etc | more

2、向linuxprobe用户发送一封邮件

echo “content” | mail -s “Subject” linuxprobe

3、使用非交互式设置用户密码,将root的密码修改为linuxprobe

echo “linuxprobe” | passwd -stdin root

输入输出重定向

先做一个简单的演示

查看linuxprobe目录的信息:

ls linuxprobe/

(……文件信息)

ls xxxxx/

ls: cannot access xxxxx:no such file or directory

[前者执行后返回的是标准输出,后者执行失败返回的是错误输出]

标准输入(STDIN,文件描述符为0:默认从键盘输入,为0时表示是从其它文件或命令的输出
标准输出(STDOUT,文件描述符为1):默认输出到屏幕,为1时表示是文件
错误输出(STDERR,文件描述符为2):默认输出到屏幕,为2时表示是文件

对于输出重定向符有这些情况:

符号 作用
命令 > 文件 将标准输出重定向到一个文件中(清空原有文件的数据)
命令 2> 文件 将错误输出重定向到一个文件中(清空原有文件的数据)
命令 >> 文件 将标准输出重定向到一个文件中(追加到原有内容的后面)
命令 2>> 文件 将错误标准输出重定向到一个文件中(追加到原有内容的后面)
命令 >> 文件 2>$1 将标准输出与错误输出共同写入到文件中(追加到原有内容的后面)

对于输入重定向有这些情况:

符号 作用
命令 < 文件 将文件作为命令的标准输入
命令 << 分界符 从标准输入中读入,知道遇见“分界符”才停止
命令 < 文件1 > 文件2 将文件1作为命令的标准输入并将标准输出到文件2

那么来做几个输出和输入重定向的实验:

1、将man命令的帮助文档写入到/root/man.txt中:

man bash > /root/man.txt

2、向readme.txt追加一行文字

echo ”test” >> readme.txt

3、将readme.txt文件作为输入重定向给 wc -l 命令来计算行数

wl -l < readme.txt

命令行通配符

通配符 含义
* 匹配零个或多个字符
匹配任意单个字符
[0-9] 匹配范围内的数字
[abc] 匹配已出额度任意字符

bash解释器还支持很多的特殊字符拓展:

字符 作用
\ (反斜杠) 转义后面单个字符,例如$是变量定一个符号会报错,可以通过\来进行转义
‘’(单引号) 转义所有的字符
“”(双引号) 变量依然生效
“(反引号) 执行命令语句

1、定义一个变量

Price=5

2、输出Price is 5

echo “Price is $Price”

3、但如果想要输出Price is 5,就会因为是变量定义而报错,这时候可以使用转义字符\

echo “Price is $$Price”

4、使用单引号,变量将不再被取代

echo ‘Price is $$Price’

Price is $$Price

5、执行uname -a 后可以查看到本机内核的版本与架构 (反引号里面的命令会被执行):

echo ’uname -a’

PATH变量

在linux中一切都是文件,命令文件也不例外,在用户执行一条’ls’命令后发生了什么:

1、如果是以绝对/相对路径输入的命令则直接执行(如执行/bin/ls)

2、检查是否为alias别名命令

3、有bash判断其是’内部命令’还是’外部命令’

内部命令:属于解释器内部的

外部命令:独立于解释器外的命令文件

4、通过$PATH变量中定义的路径进行命令查找

查看PATH变量的方法:echo PATH

使用 ‘type 命令名字’来得知是内部命令还是外部命令

在$PATH中目录之间用 : 间隔开了

为变量增加新的值:PATH=$PATH:[路径]

环境变量

变量名称 作用
HOME 用户的主目录”家”
SHELL 当前的shell是哪个程序
HISTSIZE 历史命令记录条数
MAIL 右键信箱文件
LANG 语系数据
RANDOM 随机数字
PS1 bash提示符
HISTFILESIZE history命令存储数量
PATH 在路径中得目录查找执行文件
EDITOR 默认文本编辑器
HOME 用户主目录

创建变量:[变量名]=[提供的值]

用户创建的变量只是局部变量,若要别的用户也能使用可以通过export提升至全局变量

了解vim编辑器

命令 作用
dd 删除(剪切)光标所在的整行
5dd 删除(剪切)从光标处开始的5行
yy 复制光标所在整行
5yy 复制从光标处开始的5行
p 将之前删除(dd)或符直(yy)过的数据贴到光标后
/字符串 在文本中从上至下搜索该字符串
?字符串 在文本中从下至上搜索该字符串
n 显示搜索命令定位到的下一个字符串
N 显示搜索命令定位到的上一个字符串
u 撤销上一步的操作

vim编辑器的末行模式中的常用命令:

命令 作用
:w 保存
:q 推出
:q! 强制退出(放弃对文本的修改内容)
:wq! 强制保存退出
:set nu 显示行号
:命令 执行该命令
:整数 跳转到该行

配置网卡信息

网卡配置文件的前缀为 “eth”,第一块为eth0,第二块为eht1,以此类推……

在RHEL7系统中网卡配置文件的前缀则为ifcfg-eno

网卡的配置文件存放在 /etc/sysconfig/network-scripts目录中

网卡配置文件关键词术语:

网卡类型:TYPE=Ethernet

地址分配模式:BOOTPROTO=static

网卡名称:NAME=eno…..
是否启动:onboot=yes

IP地址:IPADDR=X.X.X.X

子网掩码:NETMASK=X.X.X.X

网卡地址:GATEWAY=192.168.10.1

DNS地址:DNS1=192.168.10.1

配置网卡信息简单思路:

1、切换到 /etc/sysconfig/network-scripts 目录中

2、使用vim命令修改网卡配置文件 ifcfg-eno…

3、逐项写入配置参数,并保存退出

4、重新启动网卡命令 systemctl restart network

5、通过ping命令测试网卡信息是否生效

配置yum仓库

配置光盘yum源挂载:

1、切换到 /etc/yum.repos.d 目录(该目录存放yum仓库配置文件)

2、使用vim编辑器创建并打开一个名为 xxx.repo的新文件,名称自定义,后缀为repo

3、逐项写入配置参数,并保存退出

4、按配置参数的路径将光盘挂在

5、架构光盘挂载信息写入到/etc/fstab文件中

6、使用yum install https -y 命令检查是否配置正确

简单的repo文件配置:

1
2
3
4
5
[test]
name=test
baseurl=file:///media/cdrom
enabled=1
gpgcheck=0

创建光盘的挂载目录:

mkdir -p /media/cdrom

挂载光盘:

mount /dev/cdrom /media/cdrom

设置开机自动挂载:

vim /etc/fstab

/dev/cdrom /media/cdrom iso9660 defaults 0 0

了解shell脚本

查看系统中所有可用的shell解释器:

cat /etc/shells

查看当前的shell解释器:

echo $SHELL

编译简单的脚本

shell脚本的编写要使用到vim文本编辑器,按照命令的执行顺序一次编写,每行写一条linux命令。并且一个完整的shell脚本则应该包括”脚本声明”、”注释信息”和”可执行语句”。

脚本声明(#!):告知系统用何种shell来解释

注释信息(#):对可执行语句或程序功能做介绍,可以不写

可执行语句:执行的具体命令

一个简单的shell脚本示例:

vim example.sh

1
2
3
4
#!/bin/bash
#显示当前的工作路径并列出当前目录下的所有文件与属性
pwd
ls -al

执行脚本有三种方法:

1、脚本文件路径:/example.sh

2、sh脚本文件路径:sh example.sh

3、source脚本文件路径:source example.sh

(只要脚本文件路径没有写错,sh或source命令都可以直接执行改脚本,但一般来说可能会出现权限不足的错误,所以需要使用chmod来赋予权限)

chmod u+x example.sh

接收用户的参数

shell脚本能够让用户更灵活的完成工作需求,应该有办法接受用户输入的参数,像上面的脚本的写法真的很不灵活

在可执行文件中已经内设:命令名 参数1 参数2 参数3

$0 当前执行的shell脚本的程序名
$1-9,{10},{11}… 参数的位置变量
$# 一共有多少个变量
$** 所有位置变量的值
$? 判断上一条命令是否执行成功,0为成功,非0为失败

一个可以接收用户参数的shell脚本:

1
2
3
4
5
6
7
8
9
10
#!/bin/bash
echo "当前脚本名称为$0"
echo "总共有$#个参数,分别是$*"
echo "第一个参数为$!,第五个为$5"


[root@zhou tmp]# sh example.sh 1 2 3 4 5
当前脚本名称为example.sh
总共有5个参数,分别是1 2 3 4 5
第一个参数为,第五个为5

判断用户的参数

shell脚本有时还要判断用户输入的参数,例如像mkdir命令一眼,当目录不存在则创建,若已存在则报错,条件测试语句能够测试特定的表达式是否成立,当条件成立时返回值0,否则返回其他数值

测试语句格式:[ 条件表达式 ] (需要注意的是两边均应有一个空格)

细分测试语句有:文件测试、逻辑测试、整数值比较、字符串比较

文件测试:[ 操作符 文件或目录名 ]

操作符 作用
-d 测试是否为目录
-e 测试文件或目录是否存在
-f 判断是否为文件
-r 测试当前用户是否有权限读取
-w 测试当前用户是否有权限写入
-x 测试当前用户是否有权限执行
1
2
3
4
5
6
7
8
[root@zhou tmp]# [ -d /etc/fstab ]
[root@zhou tmp]# echo $?
1


[root@zhou tmp]# [ -f /etc/fstab ]
[root@zhou tmp]# echo $?
0

符号&&代表逻辑上的”与”,当前面的命令执行成功后才会执行后面的命令

判断/dev/stdin是否存在,若存在则输出exist

[root@zhou ~]# [ -e /dev/stdin ] && echo “exist”
exist

逻辑测试:[ 表达式1 ] 操作符 [ 表达式2 ]

操作符 作用
&& 逻辑的与,”而且”的意思
\
! 逻辑的否
1
2
3
4
5
6
7
8
9
USER变量是当前登录的用户名
[root@zhou ~]# echo $USER
root

若当前登录的用户不是root,输出user,是root则为空
[root@zhou ~]# [ $USER! = root ] && echo "user"

非root输出user,root输出root
[root@zhou ~]# [ $USER! = root ] && echo "user" || echo "root"

整数值比较:[ 整数1 操作符 整数2 ]

操作符 作用
-eq 判断是否等于
-ne 判断是否不等于
-gt 判断是否大于
-lt 判断是否小于
-le 哦安短是否等于或小于
-ge 判断是否大于或等于
1
2
3
4
5
6
7
8
9
10
比较10是否大于10
[root@zhou ~]# [ 10 -gt 10 ]
[root@zhou ~]# echo $?
1
#显示上一条命令执行失败,10不大于10

比较10是否等于10
[root@zhou ~]# [ 10 -eq 10 ]
[root@zhou ~]# echo $?
0
1
2
3
4
5
获取当前可用的内存量,并将此值赋值给变量freemem
首先用free-m查看以m为单位的内存使用情况
然后grep cache过滤出剩余内存的行
最后用awk '{print $3}'过滤只保留第三列
而freemen='语句'则表示执行里面的雨具后赋值给变量

字符串比较:[字符串 1 操作符 字符串2]

操作符 作用
= 比较字符串内容是否相同
!= 比较字符串内容是否不同
-z 判断字符串内容是否为空
1
2
3
4
#判断string变量是否为空
[root@zhou tmp]# [ -z $string ]
[root@zhou tmp]# echo $?
0

条件测试语句

if条件语句

if条件语句分为 单分支结构、双分支结构、多分支结构

单分支结构:仅用if、then、fi关键词组成,只在条件成立后执行

1
2
3
4
5
6
7
8
#!/bin/bash
DIR="/media/cdrom"
if [ ! -e $DIR ]
then
mkdir -p $DIR
fi

#判断目录是否存在,若不存在则自动创建

双分支结构:由if、then、else、fi关键词组成,做条件成立或条件不成立的判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash
ping -c 3 -i 0.2 -W 3 $1 &> /dev/null
if [ $? -eq 0 ]
then
echo "host $1 is up"
else
echo "host $1 is down"
fi

#判断主机能否ping通,根据返回结果分别给予提示或警告
ping -c 代表发送的数据包额度个数
ping -i 代表每0.2秒发送一个数据包
ping -W 代表3秒即超时
$1为用户输入额度第一个参数
$?为上一条命令的执行结果,判断是否等于0(0为成功)

多分支结构:是有if、then、else、elif、fi关键词组成,根据多种条件成立的可能性执行不同的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
read -p "Enter your score (0-100): " GRADE
if [ $GRADE -ge 85 ] && [ $GRADE -le 100 ];then
echo "$GRADE is Excellent"
elif [ $GRADE -ge 70 ] && [ $GRADE -le 84 ];then
echo "$GRADE is PASS"
else echo "$GRADE is Fail"
fi

#判断用户呼入的分数在哪个区间内,然后判定为优秀、合格或不合格
使用read命令让用户为GRADE变量赋值
大于85小于100输出excellent
大于70小于84输出pass
其余情况输出fail

for条件语句

for条件语句会先读取多个不同的变量值,然后逐一执行同一组命令

1
2
3
4
5
6
7
8
创建用户名文件
[root@zhou tmp]# vim test.txt
andy
barry
carl
duke
eric
george
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
read -p "Enter the password: " PASSWD
for UNAME in `cat test.txt`
do
id $UNAME &> /dev/null
if [ $? -eq 0 ]
then
echo "Already exists"
else
useradd $UNAME &> /dev/null
echo "$PASSWD" | passwd --stdin $UNAME &> /dev/null
if [ $? -eq 0 ]
then
echo "Create success"
else
echo "Create failure"
fi
fi
done

shell脚本提示用户输入要设置的密码并赋值给PASSWD变量
从test.txt文件中读入用户名并赋值给UNAME变量
而查看用户的信息都重定向到/dev/null文件,不显示屏幕

2、测试主机是否在线

1
2
3
4
5
首先创建主机地址列表:
[root@zhou tmp]# vim ipadds.txt
192.168.10.10
192.168.10.11
192.168.10.12
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash
HLIST=$(cat /tmp/ipadds.txt)
for IP in $HLIST
do
ping -c 3 -i 0.2 -W 3 $IP &> /dev/null
if [ $? -eq 0 ] ; then
echo "Host $IP is up."
se
echo "Host $IP is down."
fi
done

从ipadds.txt中读取主机地址后赋值给HLIST变量
逐个ping列表中的主机IP地址测试主机是否在线

while条件语句

while条件语句用于测试重复测试某个条件,当小件成立时则继续重复执行

随机生成0-999的数字,猜数字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
PRICE=$(expr $RANDOM % 1000)
TIMES=0
echo "randow 0-999"
while true
do
read -p "input numbers: " INT
let TIMES++
if [ $INT -eq $PRICE ] ; then
echo "It's $PRICE"
echo "猜了 $TIMES 次"
exit 0
elif [ $INT -gt $PRICE ] ; then
echo "so high"
else
echo "so low"
fi
done

let可以使变量进行运算,无需加$

case条件语句

case条件语句可以依据变量的不同数值,分别执行不同的命令动作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash
read -p "输入一个字符: " KEY
case "$KEY" in
[a-z]|[A-Z])
echo "输入的是字母。"
;;
[0-9])
echo "输入的是数字。"
;;
*)
echo "输入的是其他。"
esac

提示用户输入一个字符,判断该字符是字母、数字或特殊字符
;;相当于break的效果,退出