管道与重定向
前言
之前我们讨论进程管理的时候就已经运用到了管道和重定向的部分,这里我们来详细的探讨关于管道和重定向相关的知识。
一、重定向
1.利用 > 将操作显示的信息重定向输入到文件中
以date操作为例子,我们在shell中输入date之后会输出目前系统的时间:
date
Wed Jan 27 09:02:50 CST 2021
但是我们可以知道,date命令两次输入,输出的结果肯定是不同的,如果我们在重启之后再次输入date是不可能获得重启之前的输出的。
我们可以用重定向将命令的输出存储到文本文档中:
date > time.txt
我们可以把这个 > 当作是一个传输的符号,把输出的字符从date指令传输到time.txt文件中。
之后我们便在当前的工作目录下创建了一个名字为time.txt的文件,里面存储着date命令输出的字符。
2. FD简介
FD即为 file descriptors,文件描述符,也叫文件句柄。进程使用文件描述符来管理打开的文件。
一个进程如果要使用文件路径的时候,就会用FD来标注(起一个代号),调用文件的时候会更加方便,这就创建了一个软连接。FD的每一个代号都会和一个特定的文件路径相关联(FD为1,2,3,4,5……)
FD的数字范围为0-255, 0表示标准输入,是键盘只读,1为标注输出,2为标准错误,3,4,5,6……为其他文件。
下面我们可以用vim来观察一个进程的FD信息:
首先我们先打开第一个终端,打开一个文本:
vim 1.txt
接着,在另外一个终端里面用ps来查找这个打开文本的进程ID:
pa aux | grep vim
root 2878 0.0 0.2 149504 5332 pts/0 S+ 09:21 0:00 vim 1.txt
root 2952 0.0 0.0 112808 960 pts/1 R+ 09:22 0:00 grep --color=auto vim
(我这里显示的进程号为2878)。
接着,我们可以查看上一个文章中说到的proc目录来查看程序的FD:
cd /proc/
#在这个目录里面可以看见一个目录名为2878(你的进程ID)
cd 2878/
#在这个进程的文件目录里面有一个叫做fd的目录
cd fd/
#在fd目录中可以看到有 0 1 2 3 四个链接文件。
如果我们用ll来显示这四个链接的详细信息,可以看到:
ll
lrwx------. 1 root root 64 Jan 27 09:25 0 -> /dev/pts/0
lrwx------. 1 root root 64 Jan 27 09:25 1 -> /dev/pts/0
lrwx------. 1 root root 64 Jan 27 09:22 2 -> /dev/pts/0
lrwx------. 1 root root 64 Jan 27 09:25 3 -> /root/Desktop/.1.txt.swp
前面三个pts/0即为我们打开的0号终端(标准输入,输出和标准错误),第四个就是这个进程查看的1.txt文件。
那么有了这个概念之后,我们既可以试一下如下的操作:
echo 1234 > /dev/pts/0 #在第二个打开的终端执行这个命令
我们如果在1号终端里输入这个命令,可以看到1号终端没有输出,0号终端输出了1234。这就是把echo的输出重定向到了0号终端的文件。
3. 重定向及综合案例
在了解了重定向和FD之后,我们可以用FD的代号来对进程的FD的结果进行重定向。
我们知道1为FD的标准输出,所以在一开始我们的date重定向的命令中,我们可以用如下代替:
date 1> /dev/pts/0 #同样在第二个打开的终端进行操作
可以看到在第一个终端里输出了目前的系统时间。这里就是我们把标准输出重定向到了0号终端。
1> 的重定向符号,和一般的重定向符号 > 是等价的。
1>> 的重定向符号,和一般的重定向符号 >> 是等价的。
(一个>表示输出会覆盖原有的文件,两个>>表示输出会在末尾追加,不会覆盖之前的文件)。
2> 和 2>> 这两个错误输出重定向是没有简写的。
在没有错误输出的时候,将错误输出重定向到文件,文件中是没有信息的:
ls 2> ls.txt
ls.txt中不会有输出,因为ls输出的当前目录下的文件都是标准输出。
之有有错误输出的时候才会重定向:
ls /aaaaaaaaaaaaaaaaaaaaaa 2> ls.txt
这个时候ls.txt中就会有重定向的错误输出,显示没有名字为aaaaaaaaaaaaaaaaaaaaaa的文件或目录。
我们可以用 &> 操作符把标准输出和错误输出都重定向到同一个文件中:
ls /home/ /adsfdsgsdfdasfdas &> ls.txt
这样在ls.txt中,既会显示home目录下的文件和目录,也会显示没有名字为adsfdsgsdfdasfdas的文件或目录的报错信息。
我们也可以分开令其进行重定向:
ls /home/ /adsfdsgsdfdasfdas 1> yes.txt 2> no.txt
这样标准输出和错误输出分别重定向到两个txt文件中。
4.将输入进行重定向
我们可以把重定向的符号返过来,变成 < ,就可以把文件的内容当作输入,输入到命令中:
mail -s "test01" alice < word.txt
我们便给alice发了一封内容为word.txt文件内容的邮件。
二、管道
管道可以将多条命令组合起来,一次性完成复杂的处理任务。
1.管道的基本使用
语法:
command1|command2|command3
command1的标准输出信息会作为command2的标准输入,command2根据输入,运行进行标准输出到command3,command3就会将输出输出到终端中。
比如之前我们在用户管理中用到的命令:
cat /etc/passwd | head -3
在这里我们cat passwd文件的结果传输到head指令中,head指令只把passwd的前三行显示出来。
同时在我们进程管理中,也用到了管道:
ps aux | grep root
ps aux将所有的进程信息传递给grep指令,grep命令在这些信息中寻找root用户创建的进程。
同时我们可以有多个管道:
ps aux | grep root | head -1
只显示第一个root用户创建的进程。
2.tee管道
tee管道可以理解成为一个三通。我们在一般的管道中有如下格式:
command1|command2
如果把command1和command2理解为两个水管,中间的 | 操作符就是连接两根水管的软管,那么有tee管道就会形成一个三通:
command1| tee 1.txt | command2
在这里command1的输出不仅作为command2的输出,同时也重定向到了1.txt文件中。
比如如下的例子:
cat /etc/passwd | tee 1.txt | tail -1
在终端中,只会显示passwd文件的最后一行,但是在文件1.txt中,所有passwd的信息都被存储。
3. 参数传递Xargs
在linux系统中,有一些命令不支持输入重定向和管道,比如 cp,rm,mkdir等。
比如:
cat files.txt | rm -rvf
单纯这样进行管道是不会删除文件的,因为rm指令不支持管道。
需要如下指令:
cat files.txt | xargs rm -rvf
这样将cat的结果当作参数传递给rm指令,由于我们给rm指令选择了-v选项,可以看到删除成功的提示。
总结
本文我们讨论了管道与重定向的相关知识,包括输出重定向,输出重定向和FD的重定向,以及指令之间的管道操作等,下面我们将会讨论磁盘管理相关的知识。