跳到主要内容

输入输出与管道

本节我们熟悉bash中的输入输出和管道的操作。

标准输入输出

当一个bash进程启动的时候会产生一个进程id即pid,每个pid下面会打开若干文件,一个文件对应一个文件描述符,由一个数字表示。默认情况下,保留有三个特殊含义的数字0、1、2,分别表示标准输入(stdin),标准输出(stdout)和标准错误(stderr),当启动一个bash进程的时候以上三个文件描述符默认打开,如果我们要打开新的文件描述符而又不和这三个冲突的话就需要从3开始。bash中默认的标准输入是键盘,标准输出和标准错误是屏幕,我们可以对标准输入输出进行重定向。 下面通过一个示例来了解bash中如何操作输入输出:

# 从键盘获取输入,赋值到变量str1
read -p 'input plz: ' str1
# 将变量值输出到标准输出
echo $str1
# 将变量值输出到标准错误
echo $str1 >&2

看一下执行结果:

io

以上通过read命令和echo命令演示了最简单的方式操作标准输入、标准输出和标准错误。

重定向

输入、输出都支持重定向,意思是输入不用键盘而改用其他的,输出也不到屏幕了而是输出到别的地方,例如:

date >/dev/null

上面把date命令的输出重定向到了null黑洞文件,这样屏幕上就不会输出了。

重定向符号 <> 与输入输出的对应关系如下表所示:

标准文件文件描述符重定向符号
stdin0<
stdout11>
stderr22>

其中 > 默认不带数字就标准输出,所以 1> 中的 1 可以省略。除了此以外还有更多的重定向符号,常见的有:

符号作用
>覆盖模式
>>追加模式
&>同时重定向标准输出和标准错误,覆盖模式
&>>同上,追加模式
2>&1标准错误重定向到标准输出
>&2重定向标准输出到标准错误

下面举个例子:

#!/bin/bash

log() {
    echo "$*" >>a.log
}

log "$(date)"
log "$(data 2>&1)"

执行看下效果:

redirect

可以看到log函数把输入重定向到a.log文件,第一行log把date命令的标准输出记录下来,第二行log后面因为执行的一个无效的命令,因此会产生标准错误,使用了重定向把它输出到了标准输出,否则会直接输出到屏幕。

管道

讲到输入输出就不得不提及管道,管道符 | 用于连接两个命令使得管道左边命令的标准输出作为管道后边命令的标准输入。管道在bash脚本编程中会经常用到,因为很多常用命令都能接收标准输入,通过管道连接不同的命令组合可以很方便地把不同的“零部件”拼接成各式各样的功能模块。下面通过例子感受下管道的用途:

# 输出磁盘使用百分比最大的挂载点
df -P | sort -n -k5 | tail -1 | awk '{print $NF}'
# 杀死所有含httpd关键字的进程
ps -ef | grep httpd | grep -v grep | awk '{print $2}' | xargs kill

可以看到通过管道连接多个命令可以很方便的进行一系列的组合操作,而不需要再单独管理每个命令的输出,这极大提升了组合拼装的效率。

需要注意的是管道符|默认只能往右边传标准输出,而想要把标准错误也一起传过去则需要使用 |& ,或者提前将标准错误重定向到标准输出,例如:

美女 |& 野兽
美女 2>&1 | 野兽