2>&1到底是什么意思?

java -jar snapshot.jar > snapshot.log 2>&1 &

Java的朋友一定对上面的命令很熟悉,相信大部分人都知道 >表示的是重定向,那么什么是重定向? 2>&1又是什么意思?

要从根儿上说明这个问题,我们有必要好好理解一下「文件描述符」的概念。

1. 文件描述符

1.1. 什么是文件描述符

文件描述符(File descripter)就是一个整数,这个整数唯一标识了操作系统中某个被打开的”文件”。

1.2. 文件与I/O

说到”文件”必然离不开I/O。

很多人搞不明白I/O到底应该怎么理解,字面上就是输入/输出罢了,但是站在不同角度,其表示的含义也不一样。

站在计算机的角度,I/O表示的是计算机与外界的交互,交互的对象是硬件设备,输入输出自然也指的是和硬件之间的输入输出。

2>&1到底是什么意思?

站在程序的角度,I/O的含义更宽泛,操作系统与所有能被当作文件的对象之间的交互就是I/O。

Linux的哲学思想是「一切皆文件」,文件(file,例如foo.txt)、管道(pipe)、网络(socket),甚至打印机、显示器、磁盘以及命令行(terminal)都算是文件。

文件描述符标识的就是这些文件。

文件描述符这个术语通常出现在Unix或类Unix系统中,比如Linux、MacOS以及BSD等。
在Windows系统中,他有另外一个响当当(或者臭名昭著)的名字—— 句柄(File handle)。

2. 文件描述符原理

2.1. 进程私有文件描述符表

每个进程可以打开多个文件,所以每个进程都会有一个私有的文件描述符表(file descriptors table)。

注:下文称 file descriptors table中的每一个条目为 file descriptor,称 file descriptor中的整数为 fd

需要注意的是,每个进程的fd 012已经被占用(下文会有解释),之后分配的每个进程的 fd3开始。

2>&1到底是什么意思?

进程级的描述符表的每一个条目记录了当前进程所有打开的文件的文件描述符,进程之间相互独立,例如一个进程使用了文件描述符 99,另一个进程也可以用 99

fd只是个数字而已,操作系统肯定需要根据这个数字来找到实际对应的文件。换句话说, file descripter肯定指向了某个表示真实文件的数据结构,或者能够再次根据这个数据结构来找到真实文件。

这个数据结构就是「全局文件表」。

2.2. 全局文件表

全局文件表(global file table),顾名思义,就是所有进程共享的一个数据结构。

当用户进程向内核发起一个针对文件的 system call(比如 open())时,内核将

  1. 允许进程访问;
  2. 向全局文件表(global file table)中插入一个条目,并向进程返回一个指向该条目的一个 file descriptor
  3. 进程将 file descriptor插入到 file descriptors table,并返回其在 file descriptors table中的下标,也就是 fd

2>&1到底是什么意思?

其实,根据global file table并不能直接找到对应文件进行操作,还需要根据其中的指针找到inode table的数据结构,进而再找到最终文件。但是这个技术细节对我们认识文件描述符没有什么作用,于是按下不表了。

2.3. 为什么需要文件描述符

进程进行系统调用的时候,内核为什么不直接返回指向文件的指针呢?反而多此一举加了个 fd来引用文件。

原因是 为了防止用户空间的程序随意读写操作系统内核的文件对象

如果内核直接返回内核中文件对象的地址给进程,进程便可以绕过内核,肆意对该文件进行操作,这样一来用户空间和内核空间的划分便如同虚设。

有了文件描述符之后,由于global file table处于内核空间中,用户即使拥有 fd,也无法得到实际文件对象的地址,除非把 fd作为系统调用的参数来使用,如此一来,控制权又回到了内核手中,也便达到了权限控制的目的。

2>&1到底是什么意思?

3. 标准输入/标准输出/标准错误

前面说到,进程的文件描述符表的前3项已经被默认使用了。

  • 0:标准输入(stdin)
  • 1:标准输出(stdout)
  • 2:标准错误(stderr)

这些名词怎么理解?

我们在Java中使用 new Scanner(System.in)接收从键盘的输入,使用 System.out.println()向显示器写数据,对应C语言分别是 scanf()printf()

需要明确的是, 函数并非直接使用键盘和显示器,而是使用了标准输入和标准输出

说得再通俗一点就是,进程生来就有一个耳朵和两张嘴,耳朵用来接受 标准输入里的数据,一个嘴往 标准输出里边”说话”,另一张嘴往 标准错误里边”吐槽”。

2>&1到底是什么意思?

函数并不知道数据从哪里来,也不关心数据要到哪里去,它们只需要从 标准输入读数据,向 标准输出标准错误中写数据就行了。

这就是抽象啊,朋友们!

默认情况下,操作系统会把所有键盘输入都发送到 标准输入,会把从 标准输出标准错误中读到数据发送到显示器。

2>&1到底是什么意思?

为了方便表示,下文不再将全局文件表画出,而是用一张表来简化表示文件描述符和数据流之间的对应关系。

2>&1到底是什么意思?

接下来我们就可以解释文章开头提的问题了。

4. 输入输出重定向

标准输入/输出/错误在描述表的位置虽然是固定的,但他们指向的数据流是可以改变的。

2>&1到底是什么意思?
java -jar snapshot.jar > snapshot.log 2>&1 &

这条指令的意思就是将 snapshot.jar程序用 >运算符重定向标准输出,由原本的指向显示器改为 snapshot.log文件。

2>是用来重定向标准错误,因为 标准错误在描述符表中的 fd就是 2,同样,其实重定向标准输出也可以表示为 1>,不过一般简写为 >

标准错误标准输出可以重定向到同一个地方,比如指令中的 &1表示的就是 标准输出2>&1的含义就是重定向标准错误到 标准输出表示的数据流中。

完!

Original: https://www.cnblogs.com/chanmufeng/p/16727359.html
Author: 蝉沐风
Title: 2>&1到底是什么意思?

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/579868/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • SpringBoot内置Tomcat启动原理源码分析

    1、获取SpringBoot内置Tomcat自动配置类: 在SpringBoot项目中引入spring-boot-starter-web依赖,就默认使用Tomcat容器,该依赖中引…

    Java 2023年6月7日
    0105
  • 提高学习效率的工具

    浏览器 浏览器:谷歌(推荐,后面都是基于谷歌的,要懂得如何高效地上网)、edge… 插件:SuperCopy(超级复制)、AdBlock(拦截广告)、Tampermon…

    Java 2023年6月5日
    085
  • xen 虚拟机挂了,宿主机假死的问题追终,全思路

    出问题主机工作环境用的是xenserver6.5集群,有一天上去突然发现一台vm连不上了,想着那就上去xenserver重启虚拟机,结果强制重启不能成功,就上去宿主机查询磁盘空间 …

    Java 2023年5月30日
    093
  • sentinel基础概念及使用

    点赞再看,养成习惯,微信搜索「 小大白日志」关注这个搬砖人。 文章不定期同步公众号,还有各种一线大厂面试原题、我的学习系列笔记。 什么是sentinel sentinel是Spri…

    Java 2023年6月8日
    084
  • Docker系列-Docker Hub

    Docker Hub 目前 Docker 官方维护了一个公共仓库 Docker Hub,大部分需求都可以通过在 Docker Hub 中直接下载镜像来实现。 可以通过执行 dock…

    Java 2023年6月8日
    067
  • nginx重新整理——————nginx 模块[十]

    前言 简单介绍一下nginx的模块。 正文 https://nginx.org/en/docs/ 这里面可以看到官方模块。 比如打开这个模块: https://nginx.org/…

    Java 2023年5月30日
    075
  • 使用http代理,解决Java对外请求需固定ip问题

    背景:对接第三方接口,第三方为安全考虑,需要固定ip设置白名单。公司对外使用动态ip。 办法: 购买一台ip固定的服务器,比如云虚拟服务器。搭建http代理服务器,比如prioxy…

    Java 2023年5月29日
    081
  • 终止线程的运行

    终止线程的执行 强制终止用的是stop()方法,因为这种方法会丢失数据,所以一般不采用这种方法。 原理是直接杀死线程,这样的话线程中没有保存的数据就会丢失 /* 在java中强制终…

    Java 2023年6月9日
    0117
  • 基于阿里云的JavaEE系统框架介绍

    基于阿里云的系统框架展望 1) CDN 用于缓存静态文件等等。七牛和阿里的都还可以。 七牛要做的久一点,各种图片处理的接口要完善一些 阿里的CDN要稍微好一点点,但是没有不安全的访…

    Java 2023年5月29日
    079
  • rocketmq实现延迟队列精确到秒级实现方案1-代理实现

    简单的来说,就是rocketmq发送消息到broker的时候,判断是否定时消息, 如果是定时消息,将消息发送到代理服务(这个是一个独立的服务,需要自己开发,定时地把消息发送出去),…

    Java 2023年6月5日
    090
  • Java 顺序查找 二分查找

    查找 在 Java 中我们常用的查找有两种: 顺序查找 即:有一个数组/数列 {“a”, “b”, “c”, “d”} 我们从键盘中输入任意一个 与数组类型相同的值,然后循环遍历这…

    Java 2023年6月5日
    0202
  • oracle创建索引

    数据库索引是为了提高查询速度的一种数据结构。 索引的创建语句 CREATE INDEX 索引名 ON 表名(列名);1除了单列索引,还可以创建包含多个列的复合索引。 CREATE …

    Java 2023年5月29日
    076
  • 千万不要把Request传递到异步线程里面!有坑!

    你好哇,我是歪歪。 前几天在网上冲浪的时候看到一篇技术文章,讲的是他把一个 request 请求传递到了线程池里面,然后遇到了一个匪夷所思的情况。 他写了这篇文章,把自己针对这个问…

    Java 2023年6月5日
    070
  • C++求最长的一条食物链的长度。DFS深度优先算法

    题目描述 如图所示为某生态系统的食物网示意图,据图回答第一小题。 数一数,在这个食物网中最长的食物链包含的物种数是 ( ) …… 现在给你 n 个物种和 m…

    Java 2023年6月5日
    085
  • MySQL系统变量和字符集

    书名《MySQL是怎样运行的:从根儿上理解MySQL》可自行百度 以下是知识点总结 重新认识Mysql MySQL是一个C/S架构的软件。 在Windows安装后首先注册成服务,然…

    Java 2023年6月16日
    071
  • PLG SaaS 产品 Figma 商业模式拆解

    9 月 15 日,Figma 的 CEO Dylan Field 发布消息:今天,Figma 宣布接受 Adobe 的收购… Adobe 以约 200 亿美元收购 Fi…

    Java 2023年6月13日
    067
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球