linux分享之浅谈标准输入输出

问题

  • fd是什么
  • tty/pty是什么
  • stdin/stdout分别是什么
  • nohup执行命令的stdin是什么
  • ./test.sh > test.log发生了什么
  • ./test.sh > test.log 2>&1是什么意思
  • ./test.sh > /dev/null是什么意思

终端

tty

终端是一种字符型设备,它有多种类型,通常使用tty来简称各种类型的终端设备

pty

如果我们远程ssh到主机会自动开启虚拟终端pty(pseudo-tty)

可通过命令 tty查看当前终端

[root@k8s-master fd]# ls -all /dev/pts/2
crw--w----. 1 root tty 136, 2 1月   9 03:46 /dev/pts/2

发现/dev/pts/2为字符设备

操作

echo "test" > /dev/pts/2

fd

  • 开启某窗口执行
tail  -f  xxx
  • 在另一容器中查看fd
[root@k8s-master fd]# ls -all
总用量 0
dr-x------. 2 root root  0 1月   9 03:56 .
dr-xr-xr-x. 9 root root  0 1月   9 03:56 ..
lrwx------. 1 root root 64 1月   9 03:56 0 -> /dev/pts/1
lrwx------. 1 root root 64 1月   9 03:56 1 -> /dev/pts/1
lrwx------. 1 root root 64 1月   9 03:56 2 -> /dev/pts/1
lr-x------. 1 root root 64 1月   9 03:56 3 -> /root/ifconfig.log

fd

linux中, 每一个进程在内核中,都对应有一个“打开文件”数组,存放指向文件对象的指针,而 fd 是这个数组的下标。
在该fd集合中,固定0为标准输入 1为标准输出 2为异常输出即stderr

int main()
{
    int fd1,fd2;
    
    fd2 = open("p1.py",O_RDONLY,0);
    dup2(fd2,0);
    char c;
    while( read(0,&c,1) > 0)
        printf("%c",c);
    close(fd2);

    fd1 = open("/dev/stdin",O_RDONLY);

    printf("%d\n",fd1);
    while( read(fd1, &c, 1) > 0)
        printf("%c",c);

    return 0;
}

标准输入输出

stdin&stdout

ll /dev/
···
lrwxrwxrwx 1 root root          15 Dec  7  2018 stderr -> /proc/self/fd/2
lrwxrwxrwx 1 root root          15 Dec  7  2018 stdin -> /proc/self/fd/0
lrwxrwxrwx 1 root root          15 Dec  7  2018 stdout -> /proc/self/fd/1
···

proc/self

ls -all proc/self
lrwxrwxrwx. 1 root root 0 1月  10 2020 /proc/self -> 22195

演示

nohup执行命令的标准输入是什么

nohup ./test.sh &
l-wx------. 1 root root 64 1月   9 04:26 0 -> /dev/null
l-wx------. 1 root root 64 1月   9 04:26 1 -> /home/kevin/inout/nohup.out
l-wx------. 1 root root 64 1月   9 04:26 2 -> /home/kevin/inout/nohup.out
  • 当执行nohup时,标准输入为/dev/null
  • 标准输出至 nohup.out文件中

./test.sh > test.log

lrwx------. 1 kevin kevin 64 1月   9 04:30 0 -> /dev/pts/2
l-wx------. 1 kevin kevin 64 1月   9 04:30 1 -> /home/kevin/inout/test.log
lrwx------. 1 kevin kevin 64 1月   9 04:29 2 -> /dev/pts/2

标准输出调整为test.log

./test.sh > test.log 2>&1是什么意思

lrwx------. 1 kevin kevin 64 1月   9 04:31 0 -> /dev/pts/2
l-wx------. 1 kevin kevin 64 1月   9 04:31 1 -> /home/kevin/inout/test.log
l-wx------. 1 kevin kevin 64 1月   9 04:31 2 -> /home/kevin/inout/test.log

标准输出和异常输出调整为test.log

./test.sh > /dev/null是什么意思

lrwx------. 1 kevin kevin 64 1月   9 04:32 0 -> /dev/pts/2
l-wx------. 1 kevin kevin 64 1月   9 04:32 1 -> /dev/null
lrwx------. 1 kevin kevin 64 1月   9 04:31 2 -> /dev/pts/2

抛弃标准输出

总结

  • linux上一切皆文件,包括字符设备 块设备 socket等
  • 每开启一个ssh容器,即会创建一个虚拟终端 pty
  • linux dev和proc下很多文件均为链接,如/proc/self,stdin stdout等
  • linux每个线程都维护有一组fd的集合,其中0 1 2为输入输出及异常输出
  • 通过一个进程的标准输入输出均为pts,但是如果使用了nohup或者 > 会改变输入输出源
  • 在java程序中使用logback时,会配置logback日志的输出端,如ConsoleAppender即为标准输出