Linux开发讲课18--- “>file 2>1“ 和 “2>1 >file“ 的区别

        在 Bash 脚本和命令行操作中,输出重定向是一项基本且强大的功能。它允许用户控制命令的输出流,将数据从一个地方转移到另一个地方,实现更加灵活和高效的工作流程。本文旨在记录 Bash 中几种常见的输出重定向方法,包括:

        

-. > file

-. >file 2>&1 vs 2>&1 >file

-. | (pipe)

2. 基本概念

文件描述符(File Descriptor, FD)是 Unix 和 Unix-like 操作系统中的基本概念,用于表示一个进程打开的文件、管道、套接字或其他输入/输出资源。每个进程都有一个文件描述符表,管理其所有打开的文件。其中,对于系统管理员来说,STDIN、STDOUT 和 STDERR 这几个术语应该很熟悉,对应于程序内的三个文件描述符:0、1 和 2。

STDIN、STDOUT 和 STDERR 是三个标准的输入输出流,是操作系统为进程提供的默认输入和输出机制:

标准输入(STDIN):

  • 描述:STDIN 是标准输入流,通常从键盘输入

  • 文件描述符:0

  • 默认来源:键盘

  • 作用:用于从用户或其他进程读取输入数据

  • 示例:

    root@jpzhang-dev:~# read name
    jpzhang
    root@jpzhang-dev:~# echo "Hello, $name"
    Hello, jpzhang
    

    在这个示例中,read name 从 STDIN 读取用户输入。

标准输出(STDOUT):

  • 描述:STDOUT 是标准输出流,通常显示在屏幕上

  • 文件描述符:1

  • 默认目标:终端(屏幕)

  • 作用:用于向用户或其他进程输出数据

  • 示例:

    ls non_existent_file
    

    在这个示例中,ls 命令会尝试列出一个不存在的文件,并将错误消息输出到 STDERR。

  • 实际上,在程序中执行文件操作时,会生成新的文件描述符,通常从 3、4、5 开始,依次类推。内置的 0、1、2 最初并不指向任何文件,而是指向 /dev/tty。这意味着应用程序可以通过 STDIN 从 tty 向程序发送数据,反之亦然,它可以通过 STDOUT 和 STDERR 向 /dev/tty 输出不同类型的输出。

    以下面脚本为例:test.sh

    #!/bin/bash
    echo "Hello stdout"
    echo "Hello stderr" 1>&2
    

    向 STDOUT 输出 "Hello stdout",向 STDERR 输出 "Hello stderr"。

    执行脚本如下:

    root@jpzhang-dev:/home/workspace/linux/std# bash test.sh
    Hello stdout
    Hello stderr
    

    因此,在默认条件下,两者的关系如下:

                ​​​​​​​        ​​​​​​​        

3. 输出重定向

以下是几种常见的输出重定向方法及其用途:

3.1 > file

将标准输出(STDOUT)重定向到文件。如果文件不存在,则创建该文件,如果文件存在,则覆盖该文件的内容。

echo "Hello, World!" > output.txt

这个命令将字符串 "Hello, World!" 输出到 output.txt 文件中。

3.2 >file 2>&1 与 2>&1 >file

"> file" 和 "2>&1" 是重定向的语法,用于分别控制标准输出(stdout)和标准错误输出(stderr)。理解 ">file 2>&1" 和 "2>&1 >file" 需要理解命令重定向的顺序以及它们各自的作用。

3.2.1 >file 2>&1

">file 2>&1" 命令解释:

  • "> file":将标准输出重定向到 file 文件;

  • "2>&1":将标准错误输出重定向到标准输出(在这时,标准输出已经被重定向到 file);

因此,所有的输出(标准输出和标准错误输出)都会被重定向到 file 文件中。

3.2.2 2>&1 >file

"2>&1 >file" 命令解释:

  • "2>&1":将标准错误输出重定向到标准输出(在这时,标准输出还指向终端);

  • "> file":将标准输出重定向到 file 文件;

在这个顺序中,标准错误输出仍然重定向到原始的标准输出(终端),而标准输出被重定向到 file 文件。结果是:

  • 标准输出被重定向到 file 文件;

  • 标准错误输出仍然输出到终端;

3.2.3 具体示例

假设命令 ls non_existent_file 会产生一个标准错误输出。

  • 使用 > file 2>&1

ls non_existent_file > output.txt 2>&1

在 output.txt 文件中,你会看到标准错误信息:

root@jpzhang-dev:/home/linux/std# cat output.txt
ls: 无法访问 'non_existent_file': 没有那个文件或目录
  • 使用 2>&1 > file

ls non_existent_file 2>&1 > output.txt

在 output.txt 文件中将会是空的,因为标准输出重定向到文件,而标准错误输出仍然显示在终端:

root@jpzhang-dev:/home/linux/std# ls non_existent_file 2>&1 > output.txt
ls: 无法访问 'non_existent_file': 没有那个文件或目录
root@jpzhang-dev:/home/linux/std# cat output.txt
3.2.4 小结
  • >file 2>&1:将标准输出和标准错误都重定向到 file;

  • 2>&1 >file:将标准输出重定向到 file,标准错误输出仍然显示在终端;

顺序在这里是关键,因为重定向是从左到右执行的,所以不同的顺序会导致不同的结果。

3.3 | (pipe)

管道(pipe)用于将一个命令的标准输出作为下一个命令的标准输入。

ls -l | grep "txt"

这个命令将 ls -l 的输出通过管道传递给 grep "txt" 命令,从而过滤出包含 "txt" 的行。

4. 示例分析

4.1 示例 1

将输出重定向到文件,可以使用 ">",后面跟上文件名。例如,"pwd > my_test" 执行 pwd 命令,并将 STDOUT 的内容重定向到文件 "my_test"。

如前所述,STDOUT 和 STDERR 分别对应数字 1 和 2。因此,使用 "2> my_test" 表示将 STDERR 的内容重定向到文件。

用 test.sh 脚本演示:

root@jpzhang-dev:/home/linux/std# bash test.sh > test_out
Hello stderr

root@jpzhang-dev:/home/linux/std# cat test_out
Hello stdout

在上例中,STDOUT 被重定向到文件 "test_out",因此执行后,"Hello stderr" 仍会输出到 /dev/tty,而 "Hello stdout" 则会写入文件。

如果使用 "2>",结果就会相反:

root@jpzhang-dev:/home/linux/std# bash test.sh 2> test_out2
Hello stdout

root@jpzhang-dev:/home/linux/std# cat test_out2
Hello stderr

文件输出本身可以一起使用,例如:

root@jpzhang-dev:/home/linux/std# bash test.sh > test_out 2> test_out2
root@jpzhang-dev:/home/linux/std# cat test_out
Hello stdout

root@jpzhang-dev:/home/linux/std# cat test_out2
Hello stderr

除了单独输出到文件外,还可以引用其他文件描述符。例如,使用 "2>&1" 可将 STDERR 重定向到 STDOUT。由于 "2>1" 的意思是 "将 STDERR 重定向到文件 1",因此添加"&1" 是为了引用 STDOUT,而不是文件。

整个概念如下,但由于当前输出是 /dev/tty,因此在使用上可能没有明显的区别:

        ​​​​​​​        ​​​​​​​        ​​​​​​​        

root@jpzhang-dev:/home/linux/std# bash test.sh 1>&2
Hello stdout
Hello stderr

下面是实现 "2>&1",将 STDERR 重定向到 STDOUT 的 C 代码示例:

#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<unistd.h>

int main()
{
        fwrite("For stdout\n", 11, 1, stdout);
        fwrite("For stderr\n", 11, 1, stderr);

        dup2(STDOUT_FILENO, STDERR_FILENO);

        fwrite("To Stdout \n", 11, 1, stdout);
        fwrite("To Stderr \n", 11, 1, stderr);
        return 0;
}

执行 “dup2(STDOUT_FILENO, STDERR_FILENO);” 之后,所有输出到 stderr 的内容都将重定向到与 stdout 相同的输出。

4.2 示例 2

在了解 STDOUT 和 STDERR 之后,一个常见的要求是将 STDOUT 和 STDERR 写入同一个文件,其逻辑如下:

  • 合并 stdout 和 stderr 的输出;

  • 将合并结果输出到文件中;

因此,常见的解决方案是 "> file 2>&1", 错误用法是 "2>&1 > file" 两者虽看起来非常相似,但内在逻辑却不同;

首先,对于 "> file 2>&1",逻辑可以分为两个部分:

  • > file => 将 STDOUT 的输出写入文件;

  • 2>&1 => 将 STDERR 的输出重定向到 STDOUT 的输入;

因此,STDOUT 和 STDERR 都可以写入文件。

对于 "2>&1 > file",如果把逻辑分解一下:

  • 2>&1 => 将 STDERR 的输出重定向到 STDOUT 的输出;

  • > file=> 将 STDOUT 的输出写入文件;

另一个更简单方式是 "&> file",可以达到将 STDOUT 和 STDERR 写入文件达到相同效果:

root@jpzhang-dev:/home/linux/std# bash test.sh &> qq
root@jpzhang-dev:/home/linux/std# cat qq
Hello stdout
Hello stderr

4.3 示例 3

在使用命令时,通常会将它们与管道 "|" 的概念结合起来。"|" 的基本思想是将当前命令的 "STDOUT" 重定向到下一条命令的 "STDIN",如下面的流程所示:

        ​​​​​​​        ​​​​​​​        

在下面的示例中,只有 STDOUT 被重定向到 grep 命令,而 STDERR 仍被输出到 /dev/tty:

root@jpzhang-dev:/home/linux/std# bash test.sh | grep test_out
Hello stderr

如果还需要通过管道发送 STDERR 的内容,其概念与向文件写入内容类似,需要:

  • 将 STDERR 重定向到 STDOUT;

  • 将下一条命令的 STDIN 连接到当前命令的 STDOUT;

root@jpzhang-dev:/home/linux/std# bash test.sh 2>&1 | grep xxx
root@jpzhang-dev:/home/linux/std# bash test.sh 2>&1 | grep err
Hello stderr

        ​​​​​​​        ​​​​​​​        

本文简要介绍了 Bash 中常见的重定向技术,理解其原理就不需要再死记硬背如何将 STDERR 和 STDOUT 重定向到同一个文件,可以更严谨地思考如何实现各种要求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/755789.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机Java项目|基于SpringBoot的新闻稿件管理系统

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、Python项目、前端项目、人工智能与大数据、简…

密码学:用随机函数隐藏指纹

英文中e的出现频率高&#xff0c;加密后&#xff0c;频率最高的那个符号代表e。这是历史上的一次真实案例。这些符号的概率&#xff0c;叫做“指纹”。 把e加密成2个符号&#xff0c;用随机函数选择&#xff0c;例如70%概率下选择符号1&#xff0c;30%选择符号2。解密时&#…

启智畅想:AI集装箱箱号识别系统,解决方案提供商

AI集装箱箱号识别系统 当前,智能卡口管理行业正处于快速发展的阶段。随着物联网、大数据、人工智能等技术的不断进步,智能卡口管理系统已经能够实现对集装箱运输的全程跟踪、监控和管理,大大提高了管理效率和安全性。然而,市场上现有的智能卡口管理系统仍然存在一些痛点问题,如…

Spring容器的启动过程及留给开发者的可拓展点

一、Spring容器启动经过了哪些过程&#xff1f; 1、首先需要加载读取到应用环境中的配置&#xff0c;比如要加载的bean的class的包路径等信息。 【读取配置】 2、再就需要找到哪些类是需要spring进行类实例创建并管理的&#xff0c;扫描到具体的Class及Class元信息上的一些注…

【漏洞复现】电信网关配置管理系统——命令执行

声明&#xff1a;本文档或演示材料仅供教育和教学目的使用&#xff0c;任何个人或组织使用本文档中的信息进行非法活动&#xff0c;均与本文档的作者或发布者无关。 文章目录 漏洞描述漏洞复现测试工具 漏洞描述 电信网关配置管理系统是一个用于管理和配置电信网关设备的软件系…

为什么Modbus链接/从机不通?From 摩尔信使MThings

为了回应用户平日里关于摩尔信使&#xff08;MThings&#xff09;使用过程中最常见的问题&#xff0c;包括“网络链接连不上”、“为什么不能增加串口”和“为什么从机不通”&#xff0c;我们在此统一介绍解决方法。 1、具备哪些通信能力 支持串口和网络两种通信方式。 需要…

开箱即用的fastposter海报生成器

什么是 fastposter ? fastposter 海报生成器是一款快速开发海报的工具。只需上传一张背景图&#xff0c;在对应的位置放上组件&#xff08;文字、图片、二维码、头像&#xff09;即可生成海报。 点击代码直接生成各种语言 SDK 的调用代码&#xff0c;方便快速开发。 软件特性&…

NSSCTF-Web题目18(反序列化)

目录 [NISACTF 2022]babyserialize 1、题目 2、知识点 3、思路 [SWPUCTF 2022 新生赛]ez_ez_unserialize 4、题目 5、知识点 6、思路 [NISACTF 2022]babyserialize 1、题目 2、知识点 反序列化、绕过过滤、命令执行 3、思路 <?php include "waf.php";…

正版软件 | R-Studio Corporate:企业级数据恢复的终极解决方案

数据是企业的生命线&#xff0c;而数据丢失可能随时威胁到企业的正常运营。R-Studio Corporate 是一款专为企业环境设计的多功能数据恢复软件&#xff0c;确保您在面临数据危机时&#xff0c;能够迅速、高效地恢复宝贵数据。 跨平台操作&#xff0c;灵活恢复 R-Studio Corporat…

雷池软硬件部署模式

硬件模式&#xff1a; 硬件反向代理 VRRP 硬件透明代理 雷池硬件设备 硬件透明墙 硬件流量镜像 流量镜像具备旁路阻断攻击的能力 软件模式 模式对比

shopify入门教程-应用开发(二)

4.内网穿透 为什么要用这个&#xff0c;就是把电脑上的开发内容通过内网穿透显示到你的开发店铺上。这里的内网穿透我用了ngrok,花生壳&#xff0c;但都不如shopify官方推荐的cloudflare好用。所以这里我也推荐cloudflare。 运用内网穿透2个步骤 把app运行起来 ​​​​​​​…

正点原子rk3588编译sdk

1、编译SDK 1.1 安装 RK3588 Linux SDK .repo/repo/repo sync -l -j101.2 SDK 工程目录介绍 app&#xff1a;存放上层应用 app&#xff0c;包括 Qt 应用程序&#xff0c;以及其它的 C/C应用程序。 buildroot&#xff1a;基于 buildroot 开发的根文件系统。 debian&#xff1…

【shell脚本实战案例】数据磁盘初始化

文章目录 一、案例应用场景二、案例需求三、案例算法四、代码实现五、实现验证 &#x1f308;你好呀&#xff01;我是 山顶风景独好 &#x1f388;欢迎踏入我的博客世界&#xff0c;能与您在此邂逅&#xff0c;真是缘分使然&#xff01;&#x1f60a; &#x1f338;愿您在此停留…

已解决javax.xml.bind.MarshalException:在RMI中,参数或返回值无法被编组的正确解决方法,亲测有效!!!

已解决javax.xml.bind.MarshalException&#xff1a;在RMI中&#xff0c;参数或返回值无法被编组的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 目录 问题分析 出现问题的场景 服务器端代码 客户端代码 报错原因 解决思路 解决方法 1. 实现…

IBCS 虚拟专线用哪些特点!

当今数字化时代&#xff0c;高效、稳定、安全的网络连接对于企业和个人来说至关重要。IBCS 虚拟专线作为一种创新的网络解决方案&#xff0c;凭借其众多显著的优势&#xff0c;正逐渐成为众多用户的首选。 IBCS 虚拟专线最突出的优势之一在于其卓越的网络性能。它通过优化网络路…

DC-DC产品设计PCB注意事项

DC-DC的电路比LDO会复杂很多&#xff0c;噪声也更大&#xff0c;布局和layout要求更高&#xff0c;layout的好坏直接影响DC-DC的性能&#xff0c;所以了解DC-DC的layout至关重要。 一、Bad Layout EMI&#xff0c;DC-DC的SW管脚上面会有较高的dv/dt&#xff0c; 比较高的dv/d…

Python+Pytest+Allure+Yaml+Jenkins+GitLab接口自动化测试框架详解

PythonPytestAllureYaml接口自动化测试框架详解 编撰人&#xff1a;CesareCheung 更新时间&#xff1a;2024.06.20 一、技术栈 PythonPytestAllureYamlJenkinsGitLab 版本要求&#xff1a;Python3.7.0,Pytest7.4.4,Allure2.18.1,PyYaml6.0 二、环境配置 安装python3.7&…

kafka 消费者 API 使用总结

前言 应用程序使用KafkaConsumer向Kafka订阅主题&#xff0c;并从订阅的主题中接收消息。不同于从其他消息系统读取数据&#xff0c;从Kafka读取数据涉及一些独特的概念和想法。如果不先理解这些概念&#xff0c;则难以理解如何使用消费者API。本文将先解释这些重要的概念&…

你还能顶几天?

A总&#xff1a;你还能顶几天&#xff1f; 汪汪队&#xff1a;顶到奉命撤退的那一天 A总&#xff1a;你在这守散钱点几十年了&#xff0c;从来没跟我提过任何的要求&#xff0c;难道你不困难吗&#xff1f; 汪汪队&#xff1a;有困难&#xff0c;但是我提了有什么用呢&#…

【密码学】面向小白的古典密码基础入门笔记

目录 Mindmap 前言 破译方法 三类古典密码 替换密码 分类 单表替换密码 凯撒密码 简单替换密码 仿射密码 普莱费尔密码 培根密码 猪圈密码 摩斯密码 多表替换密码 维吉尼亚密码 移位密码 滚筒密码 栅栏密码 Mindmap 前言 1.所有古典密码都已不安全 2.密…