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

1.重定向技术的 5 种模式

(1)标准覆盖输出重定向

(2)标准追加输出重定向

(3)错误覆盖输出重定向

(4)错误追加输出重定向

(5)输入重定向
2.输入输出重定向

输入重定向:是指把文件导入到命令中

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

➢ 标准输入重定向(STDIN,文件描述符为 0 ):默认从键盘输入,也可从其他文件或命令中输入。

➢ 标准输出重定向(STDOUT,文件描述符为 1 ):默认输出到屏幕。

➢ 错误输出重定向(STDERR,文件描述符为 2 ):默认输出到屏幕。

注:对于重定向中的标准输出模式,可以省略文件描述符 1 不写,而错误输出模式的文件描
述符 2 是必须要写的。

通过标准输出重定向将 man bash 命令原本要输出到屏幕的信息写入到文件 readme.txt 中,然后显示 readme.txt 文件中的内容:

bash 复制代码
[root@localhost Desktop]# man bash > read.txt
[root@localhost Desktop]# cat read.txt 
BASH(1)                     General Commands Manual                    BASH(1)



NAME
       bash - GNU Bourne-Again SHell

SYNOPSIS
       bash [options] [file]

COPYRIGHT
       Bash is Copyright (C) 1989-2011 by the Free Software Foundation, Inc.

DESCRIPTION
       Bash  is  an  sh-compatible  command language interpreter that executes
       commands read from the standard input or from a file.  Bash also incor‐
       porates useful features from the Korn and C shells (ksh and csh).
...

通过覆盖写入模式向 readme.txt 文件写入多行数据(该文件中已包含上一个实验的 man 命令信息):

bash 复制代码
[root@localhost Desktop]# echo "Welcome to linuxprobe" > read.txt 
[root@localhost Desktop]# echo "Welcome to linuxprobe" > read.txt 
[root@localhost Desktop]# echo "Welcome to linuxprobe" > read.txt 
[root@localhost Desktop]# cat read.txt 
Welcome to linuxprobe
[root@localhost Desktop]# 

(注:在通过覆盖写入模式向文件中写入数据时,每一次都会覆盖掉上一次写入的内容,所以最终文件中只有最后一次的写入结果)

再通过追加写入模式向 readme.txt 文件写入一次数据,然后在执行 cat 命令之后,可以看到如下所示的文件内容:

bash 复制代码
[root@localhost Desktop]# echo "quality linux learning" >> read.txt 
[root@localhost Desktop]# cat read.txt 
Welcome to linuxprobe
quality linux learning
[root@localhost Desktop]# 

以一个不存在的文件进行演示:

bash 复制代码
[root@localhost Desktop]# ls -l xx > error.txt 
ls: cannot access xx: No such file or directory
[root@localhost Desktop]# ls -l xxxx 2> error.txt 
[root@localhost Desktop]# cat error.txt 
ls: cannot access xxxx: No such file or directory

还有一种常见情况,就是我们想不区分标准输出和错误输出,只要命令有输出信息则全部追加写入到文件中。这就要用到&>>操作符了:

bash 复制代码
[root@localhost Desktop]# ls -l linuxprobe &>> read.txt 
[root@localhost Desktop]# ls -l xxx &>> read.txt 
[root@localhost Desktop]# ls -l linuxprobe &>> read.txt 
[root@localhost Desktop]# cat read.txt 
Welcome to linuxprobe
quality linux learning
-rw-r--r--. 1 root root 0 Nov  4 10:46 linuxprobe
ls: cannot access xxx: No such file or directory
-rw-r--r--. 1 root root 0 Nov  4 10:46 linuxprobe

输入重定向的作用是把文件直接导入到命令中。接下来使用输入重定向把 readme.txt 文件导入给 wc -l 命令,统计一下文件中的内容行数:

bash 复制代码
[root@localhost Desktop]# wc -l < read.txt 
5
[root@localhost Desktop]# cat read.txt 
Welcome to linuxprobe
quality linux learning
-rw-r--r--. 1 root root 0 Nov  4 10:46 linuxprobe
ls: cannot access xxx: No such file or directory
-rw-r--r--. 1 root root 0 Nov  4 10:46 linuxprobe
[root@localhost Desktop]# 

(注:这次的输出结果与讲解wc命令时不同:没有了文件名称,这是因为此前使用的"wc -l /etc/passwd"是一种非常标准的"命令+参数+对象"的执行格式,而这次的"wc -l < readme.txt"则是将 readme.txt 文件中的内容通过操作符导入到命令中,没有被当作命令对象进行执行,因此 wc 命令只能读到信息流数据,而没有文件名称的信息。)

3.管道命令符:

管道命令符的作用也可以用一句话概括为"把前一个命令原本要输出到屏幕的信息当作后一个命令的标准输入"。按下键盘上的 Shift+反斜杠(\)键即可输入管道符,其执行格式为"命令 A | 命令 B"

把 grep 搜索命令的输出值传递给 wc 统计命令,即把原本要输出到屏幕的用户信息列表再交给 wc 命令作进一步的加工,因此只需要把管道符放到两条命令之间即可,具体如下:

bash 复制代码
[root@localhost Desktop]# grep /sbin/nologin /etc/passwd | wc -l
33

将 ps、grep、管道符三者结合到一起使用,下面搜索与 bash 有关的进程信息:

bash 复制代码
[root@localhost Desktop]# ps aux | grep bash
root       1050  0.0  0.0 115216   932 ?        S    12:36   0:00 /bin/bash /usr/sbin/ksmtuned
root       2104  0.0  0.0  53320   568 ?        Ss   12:36   0:00 /usr/bin/ssh-agent /bin/sh -c exec -l /bin/bash -c "env GNOME_SHELL_SESSION_MODE=classic gnome-session --session gnome-classic"
root       2549  0.0  0.1 116260  3072 pts/0    Ss   12:37   0:00 bash
root      30910  0.0  0.0 112640   980 pts/0    R+   13:27   0:00 grep --color=auto bash

(注:管道命令符不是只能在一个命令组合中使用一次。我们完全可以这样使用:"命令 A | 命令 B | 命令 C")

下述命令将显示系统中所有与 bash 相关的进程信息,并同时将输出到屏幕和文件中:

bash 复制代码
[root@localhost Desktop]# ps aux | grep bash | tee read.txt 
root       1050  0.0  0.0 115216   932 ?        S    12:36   0:00 /bin/bash /usr/sbin/ksmtuned
root       2104  0.0  0.0  53320   568 ?        Ss   12:36   0:00 /usr/bin/ssh-agent /bin/sh -c exec -l /bin/bash -c "env GNOME_SHELL_SESSION_MODE=classic gnome-session --session gnome-classic"
root       2549  0.0  0.1 116260  3072 pts/0    Ss   12:37   0:00 bash
root      30962  0.0  0.0 112644   976 pts/0    S+   13:31   0:00 grep --color=auto bash
[root@localhost Desktop]# cat read.txt 
root       1050  0.0  0.0 115216   932 ?        S    12:36   0:00 /bin/bash /usr/sbin/ksmtuned
root       2104  0.0  0.0  53320   568 ?        Ss   12:36   0:00 /usr/bin/ssh-agent /bin/sh -c exec -l /bin/bash -c "env GNOME_SHELL_SESSION_MODE=classic gnome-session --session gnome-classic"
root       2549  0.0  0.1 116260  3072 pts/0    Ss   12:37   0:00 bash
root      30962  0.0  0.0 112644   976 pts/0    S+   13:31   0:00 grep --color=auto bash

tee命令: 功能是用于读取标准输入的数据,将其内容转交到标准输出设备中,同时保存成文件。

语法格式:tee [参数] 文件名

将用户输入的数据同时写入到两个文件中

bash 复制代码
[root@localhost Desktop]# tee file1 file2
linuxprob.com
linuxprob.com
^C
[root@localhost Desktop]# cat file1
linuxprob.com
[root@localhost Desktop]# cat file2
linuxprob.com
[root@localhost Desktop]# 

执行某个指定的命令,并将其执行结果即输出到屏幕,又写入到文件中:

bash 复制代码
[root@localhost Desktop]# uptime | tee file.txt
 13:37:20 up  1:00,  2 users,  load average: 0.14, 0.12, 0.08

使用标准输出">>"只能输入到文件,不能输出到屏幕:

bash 复制代码
[root@localhost Desktop]# uptime >> file.txt 
[root@localhost Desktop]# cat file.txt 
 13:37:20 up  1:00,  2 users,  load average: 0.14, 0.12, 0.08
 13:38:01 up  1:01,  2 users,  load average: 0.07, 0.10, 0.08

4.命令行的通配符:

通配符就是通用的匹配信息的符号,。Linux 系统中的通配符及含义如下 所示:

匹配所有在/dev 目录中且以 sda开头的文件:

bash 复制代码
[root@localhost Desktop]# ls -l /dev/sda*
brw-rw----. 1 root disk 8, 0 Nov  4  2024 /dev/sda
brw-rw----. 1 root disk 8, 1 Nov  4  2024 /dev/sda1
brw-rw----. 1 root disk 8, 2 Nov  4  2024 /dev/sda2

如果只想查看文件名以 sda 开头,但是后面还紧跟其他某一个字符的文件的相关信息,这时就需要用到问号来进行通配了:

bash 复制代码
[root@localhost Desktop]# ls -l /dev/sda?
brw-rw----. 1 root disk 8, 1 Nov  4  2024 /dev/sda1
brw-rw----. 1 root disk 8, 2 Nov  4  2024 /dev/sda2

除了使用[0-9]来匹配 0~9 之间的单个数字,也可以用[135]这样的方式仅匹配这 3 个指定数字中的一个;若没有匹配到数字 1 或 2 或 3,则不会显示出来:

bash 复制代码
[root@localhost Desktop]# ls -l /dev/sda[0-9]
brw-rw----. 1 root disk 8, 1 Nov  4  2024 /dev/sda1
brw-rw----. 1 root disk 8, 2 Nov  4  2024 /dev/sda2
[root@localhost Desktop]# ls -l /dev/sda[135]
brw-rw----. 1 root disk 8, 1 Nov  4  2024 /dev/sda1

通配符不一定非要放到最后面,也可以放到前面。比如,可以使用下述命令来搜索/etc/目录中所有以.conf 结尾的配置文件有哪些:

bash 复制代码
[root@localhost Desktop]# ls -l /etc/*.conf
-rw-r--r--. 1 root root    55 Jan 29  2014 /etc/asound.conf
-rw-r--r--. 1 root root 21929 Jan 29  2014 /etc/brltty.conf
-rw-r--r--. 1 root root  1157 Feb  6  2014 /etc/chrony.conf
-rw-r--r--. 1 root root  1330 Jan 25  2014 /etc/colord.conf
-rw-r--r--. 1 root root 25213 Jan 25  2014 /etc/dnsmasq.conf
...

通配符不仅可用于搜索文件或代替被通配的字符,还可以与创建文件的命令相结合,一口气创建出好多个文件。不过在创建多个文件时,需要使用大括号,并且字段之间用逗号间隔:

bash 复制代码
[root@localhost Desktop]# touch {AA,BB,CC}.conf
[root@localhost Desktop]# ls -l *.conf
-rw-r--r--. 1 root root 0 Nov  4 13:49 AA.conf
-rw-r--r--. 1 root root 0 Nov  4 13:49 BB.conf
-rw-r--r--. 1 root root 0 Nov  4 13:49 CC.conf

使用通配符还可以输出一些指定的信息:

bash 复制代码
[root@localhost Desktop]# echo file{1,2,3,4,5}
file1 file2 file3 file4 file5

5.常用的转义字符

为了能够更好地理解用户的表达,Shell 解释器还提供了特别丰富的转义字符来处理输入的特殊数据。4 个最常用的转义字符如下所示:

➢ 反斜杠(\):使反斜杠后面的一个变量变为单纯的字符。

➢ 单引号(' '):转义其中所有的变量为单纯的字符串。

➢ 双引号(" "):保留其中的变量属性,不进行转义处理。

➢ 反引号(` `):把其中的命令执行后返回结果。

先定义一个名为 PRICE 的变量并赋值为 5,然后输出以双引号括起来的字符串与变量信息:

bash 复制代码
[root@localhost Desktop]# PRICE=5
[root@localhost Desktop]# echo "Price is $PRICE"
Price is 5

我们希望能够输出"Price is 5",即"价格是 5 美元"的字符串内容,但碰巧美元符号与变量提取符号合并后的$作用是显示当前程序的进程 ID 号码,于是命令执行后输出的内容并不是我们所预期的:

bash 复制代码
[root@localhost Desktop]# echo "Price is $$PRICE"
Price is 2549PRICE

要想让第一个"$"乖乖地作为美元符号,那么就需要使用反斜杠(\)来进行转义,将

这个命令提取符转义成单纯的文本,去除其特殊功能:

bash 复制代码
[root@localhost Desktop]# echo "Price is \$$PRICE"
Price is $5

而如果只需要某个命令的输出值,可以像`命令`这样,将命令用反引号括起来,达到预

期的效果。例如,将反引号与 uname -a 命令结合,然后使用 echo 命令来查看本机的 Linux 版

本和内核信息:

bash 复制代码
[root@localhost Desktop]# echo `uname -a`
Linux localhost.localdomain 3.10.0-123.el7.x86_64 #1 SMP Mon May 5 11:16:57 EDT 2014 x86_64 x86_64 x86_64 GNU/Linux

反斜杠和反引号的功能比较有特点,同学们一般不会犯错,但对于什么时候使用双引号却容易混淆,因为在大多数情况下好像加不加双引号,效果都一样。(小技巧:如果参数中出现了空格,就加双引号;如果参数中没有空格,那就不用加双引号。)

6.重要的环境变量

变量是计算机系统用于保存可变值的数据类型。在 Linux 系统中,变量名称一般都是大写的,命令则都是小写的,这是一种约定俗成的规范。Linux 系统中的环境变量是用来定义系统运行环境的一些参数,比如每个用户不同的家目录、邮件存放位置等。可以直接通过变量名称来提取到对应的变量值。

命令在 Linux 中的执行分为 4 个步骤:

**第一步:**判断用户是否以绝对路径或相对路径的方式输入命令(如/bin/ls),如果是绝对路径则直接执行,否则进入第 2 步继续判断。

**第二步:**Linux 系统检查用户输入的命令是否为"别名命令",即用一个自定义的命令名称来替换原本的命令名称。

**第三步:**Bash 解释器判断用户输入的是内部命令还是外部命令。内部命令是解释器内部的指令,会被直接执行;而用户在绝大部分时间输入的是外部命令,这些命令交由步骤 4 继续处理。可以使用"type 命令名称"来判断用户输入的命令是内部命令还是外部命令:

bash 复制代码
[root@localhost Desktop]# type echo
echo is a shell builtin
[root@localhost Desktop]# type uptime
uptime is hashed (/usr/bin/uptime)

第四步: 系统在多个路径中查找用户输入的命令文件,而定义这些路径的变量叫作 PATH,

可以简单地把它理解成是"解释器的小助手",作用是告诉 Bash 解释器待执行的命令可能存

放的位置,然后 Bash 解释器就会乖乖地在这些位置中逐个查找。PATH 是由多个路径值组成

的变量,每个路径值之间用冒号间隔,对这些路径的增加和删除操作将影响到 Bash 解释器对

Linux 命令的查找。

bash 复制代码
[root@localhost Desktop]# echo $PATH
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/root/bin

经典的问题:"为什么不能将当前目录(.)添加到 PATH 中呢?"

答:尽管可以将当前目录(.)添加到 PATH 变量中,从而在某些情况下可以让用户免去输入命令所在路径的麻烦。但是,如果黑客在比较常用的公共目录/tmp 中存放了一个与 ls 或 cd 命令同名的木马文件,而用户又恰巧在公共目录中执行了这些命令,那么就极有可能中招了。 所以,作为一名态度谨慎、有经验的运维人员,在接手一台 Linux 系统后一定会在执行命令前先检查 PATH 变量中是否有可疑的目录。我们可以使用 env 命令来查看 Linux 系统中所有的环境变量。

使用下述命令来查看 HOME 变量在不同的用户身份下都有哪些值(su 是用于切换用户身份的命令):

bash 复制代码
[root@localhost Desktop]# echo $HOME
/root
[root@localhost Desktop]# su - linuxprobe
[linuxprobe@localhost ~]$ echo $HOME
/home/linuxprobe

设置一个名称为 WORKDIR 的变量,方便用户更轻松地进入一个层次较深的目录:

bash 复制代码
[root@localhost ~]# mkdir /home/workdir
[root@localhost ~]# WORKDIR=/home/workdir
[root@localhost ~]# cd $WORKDIR
[root@localhost workdir]# pwd
/home/workdir

如果工作需要,可以使用 export 命令将其提升为全局变量,这样其他用户也就可以使用它了:

bash 复制代码
[root@localhost ~]# export WORKDIR
[root@localhost ~]# su linuxprobe
[linuxprobe@localhost root]$ cd $WORKDIR
[linuxprobe@localhost workdir]$ pwd
/home/workdir

后续要是不使用这个变量了,则可执行 unset 命令把它取消掉:(注:直接在终端设置的变量能够立即生效,但在重启服务器后就会失效,因此我们需要将变量和变量值写入到.bashrc 者.bash_profile 文件中,以确保永久能使用它们。)

bash 复制代码
[root@localhost ~]# unset WORKDIR 
[root@localhost ~]# cd $WORKDIR
[root@localhost ~]# 
相关推荐
cominglately1 小时前
centos单机部署seata
linux·运维·centos
魏 无羡1 小时前
linux CentOS系统上卸载docker
linux·kubernetes·centos
CircleMouse1 小时前
Centos7, 使用yum工具,出现 Could not resolve host: mirrorlist.centos.org
linux·运维·服务器·centos
木子Linux2 小时前
【Linux打怪升级记 | 问题01】安装Linux系统忘记设置时区怎么办?3个方法教你回到东八区
linux·运维·服务器·centos·云计算
mit6.8242 小时前
Ubuntu 系统下性能剖析工具: perf
linux·运维·ubuntu
鹏大师运维2 小时前
聊聊开源的虚拟化平台--PVE
linux·开源·虚拟化·虚拟机·pve·存储·nfs
watermelonoops2 小时前
Windows安装Ubuntu,Deepin三系统启动问题(XXX has invalid signature 您需要先加载内核)
linux·运维·ubuntu·deepin
滴水之功3 小时前
VMware OpenWrt怎么桥接模式联网
linux·openwrt
ldinvicible4 小时前
How to run Flutter on an Embedded Device
linux
YRr YRr4 小时前
解决Ubuntu 20.04上编译OpenCV 3.2时遇到的stdlib.h缺失错误
linux·opencv·ubuntu