Bash的基本特性之标准输入输出和文件描述符

标准输入(stdin)

标准输入(standard input)指的是输入给要执行命令的数据,通常是键盘的输入,或者是文件中的数据。命令程序要求以读(read)的方式来传输数据。

1
2
3
4
5
6
[user1@study ~]$ read -p 'Please input a number: ' user_number; echo "Your number is ${user_number}"
Please input a number: 1234
Your number is 1234
[user1@study ~]$ cat file.txt
Hello world !
[user1@study ~]$

并不是所有的命令都要求有输入,例如 lsdf 在执行时不需要任何输入

1
2
3
4
5
6
7
8
9
10
11
12
[user1@study ~]$ ls 
file2.txt file3.txt file.bak file.txt nginx1.log nginx2.log nginx3.log nginx4.log nginx5.log
[user1@study ~]$ df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda3 18707456 1534712 17172744 9% /
devtmpfs 921652 0 921652 0% /dev
tmpfs 932640 0 932640 0% /dev/shm
tmpfs 932640 9560 923080 2% /run
tmpfs 932640 0 932640 0% /sys/fs/cgroup
/dev/sda1 201380 114428 86952 57% /boot
tmpfs 186532 0 186532 0% /run/user/0
[user1@study ~]$

标准输入的文件描述符为 0

1
2
3
[user1@study ~]$ ls -l /dev/stdin 
lrwxrwxrwx 1 root root 15 Jul 14 2015 /dev/stdin -> /proc/self/fd/0
[user1@study ~]$

标准输出(stdout)

标准输出(standard output)指的是所执行的命令所输出数据,默认输出到屏幕。命令要求以写(write)操作来传输数据。

1
2
3
[user1@study ~]$ echo 'Hello world'
Hello world
[user1@study ~]$

并不是所有的命令都要求输出。如 mvtouch 程序在成功完成时不会输出任何东西

1
2
3
[user1@study ~]$ touch test.txt
[user1@study ~]$ mv test.txt{,.bak}
[user1@study ~]$

标准输出的文件描述符为 1

1
2
3
[user1@study ~]$ ll /dev/stdout 
lrwxrwxrwx 1 root root 15 Jul 14 2015 /dev/stdout -> /proc/self/fd/1
[user1@study ~]$

标准错误输出(stderr)

标准错误输出是另外一种输出流,用于输出执行命令的错误消息。它独立于标准输出,并且可以分别被重导。默认的输出位置也是屏幕

1
2
3
4
5
6
[user1@study ~]$ date +'%F %T'
2015-07-13 20:31:26
[user1@study ~]$ date +%F %T
date: extra operand ‘%T’
Try 'date --help' for more information.
[user1@study ~]$

即便是标准输出被重导也是会输出到屏幕,最典型的例子就是管道,一个管道中的命令的输出被重导到下一个命令,但错误消息仍然直接输出到屏幕

1
2
3
4
5
6
[user1@study ~]$ date +'%F %T' | grep 2015
2015-07-13 20:33:53
[user1@study ~]$ date +%F %T | grep 2015
date: extra operand ‘%T’
Try 'date --help' for more information.
[user1@study ~]$

标准错误输出的文件描述子为 2

1
2
3
[user1@study ~]$ ls -l /dev/stderr 
lrwxrwxrwx 1 root root 15 Jul 14 2015 /dev/stderr -> /proc/self/fd/2
[user1@study ~]$

文件描述符

上面提到了三个文件描述符,在 Linux 系统启动后,会默认打开这三个文件描述符,分别是:0(标准输入 stdin),1(标准输出 stdout),2(标准错误输出 stderr)。

究竟什么是文件描述符呢?我们可以理解为 linux 跟踪打开文件而分配的一个数字,这个数字有点类似 C 语言操作文件时候的句柄,通过句柄就可以实现文件的读写操作。

打开文件后新增文件绑定描述符可以依次增加。每条 shell 命令执行,都会继承父进程的文件描述符。因此所有运行的 shell 命令默认都会有这三个文件描述符。

命令执行前会事先准备好所有输入输出,默认分别绑定(stdin,stdout,stderr),如果这个时候出现错误,命令将终止,不会执行。

对于任何一条 shell 命令执行,它会是这样一个过程:

有钱任性,请我吃包辣条
0%