Linux学习-标准输入输出

本文详细介绍了Linux中的文件描述符,包括标准输入(STDIN)、标准输出(STDOUT)和标准错误(STDERR)。通过文件描述符,可以重定向输入输出,例如将键盘输入替换为文件内容,或将命令输出重定向至文件。同时,文章展示了如何使用`exec`命令创建和管理额外的文件描述符,以及如何使用`lsof`命令查看打开的文件描述符。内容涵盖了输入输出重定向的基本操作和实践应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

标准文件描述符

Linux将每个对象当作文件处理,包括输入和输出进程。Linux用文件描述符(file descriptor)来标识每个文件对象,文件描述符是一个非负整数,可以唯一标识会话中打开的文件。每个进程一次最多可以有九个文件描述符,出于特殊目的考虑bash shell保留了前三个文件描述符(0,1,2)

文件描述符缩写描述
0STDIN标准输入
1STDOUT标准输出
2STDERR标准错误
### STDIN STDIN代表shell的标准输入,对于终端界面来说,标准输入是键盘,shell从STDIN文件描述符对应的键盘获得输入,处理用户输入的信息。 在使用输入重写向符号(<)时,Linux会用重定向指定的文件来替换标准输入文件描述符,它会读取文件并提取数据,就如同键盘输入。
#在命令行中输入cat命令时,会从STDIN接受输入,输入一行,cat命令就会显示出一行
[root@localhost scripts]# cat
123
123
abc
abc
#通过STDIN重定向强制cat接受来自文件的输入
[root@localhost scripts]# cat test
123
123
456
789
[root@localhost scripts]# cat <test
123
123
456
789

STDOUT

STDOUT代表shell的标准输出,在终端界面上,标准输出就是显示器,shell的所有输出会被重定向到标准输出即显示器

[root@localhost scripts]# ls -l >testout
[root@localhost scripts]# cat testout
total 112
-rwxr-xr-x. 1 root root 956 Jan 17 06:23 countUsers.sh
-rwxr-xr-x. 1 root root 455 Jan  9 07:24 createNewUserNew.sh
-rwxr--r--. 1 root root 715 Jan  6 06:08 createNewUser.sh
-rwxr-xr-x. 1 root root  93 Jan  9 07:22 deluser.sh
-rwxr-xr-x. 1 root root 979 Jan 11 07:10 detimateExpire.sh
-rwxr-xr-x. 1 root root 180 Jan 16 07:09 helloeveryone.sh
...
#通过输出重定向符号,通常会将显示到显示器的所有输出重定向至指定的文件,也可能通过【>>】追加到某个文件
[root@localhost scripts]# who >>testout
#tac从后向前查看信息,功能同cat
[root@localhost scripts]# tac testout
root     pts/0        2021-01-24 16:36 (192.168.22.140)
-rwxr-xr-x. 1 root root 119 Jan 16 06:53 test.sh
-rw-r--r--. 1 root root   0 Jan 24 16:43 testout
-rwxr-xr-x. 1 root root 250 Jan 14 05:38 testFileType.sh
-rw-r--r--. 1 root root  70 Jan 23 16:41 testfile
-rw-r--r--. 1 root root 156 Jan 23 18:06 test4.sh
...

STDERR

shell通过特殊的STDERR文件描述符来处理错误信息,shell中运行的脚本和程序出错时的信息都会发送到这个位置。

#badfile不存在
[root@localhost scripts]# ls -al badfile 2>testerror
[root@localhost scripts]# cat testerror
ls: cannot access badfile: No such file or directory
#deluser.sh存在,其它两个文件不存在
[root@localhost scripts]# ls -al deluser.sh badfile badtest 2>testerror
-rwxr-xr-x. 1 root root 93 Jan  9 07:22 deluser.sh
[root@localhost scripts]# cat testerror
ls: cannot access badfile: No such file or directory
ls: cannot access badtest: No such file or directory

重定向错误和数据

如果想重定向错误输出和正常输出,必须用两个重定向符号,需要在符号前面放上待重定向数据所对应的文件描述符,然后指向用于保存数据的输出文件。

#2>表示错误输出重定向,1>表示正常输出重定向
[root@localhost scripts]# ls -al deluser.sh badfile badtest 2>testerror 1>testout
[root@localhost scripts]# cat testout
-rwxr-xr-x. 1 root root 93 Jan  9 07:22 deluser.sh
[root@localhost scripts]# cat testerror
ls: cannot access badfile: No such file or directory
ls: cannot access badtest: No such file or directory
#通过&>将错误和正确输出重定向到同一个文件
[root@localhost scripts]# ls -al deluser.sh badfile badtest &>testout
[root@localhost scripts]# cat testout
ls: cannot access badfile: No such file or directory
ls: cannot access badtest: No such file or directory
-rwxr-xr-x. 1 root root 93 Jan  9 07:22 deluser.sh
#注:shell赋予了错误输出更高的优先级,查看时先显示错误输出

重定向输出

临时重定向输出

如果需要在脚本中生成错误信息,可以单独的一行输出重定向到STDERR,使用输出重定向符来将输出信息重定向到STDERR文件描述符。在重定向到文件描述符时,你必须在文件描述符数字之前加一个&

[root@localhost scripts]# echo "这是一个错误信息" >&2
这是一个错误信息
#默认情况下,Linux会将STDERR导向STDOUT,如果运行脚本时重定向了STDERR,脚本中所有的导向STDERR的文件都会被重定向

```bash
#!/bin/bash
#
echo "这是一个错误..." >&2
echo "这是一个标准输出"

[root@localhost scripts]# bash test5.sh 2>testerror
这是一个标准输出
[root@localhost scripts]# cat testerror
这是一个错误...
永久重定向脚本中的所有命令

如果脚本中有大量数据需要重定向,可以使用exec命令告诉shell在脚本执行期间重定向某个特定文件描述符

#!/bin/bash
#
exec 1>testout
echo "This is a test of redirecting all output"
echo "from a script to another file."
echo "without having to redirect every individual line"
#上述文件中所有的标准输出都被重定向至testout中
[root@localhost scripts]# bash test2.sh
[root@localhost scripts]# cat testout
This is a test of redirecting all output
from a script to another file.
without having to redirect every individual line

#!/bin/bash
#重定向输出至不同位置

exec 2>testerror

echo "脚本开始"
echo "重定向输出至其它位置"

exec 1>testout

echo "输出至testout文件"
echo "输出至testerror文件" >&2

#没有定向重定向输出之前,信息被定向至默认输出(显示器),定向输出后,标准输出信息被输出至testout文件中
[root@localhost scripts]# bash test6.sh
脚本开始
重定向输出至其它位置
[root@localhost scripts]# cat testout
输出至testout文件
[root@localhost scripts]# cat testerror
输出至testerror文件
创建输出文件描述符

通过exec命令为输出分配文件描述符,和标准文件描述符一样,一旦将另一个文件描述符分配给一个文件,这个重定向则会一直有效,直到重新分配。

#!/bin/bash
# 创建输出文件描述符

#将文件描述符3重定向至testout
exec 3>testout

echo "显示到屏幕"
echo "这些将存储到文件" >&3
echo "下面将显示到屏幕下面"
重定向文件描述符
#!/bin/bash
# 

#将文件描述符3重定向至标准输出文件描述符1
exec 3>&1
#将标准输出文件描述符1重定向至文件testout
exec 1>testout

echo "存储至输出文件"
echo "连同这一行"
#重新将标准输出重定向至文件描述符3,重新返回标准输出
exec 1>&3

echo "现在将返回标准输出"

[root@localhost scripts]# bash test7.sh
现在将返回标准输出
[root@localhost scripts]# cat testout
存储至输出文件
连同这一行
列出打开的文件描述符

lsof命令会列出整个Linux系统打开的所有文件描述符,该命令会产生大量输出。
-p 允许指定进程ID(PID)
-d 允许指定要显示的文件描述符编号
可能通过$$变量获得当前进程当前PID

[root@localhost scripts]# echo $$
1562
[root@localhost scripts]# ps -ef | grep 1562
root       1562   1558  0 17:08 pts/0    00:00:00 -bash
root       1616   1562  1 17:27 pts/0    00:00:00 ps -ef
root       1617   1562  0 17:27 pts/0    00:00:00 grep --color 1562

显示当前进程默认的文件描述符(0,1,2)

[root@localhost scripts]# lsof -a -p$$ -d 0,1,2
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
bash    1562 root    0u   CHR  136,0      0t0    3 /dev/pts/0
bash    1562 root    1u   CHR  136,0      0t0    3 /dev/pts/0
bash    1562 root    2u   CHR  136,0      0t0    3 /dev/pts/0

描述
COMMAND正在运行命令的前9个字符
PID进程的PID
USER进程属主的登录名
FD文件描述符号以及访问类型
TYPE文件的类型(CHR表示字符型,BLK表示块型,DIR代表目录,REG代表常规文件)
DEVICE设备的设备号(主设备号和从设备号)
SIZE如果存在表示文件的大小
NODE本地文件的节点号
NAME文件名
#!/bin/bash
#

exec 3> testfile1
exec 6> testfile2
exec 7< testfile

lsof -a -p $$ -d0,1,2,3,6,7

[root@localhost scripts]# bash test8.sh
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
bash    1585 root    0u   CHR  136,0      0t0      3 /dev/pts/0
bash    1585 root    1u   CHR  136,0      0t0      3 /dev/pts/0
bash    1585 root    2u   CHR  136,0      0t0      3 /dev/pts/0
bash    1585 root    3w   REG  253,0        0 919920 /root/scripts/testfile1
bash    1585 root    6w   REG  253,0        0 919936 /root/scripts/testfile2
bash    1585 root    7r   REG  253,0       70 919917 /root/scripts/testfile
#创建了3个替代性文件描述符,两个作为输出(3和6),一个作为输入(7)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值