LINUX学习(3)

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

目前为止,我们已经学习了数十个常用的 Linux 系统命令,如果不能把这些命令进行组 合使用,则无法提升工作效率。本章首先讲解与文件读写操作有关的重定向技术的 5 种模式:
标准覆盖输出重定向
标准追加输出重定向
错误覆盖输出重定向
错误追加输出重定 向
输入重定向

输入输出重定向

输入重定向是指把文件导入到命令中
输出重定向则是指把原本要输出到屏幕的数据信息写入到指定文件中

标准输入重定向(STDIN,文件描述符为 0):默认从键盘输入,也可从其他文件或命 令中输入。
标准输出重定向(STDOUT,文件描述符为 1):默认输出到屏幕。
错误输出重定向(STDERR,文件描述符为 2):默认输出到屏幕。
比如我们分别查看两个文件的属性信息,其中第二个文件是不存在的,虽然针对这两个文件的操作都分别会在屏幕上输出一些数据信息,但这两个操作的差异其实很大:

[root@RICARDOfs ~]# ls -l linuxprobe
-rw-r--r-- 1 root root 0 Mar 24 10:45 linuxprobe
[root@RICARDOfs ~]# ls -l lijjjj
ls: cannot access lijjjj: No such file or directory

在上述命令中,名为 linuxprobe 的文件是存在的,输出信息是该文件的一些相关权限、 所有者、所属组、文件大小及修改时间等信息,这也是该命令的标准输出信息。而名为 xxxxxx 的第二个文件是不存在的,因此在执行完 ls 命令之后显示的报错提示信息也是该命令的错误输出信息。那么,要想把原本输出到屏幕上的数据转而写入到文件当中,就要区别对待这两种输出信息。
在这里插入图片描述
在这里插入图片描述
对于重定向中的标准输出模式,可以省略文件描述符 1 不写,而错误输出模式的文件描述符 2 是必须要写的。我们先来小试牛刀。通过标准输出重定向将man bash命令原本要输出到屏幕的信息 写入到文件readme.txt中,然后显示 readme.txt文件中的内容。具体命令如下

[root@linuxprobe ~]# man bash > readme.txt 
[root@linuxprobe ~]# cat readme.txt  
BASH(1)                     General Commands Manual              BASH(1) 
NAME 
bash - GNU Bourne-Again SHell 

有没有感觉到很方便呢?我们接下来尝试输出重定向技术中的覆盖写入与追加写入这 两种不同模式带来的变化。首先通过覆盖写入模式向 readme.txt 文件写入一行数据(该文件 中包含上一个实验的 man 命令信息),然后再通过追加写入模式向文件再写入一次数据,其 命令如下

[root@RICARDOfs ~]# echo "Welcome to linux" > readmebash.txt
[root@RICARDOfs ~]# echo "Quality linux learning" >>readmebash.txt
[root@RICARDOfs ~]# cat readmebash.txt
Welcome to linux
Quality linux learning

虽然都是输出重定向技术,但是不同命令的标准输出和错误输出还是有区别的。例如查 看当前目录中某个文件的信息,这里以 linuxprobe 文件为例。因为这个文件是真实存在的,因此使用标准输出即可将原本要输出到屏幕的信息写入到文件中,而错误的输出重定向则依然 把信息输出到了屏幕上

[root@linuxprobe ~]# ls -l linuxprobe  
-rw-r--r--. 1 root root 0 Mar  1 13:30 linuxprobe 
[root@linuxprobe ~]# ls -l linuxprobe > /root/stderr.txt  
[root@linuxprobe ~]# ls -l linuxprobe 2> /root/stderr.txt  
-rw-r--r--. 1 root root 0 Mar  1 13:30 linuxprobe 

如果想把命令的报错信息写入到文件,该怎么操作呢?当用户在执行一个自动化的 Shell 脚本时,这个操作会特别有用,而且特别实用,因为它可以把整个脚本执行过程中的报错信 息都记录到文件中,便于安装后的排错工作。接下来我们以一个不存在的文件进行实验演示

[root@linuxprobe ~]# ls -l xxxxxx  
cannot access xxxxxx: No such file or directory 
[root@linuxprobe ~]# ls -l xxxxxx > /root/stderr.txt 
cannot access xxxxxx: No such file or directory 
[root@linuxprobe ~]# ls -l xxxxxx 2> /root/stderr.txt 
[root@linuxprobe ~]# cat /root/stderr.txt  
ls: cannot access xxxxxx: No such file or directory

使用输入重定向把 readme.txt 文件导入给 wc -l 命令,统计一下文件中的内容行数,并于之前的比较下

[root@RICARDOfs ~]# wc -l <readmebash.txt
0
[root@RICARDOfs ~]# wc -l ./readmebash.txt
0 ./readmebash.txt

管道命令符

其执行格式为“命令 A | 命令 B”。 管道命令符的作 用也可以用一句话来概括“把前一个命令原本要输出到屏幕的标准正常数据当作是后一个命令的标准输入”

[root@linuxprobe ~]# grep "/sbin/nologin" /etc/passwd | wc -l 
33

用翻页的形式 查看/etc 目录中的文件列表及属性信息(这些内容默认会一股脑儿地显示到屏幕上,根本看 不清楚):

[root@linuxprobe ~]# ls -l /etc/ | more 
total 1400 
drwxr-xr-x.  3 root root    97 Jul   10 17:26 abrt 
-rw-r--r--.  1 root root    16 Jul   10 17:36 adjtime 
-rw-r--r--.  1 root root  1518 Jun    7  2013 aliases 
--More-- 

通过把管道符和 passwd 命令的–stdin 参数相结合,我们可以用一条 命令来完成密码重置操作:

[root@linuxprobe ~]# echo "linuxprobe" | passwd --stdin root 
Changing password for user root. 
passwd: all authentication tokens updated successfully

在发送电子 邮件时,默认采用交互式的方式来进行,我们完全可以利用一条结合了管道符的命令语句, 把编辑好的内容与标题一起“打包”,最终用这一条命令实现邮件的发送。

[root@linuxprobe ~]# echo "Content" | mail -s "Subject" linuxprobe 
[root@linuxprobe ~]# su - linuxprobe 
Last login: Fri Jul 10 09:44:07 CST 2017 on :0 
[linuxprobe@linuxprobe ~]$ mail 
Heirloom Mail version 12.5 7/5/10. Type ? for help. 
"/var/spool/mail/linuxprobe": 1 message 1 new 
>N 1 root Sun Aug 30 17:33 18/578 "Subject"

下面这条自造的命令就结合使用了 mail 邮件命令与输入重定向的分界符,其目的是让用 户一直输入内容,直到用户输入了其自定义的分界符时,才结束输入

[root@linuxprobe ~]# mail -s "Readme" root@linuxprobe.com << over 
> I think linux is very practical
> over 
[root@linuxprobe ~]#

我们完全可以 这样使用:命令 A | 命令 B | 命令 C

命令行的通配符

假设想要批量查看所有硬 盘文件的相关权限属性,一种方式是这样的:

[root@linuxprobe ~]# ls -l /dev/sda 
brw-rw----. 1 root disk 8, 0 May 4 15:55 /dev/sda 
[root@linuxprobe ~]# ls -l /dev/sda1 
brw-rw----. 1 root disk 8, 1 May 4 15:55 /dev/sda1 
[root@linuxprobe ~]# ls -l /dev/sda2 
brw-rw----. 1 root disk 8, 2 May 4 15:55 /dev/sda2 
[root@linuxprobe ~]# ls -l /dev/sda3 
ls: cannot access /dev/sda3: No such file or directory

通配符就是通用的匹配信息的符号,比如
星号 * 代表匹配零个或多个字符
问号 ? 代表匹配单个字符
[0-9]代表匹配 0~ 9 之间的单个数字的字符
[abc]则是代表匹配 a、b、c 三个字符中的任意 一个字符。

[root@RICARDOfs ~]# ls -l /dev/vda*
brw-rw---- 1 root disk 253, 0 Feb  4 10:38 /dev/vda
brw-rw---- 1 root disk 253, 1 Feb  4 10:38 /dev/vda1
brw-rw---- 1 root disk 253, 2 Feb  4 10:38 /dev/vda2

[root@RICARDOfs ~]# ls -l /dev/vda?
brw-rw---- 1 root disk 253, 1 Feb  4 10:38 /dev/vda1
brw-rw---- 1 root disk 253, 2 Feb  4 10:38 /dev/vda2

[root@RICARDOfs ~]# ls -l /dev/vda[1-9]
brw-rw---- 1 root disk 253, 1 Feb  4 10:38 /dev/vda1
brw-rw---- 1 root disk 253, 2 Feb  4 10:38 /dev/vda2

常用的转义字符

4 个最常用的转义字符如下所示。
➢ 反斜杠(\):使反斜杠后面的一个变量变为单纯的字符串。
➢ 单引号(’’):转义其中所有的变量为单纯的字符串。
➢ 双引号(""):保留其中的变量属性,不进行转义处理。
➢ 反引号(``):把其中的命令执行后返回结果。

[root@RICARDOfs ~]# PRICE=100
[root@RICARDOfs ~]# echo "Price is $PRICE"
Price is 100

[root@RICARDOfs ~]# echo "Price is $$PRICE"
Price is 10752PRICE

[root@RICARDOfs ~]# echo "Price is \$$PRICE"
Price is $100

如果只需要某个命令的输出值时,可以像命令这样,将命令用反引号括起来,达到预 期的效果。例如,将反引号与 uname -a 命令结合,然后使用 echo 命令来查看本机的 Linux 版 本和内核信息:

[root@RICARDOfs ~]# uname -a
Linux RICARDOfs.com 4.14.129-bbrplus #1 SMP Tue Jun 25 12:23:41 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

[root@RICARDOfs ~]# echo `uname -a`
Linux RICARDOfs.com 4.14.129-bbrplus #1 SMP Tue Jun 25 12:23:41 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

重要的环境变量

变量是计算机系统用于保存可变值的数据类型。在 Linux 系统中,变量名称一般都是大写的,这是一种约定俗成的规范。我们可以直接通过变量名称来提取到对应的变量值。Linux 系统中的环境变量是用来定义系统运行环境的一些参数,比如每个用户不同的家目录、邮件存放位置等
命令在 Linux 中的 执行分为 4 个步骤
第1步 判断用户是否以绝对路径或相对路径的方式输入命令(如/bin/ls),如果是的话则直接执行
第2步 Linux 系统检查用户输入的命令是否为“别名命令”,即用一个自定义的命令名称来替换原本的命令名称。可以用 alias 命令来创建一个属于自己的命令别名,格式为 alias 别名=命令。若要取消一个命令别名,则是用 unalias 命令,格式为unalias 别名。 我们之前在使用 rm命令删除文件时,Linux 系统都会要求我们再确认是否执行删除操作, 其实这就是 Linux 系统为了防止用户误删除文件而特意设置的 rm 别名命令,接下来我们 把它取消掉

[root@linuxprobe ~]# rm anaconda-ks.cfg  
rm: remove regular file ‘anaconda-ks.cfg’? y 
[root@linuxprobe~]# alias rm 
alias rm='rm -i' 
[root@linuxprobe ~]# unalias rm 
[root@linuxprobe ~]# rm initial-setup-ks.cfg 

第3步:Bash 解释器判断用户输入的是内部命令还是外部命令。内部命令是解释器内部
的指令,会被直接执行;而用户在绝大部分时间输入的是外部命令,这些命令交由步骤 4 继 续处理。可以使用“type 命令名称”来判断用户输入的命令是内部命令还是外部命令
第4步 系统在多个路径中查找用户输入的命令文件,而定义这些路径的变量叫作PATH,可以简单地把它理解成是“解释器的小助手”,作用是告诉 Bash 解释器待执行的命令可能存放 的位置,然后 Bash 解释器就会乖乖地在这些位置中逐个查找。PATH 是由多个路径值组成的 变量,每个路径值之间用冒号间隔,对这些路径的增加和删除操作将影响到 Bash 解释器对 Linux 命令的查找

[root@linuxprobe ~]# echo $PATH 
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin 
[root@linuxprobe ~]# PATH=$PATH:/root/bin 
[root@linuxprobe ~]# echo $PATH 
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/root/bin

这里有比较经典的问题:“为什么不能将当前目录(.)添加到 PATH 中呢? ” 原因是, 尽管可以将当前目录(.)添加到 PATH 变量中,从而在某些情况下可以让用户免去输入命令 所在路径的麻烦。
但是,如果黑客在比较常用的公共目录/tmp 中存放了一个与 ls 或 cd 命令同名的木马文件,而用户又恰巧在公共目录中执行了这些命令,那么就极有可能中招了
所以,作为一名态度谨慎、有经验的运维人员,在接手了一台 Linux 系统后一定会在执 行命令前先检查 PATH 变量中是否有可疑的目录,另外读者从前面的 PATH 变量示例中是否 也感觉到环境变量特别有用呢。我们可以使用 env 命令来查看到 Linux 系统中所有的环境变 量
在这里插入图片描述
Linux 作为一个多用户多任务的操作系统,能够为每个用户提供独立的、合适的工作运行 环境,因此,一个相同的变量会因为用户身份的不同而具有不同的值。

[root@linuxprobe ~]# echo $HOME 
/root 
[root@linuxprobe ~]# su - linuxprobe 
Last login: Fri Feb 27 19:49:57 CST 2017 on pts/0 
[linuxprobe@linuxprobe ~]$ echo $HOME 
/home/linuxprobe

其实变量是由固定的变量名与用户或系统设置的变量值两部分组成的,我们完全可以自 行创建变量,来满足工作需求。例如设置一个名称为 WORKDIR 的变量,方便用户更轻松地 进入一个层次较深的目录:

[root@RICARDOfs ~]# mkdir /home/workdir
[root@RICARDOfs ~]# WORKDIR=/home/workdir
[root@RICARDOfs ~]# cd $WORKDIR
[root@RICARDOfs workdir]# pwd
/home/workdir

但是,这样的变量不具有全局性,作用范围也有限,默认情况下不能被其他用户使用。 如果工作需要,可以使用 export 命令将其提升为全局变

复习题

1.把 ls 命令的正常输出信息追加写入到 error.txt 文件中的命令是什么?
ls >> error.txt

2.请简单概述管道符的作用。
把左面(前面)命令的输出值作为右面(后面)命令的输入值以便进一步处理信息。

3.Bash 解释器的通配符中,星号(*)代表几个字符?
零个或多个。

4.PATH 变量的作用是什么?
设定解释器搜索所执行的命令的路径。

5.使用什么命令可以把名为 LINUX 的一般变量转换成全局变量?
export LINUX

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值