【BASH】回顾与知识点梳理(五)

news2025/1/15 16:30:44

【BASH】回顾与知识点梳理 五

    • 五. 数据流重导向
      • 5.1 什么是数据流重导向
        • standard output 与 standard error output
        • /dev/null 垃圾桶黑洞装置与特殊写法
        • standard input : < 与 <<
      • 5.2 命令执行的判断依据: ; , &&, ||
        • cmd ; cmd (不考虑指令相关性的连续指令下达)
        • $? (指令回传值) 与 && 或 ||

五. 数据流重导向

数据流重导向 (redirect) 由字面上的意思来看,好像就是将『数据给他传导到其他地方去』的样子?没错~数据流重导向就是将某个指令执行后应该要出现在屏幕上的数据, 给他传输到其他的地方,例如文件或者是装置 (例如打印机之类的)!这玩意儿在 Linux 的文本模式底下可重要的! 尤其是如果我们想要将某些数据储存下来时,就更有用了!

5.1 什么是数据流重导向

什么是数据流重导向啊?这得要由指令的执行结果谈起!一般来说,如果你要执行一个指令,通常他会是这样的:
在这里插入图片描述
我们执行一个指令的时候,这个指令可能会由文件读入资料,经过处理之后,再将数据输出到屏幕上。在上图当中, standard output 与 standard error output 分别代表『标准输出 (STDOUT)』与『标准错误输出 (STDERR)』, 这两个玩意儿默认都是输出到屏幕上面来的啊!那么什么是标准输出与标准错误输出呢?

standard output 与 standard error output

简单的说,标准输出指的是『指令执行所回传的正确的讯息』,而标准错误输出可理解为『 指令执行失败后,所回传的错误讯息』。举个简单例子来说,我们的系统默认有 /etc/crontab 但却无/etc/vbirdsay, 此时若下达『 cat /etc/crontab /etc/vbirdsay 』这个指令时,cat 会进行:

  • 标准输出:读取 /etc/crontab 后,将该文件内容显示到屏幕上;
  • 标准错误输出:因为无法找到 /etc/vbirdsay,因此在屏幕上显示错误讯息

不管正确或错误的数据都是默认输出到屏幕上,所以屏幕当然是乱乱的!那能不能透过某些机制将这两股数据分开呢? 当然可以啊!那就是数据流重导向的功能啊!数据流重导向可以将 standard output (简称 stdout) 与 standard error output (简称 stderr) 分别传送到其他的文件或装置去,而分别传送所用的特殊字符则如下所示:

  1. 标准输入 (stdin) :代码为 0 ,使用 < 或 << ;
  2. 标准输出 (stdout):代码为 1 ,使用 > 或 >> ;
  3. 标准错误输出(stderr):代码为 2 ,使用 2> 或 2>> ;

为了理解 stdout 与 stderr ,我们先来进行一个范例的练习:

#范例一:观察你的系统根目录 (/) 下各目录的文件名、权限与属性,并记录下来
[dmtsai@study ~]$ ll / <==此时屏幕会显示出文件名信息
[dmtsai@study ~]$ ll / > ~/rootfile <==屏幕并无任何信
[dmtsai@study ~]$ ll ~/rootfile <==有个新档被建立了!
-rw-rw-r--. 1 dmtsai dmtsai 1078 Jul 9 18:51 /home/dmtsai/rootfile
  1. 该文件 (本例中是 ~/rootfile) 若不存在,系统会自动的将他建立起来
  2. 但是当这个文件存在的时候,那么系统就会先将这个文件内容清空,然后再将数据写入!
  3. 也就是若以 > 输出到一个已存在的文件中,那个文件就会被覆盖掉啰!

汇总:

  • 1> :以覆盖的方法将『正确的数据』输出到指定的文件或装置上;
  • 1>>:以累加的方法将『正确的数据』输出到指定的文件或装置上;
  • 2> :以覆盖的方法将『错误的数据』输出到指定的文件或装置上;
  • 2>>:以累加的方法将『错误的数据』输出到指定的文件或装置上;

要注意喔,『 1>> 』以及『 2>> 』中间是没有空格的!

举例:
当你以一般身份执行 find 这个指令的时候,由于权限的问题可能会产生一些错误信息。例如执行『find / -name testing 』时,可能会产生类似『 find: /root: Permission denied 』之类的讯息。 例如底下这个范例:

# 范例二:利用一般身份账号搜寻 /home 底下是否有名为 .bashrc 的文件存在
[dmtsai@study ~]$ find /home -name .bashrc <==身份是 dmtsai 喔!
find: '/home/arod': Permission denied <== Standard error output
find: '/home/alex': Permission denied <== Standard error output
/home/dmtsai/.bashrc <== Standard output

如果想要将正确的与错误的数据分别存入不同的文件中需要怎么做?

#范例三:承范例二,将 stdout 与 stderr 分存到不同的文件去
[dmtsai@study ~]$ find /home -name .bashrc > list_right 2> list_error

注意喔,此时『屏幕上不会出现任何讯息』!因为刚刚执行的结果中,有 Permission 的那几行错误信息都会跑到 list_error 这个文件中,至于正确的输出数据则会存到 list_right 这个文件中啰!

/dev/null 垃圾桶黑洞装置与特殊写法

想象一下,如果我知道错误讯息会发生,所以要将错误讯息忽略掉而不显示或储存呢? 这个时候黑洞装置 /dev/null 就很重要了!这个 /dev/null 可以吃掉任何导向这个装置的信息喔!将上述的范例修订一下:

# 范例四:承范例三,将错误的数据丢弃,屏幕上显示正确的数据
[dmtsai@study ~]$ find /home -name .bashrc 2> /dev/null
/home/dmtsai/.bashrc <==只有 stdout 会显示到屏幕上, stderr 被丢弃了

再想象一下,如果我要将正确与错误数据通通写入同一个文件去呢?这个时候就得要使用特殊的写法了! 我们同样用底下的案例来说明:

# 范例五:将指令的数据全部写入名为 list 的文件中
[dmtsai@study ~]$ find /home -name .bashrc > list 2> list <==错误
[dmtsai@study ~]$ find /home -name .bashrc > list 2>&1 <==正确
[dmtsai@study ~]$ find /home -name .bashrc &> list <==正确

上述表格第一行错误的原因是,由于两股数据同时写入一个文件,又没有使用特殊的语法, 此时两股数据可能会交叉写入该文件内,造成次序的错乱。所以虽然最终 list 文件还是会产生,但是里面的数据排列就会怪怪的,而不是原本屏幕上的输出排序。 至于写入同一个文件的特殊语法如上表所示,你可以使用 2>&1 也可以使用 &> ! 一般来说,鸟哥比较习惯使用 2>&1 的语法啦!

standard input : < 与 <<

了解了 stderr 与 stdout 后,那么那个 < 又是什么呀?呵呵!以最简单的说法来说, 那就是『将原本需要由键盘输入的数据,改由文件内容来取代』的意思。 我们先由底下的 cat 指令操作来了解一下什么叫做『键盘输入』吧!

[root@node-135 ~]# cat > catfile
test
let's go
[root@node-135 ~]# cat catfile
test
let's go
[root@node-135 ~]#

由于加入 > 在 cat 后,所以那个 catfile 会被主动的建立,而内容就是刚刚键盘上面输入的那两行数据了。 唔!那我能不能用纯文本文件取代键盘的输入,也就是说,用某个文件的内容来取代键盘的敲击呢? 可以的!如下所示:

# 范例七:用 stdin 取代键盘的输入以建立新文件的简单流程
[dmtsai@study ~]$ cat > catfile < ~/.bashrc
[dmtsai@study ~]$ ll catfile ~/.bashrc
-rw-r--r--. 1 dmtsai dmtsai 231 Mar 6 06:06 /home/dmtsai/.bashrc
-rw-rw-r--. 1 dmtsai dmtsai 231 Jul 9 18:58 catfile
# 注意看,这两个文件的大小会一模一样!几乎像是使用 cp 来复制一般!

这东西非常的有帮助!尤其是用在类似 mail 这种指令的使用上。 理解 < 之后,再来则是 << 这个连续两个小于的符号了。 他代表的是『结束的输入字符』的意思!举例来讲:『我要用 cat 直接将输入的讯息输出到 catfile 中, 且当由键盘输入 eof 时,该次输入就结束』,那我可以这样做:

[dmtsai@study ~]$ cat > catfile << "eof"
> This is a test.
> OK now stop
> eof <==输入这关键词,立刻就结束而不需要输入 [ctrl]+d
[dmtsai@study ~]$ cat catfile
This is a test.
OK now stop <==只有这两行,不会存在关键词那一行!

看到了吗?利用 << 右侧的控制字符,我们可以终止一次输入, 而不必输入 [crtl]+d 来结束哩!这对程序写作很有帮助喔!好了,那么为何要使用命令输出重导向呢?我们来说一说吧!

  • 屏幕输出的信息很重要,而且我们需要将他存下来的时候;
  • 背景执行中的程序,不希望他干扰屏幕正常的输出结果时;
  • 一些系统的例行命令 (例如写在 /etc/crontab 中的文件) 的执行结果,希望他可以存下来时;
  • 一些执行命令的可能已知错误讯息时,想以『 2> /dev/null 』将他丢掉时;
  • 错误讯息与正确讯息需要分别输出时。

当然还有很多的功能的,最简单的就是网友们常常问到的:『为何我的 root 都会收到系统 crontab 寄来的错误讯息呢』这个咚咚是常见的错误, 而如果我们已经知道这个错误讯息是可以忽略的时候,嗯!『 2> errorfile 』这个功能就很重要了吧! 了解了吗?

问:
假设我要将 echo “error message” 以 standard error output 的格式来输出,该如何处置?
答:
既然有 2>&1 来将 2> 转到 1> 去,那么应该也会有 1>&2 吧?没错!就是这个概念!因此你可以这样作:

[dmtsai@study ~]$ echo "error message" 1>&2 
[dmtsai@study ~]$ echo "error message" 2> /dev/null 1>&2

你会发现第一条有讯息输出到屏幕上,第二条则没有讯息!这表示该讯息已经是透过 2> /dev/null 丢到垃圾桶去了!可以肯定是错误讯息啰! ^_^

5.2 命令执行的判断依据: ; , &&, ||

在某些情况下,很多指令我想要一次输入去执行,而不想要分次执行时,该如何是好?基本上你有两个选择, 一个是透过后面介绍的 shell script 撰写脚本去执行,一种则是透过底下的介绍来一次输入多重指令喔!

cmd ; cmd (不考虑指令相关性的连续指令下达)

在某些时候,我们希望可以一次执行多个指令,例如在关机的时候我希望可以先执行两次 sync 同步化写入磁盘后才 shutdown 计算机,那么可以怎么作呢?这样做呀:

[root@study ~]# sync; sync; shutdown -h now

在指令与指令中间利用分号 (;) 来隔开,这样一来,分号前的指令执行完后就会立刻接着执行后面的指令了。 这真是方便啊~再来,换个角度来想,万一我想要在某个目录底下建立一个文件,也就是说,如果该目录存在的话, 那我才建立这个文件,如果不存在,那就算了。也就是说这两个指令彼此之间是有相关性的,前一个指令是否成功的执行与后一个指令是否要执行有关!那就得动用到 && 或 || 啰!

$? (指令回传值) 与 && 或 ||

如同上面谈到的,两个指令之间有相依性,而这个相依性主要判断的地方就在于前一个指令执行的结果是否正确。 还记得本章之前我们曾介绍过指令回传值吧!嘿嘿!没错,您真聪明!就是透过这个回传值啦!再复习一次『若前一个指令执行的结果为正确,在 Linux 底下会回传一个 $? = 0 的值』。那么我们怎么透过这个回传值来判断后续的指令是否要执行呢?这就得要藉由『 && 』及『 || 』的帮忙了! 注意喔,两个 & 之间是没有空格的!那个 | 则是 [Shift]+[\] 的按键结果。

指令下达情况说明
cmd1 && cmd21. 若 cmd1 执行完毕且正确执行($?=0),则开始执行 cmd2。2. 若 cmd1 执行完毕且为错误 ($?≠0),则 cmd2 不执行。
cmd1 || cmd21. 若 cmd1 执行完毕且正确执行($?=0),则 cmd2 不执行。2. 若 cmd1 执行完毕且为错误 ($?≠0),则开始执行 cmd2。

上述的 cmd1 及 cmd2 都是指令。好了,回到我们刚刚假想的情况,就是想要: (1)先判断一个目录是否存在; (2)若存在才在该目录底下建立一个文件。由于我们尚未介绍如何判断式 test(如果有兴趣可以跳至 shell中的条件测试、特殊符号及特殊变量)的使用,在这里我们使用 ls 以及回传值来判断目录是否存在啦! 让我们进行底下这个练习看看:

# 范例一:使用 ls 查阅目录 /tmp/abc 是否存在,若存在则用 touch 建立 /tmp/abc/hehe
[dmtsai@study ~]$ ls /tmp/abc && touch /tmp/abc/hehe
ls: cannot access /tmp/abc: No such file or directory
# ls 很干脆的说明找不到该目录,但并没有 touch 的错误,表示 touch 并没有执行
[dmtsai@study ~]$ mkdir /tmp/abc
[dmtsai@study ~]$ ls /tmp/abc && touch /tmp/abc/hehe
[dmtsai@study ~]$ ll /tmp/abc
-rw-rw-r--. 1 dmtsai dmtsai 0 Jul 9 19:16 hehe

看到了吧?如果 /tmp/abc 不存在时,touch 就不会被执行,若 /tmp/abc 存在的话,那么 touch 就会开始执行啰! 很不错用吧!不过,我们还得手动自行建立目录,伤脑筋~能不能自动判断,如果没有该目录就给予建立呢? 参考一下底下的例子先:

# 范例二:测试 /tmp/abc 是否存在,若不存在则予以建立,若存在就不作任何事情
[dmtsai@study ~]$ rm -r /tmp/abc <==先删除此目录以方便测试
[dmtsai@study ~]$ ls /tmp/abc || mkdir /tmp/abc
ls: cannot access /tmp/abc: No such file or directory <==真的不存在喔!
[dmtsai@study ~]$ ll -d /tmp/abc 
drwxrwxr-x. 2 dmtsai dmtsai 6 Jul 9 19:17 /tmp/abc <==结果出现了!有进行 mkdir

如果你一再重复『 ls /tmp/abc || mkdir /tmp/abc 』画面也不会出现重复 mkdir 的错误!这是因为/tmp/abc 已经存在, 所以后续的 mkdir 就不会进行!这样理解否?好了,让我们再次的讨论一下,如果我想要建立 /tmp/abc/hehe 这个文件, 但我并不知道 /tmp/abc 是否存在,那该如何是好?试看看:

# 范例三:我不清楚 /tmp/abc 是否存在,但就是要建立 /tmp/abc/hehe 文件
[dmtsai@study ~]$ ls /tmp/abc || mkdir /tmp/abc && touch /tmp/abc/hehe

在这里插入图片描述
例题:
以 ls 测试 /tmp/vbirding 是否存在,若存在则显示 “exist” ,若不存在,则显示 “not exist”!
答:
这又牵涉到逻辑判断的问题,如果存在就显示某个数据,若不存在就显示其他数据,那我可以这样做:

[root@node-135 ~]# ls /tmp/vbirding && echo "exist" ||echo "not exist"
ls: cannot access /tmp/vbirding: No such file or directory
not exist

意思是说,当 ls /tmp/vbirding 执行后,若正确,就执行 echo “exist” ,若有问题,就执行 echo “not exist” !那如果写成如下的状况会出现什么?

ls /tmp/vbirding || echo "not exist" && echo "exist"

这其实是有问题的,为什么呢?由上图的流程介绍我们知道指令是一个一个往后执行, 因此在上面的例子当中,如果 /tmp/vbirding 不存在时,他会进行如下动作:

  1. 若 ls /tmp/vbirding 不存在,因此回传一个非为 0 的数值;
  2. 接下来经过 || 的判断,发现前一个指令回传非为 0 的数值,因此,程序开始执行 echo “not exist” ,而echo “not exist” 程序肯定可以执行成功,因此会回传一个 0 值给后面的指令;
  3. 经过 && 的判断,咦!是 0 啊!所以就开始执行 echo “exist” 。

第二个例子里面竟然会同时出现 not exist 与 exist 呢!真神奇~

由于指令是一个接着一个去执行的,因此,如果真要使用判断,那么这个 && 与 || 的顺序就不能搞错。一般来说,假设判断式有三个,也就是:
command1 && command2 || command3
而且顺序通常不会变,因为一般来说, command2 与 command3 会放置肯定可以执行成功的指令,因此,依据上面例题的逻辑分析,您就会晓得为何要如此放置啰~这很有用的啦!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android 从LibVLC-android到自编译ijkplayer播放H265 RTSP

概述 ijkplayer: Android/iOS video player based on FFmpeg n3.4, with MediaCodec, VideoToolbox support. 官方的描述就这么简单的一句话&#xff0c;但丝毫都不影响它的强大。 从LibVLC 到 ijkplayer 截止到2023.7.20 LibVLC-Android 最大的问题在与OOM&#xff0c;测试了…

多线程(JavaEE初阶系列6)

目录 前言&#xff1a; 1.什么是线程池 2.标准库中的线程池 3.实现线程池 结束语&#xff1a; 前言&#xff1a; 在上一节中小编带着大家了解了一下Java标准库中的定时器的使用方式并给大家实现了一下&#xff0c;那么这节中小编将分享一下多线程中的线程池。给大家讲解一…

威胁分析风险评估(TARA)影响和攻击可行性评估参考

在威胁分析风险评估&#xff08;TARA)过程中&#xff0c;风险等级由对资产安全属性侵害造成后果的影响等级和威胁的可能性两方面综合评估。 备注&#xff1a;以上内容的评估皆是建立在由信息安全问题引起并导致的前提下。 影响等级评估 影响等级说明&#xff0c;影响从安全&a…

k8s-服务发现service和ingress

回到目录 service用于集群内部应用的网络调用&#xff0c;处理东西流量 ingress用于集群外部用户访问内部服务&#xff0c;处理南北流量 一 kube-proxy三种代理模式 kubernetes集群中有三层网络&#xff0c;一类是真实存在的&#xff0c;例如Node Network、Pod Network,提供真…

css position: sticky;实现上下粘性布局,中间区域滚动

sticky主要解决的问题 1、使用absolute和fixed中间区域需要定义高度2、使用absolute和fixed底部需要写padding-bottom 避免列表被遮挡住一部分&#xff08;底部是浮窗的时候&#xff0c;需要动态的现实隐藏&#xff09; <!DOCTYPE html> <html lang"en"&…

从0-1实现简易Raft分布式共识算法

一、Raft前置简介 Raft目前是最著名的分布式共识性算法&#xff0c;被广泛的应用在各种分布式框架、组件中&#xff0c;如Redis、RocketMq、Kafka、Nacos&#xff08;CP&#xff09;等 根据Raft论文&#xff0c;可将Raft拆分为如下4个功能模块&#xff1a; 领导者选举日志同…

蓝桥云课ROS机器人旧版实验报告-04三维建模与仿真

项目名称 实验四 3D建模与仿真 成绩 内容&#xff1a;自定义机器人3D模型&#xff0c;创建一个URDF文件、xacro文件、ROS2[Kinetic/Melodic/Noetic]仿真 实验记录&#xff08;70分&#xff09; 从头开始构建使用 URDF 的可视化机器人模型&#xff1a; 先尝试两个案例&a…

合合信息上会在即:“排队”耗时近两年,能否交出IPO答卷?

撰稿|行星 来源|贝多财经 近日&#xff0c;上海合合信息科技股份有限公司&#xff08;下称“合合信息”&#xff09;在上海证券交易所科创板递交招股书&#xff08;上会稿&#xff09;。据贝多财经了解&#xff0c;合合信息于2021年9月27日递交招股书&#xff0c;将于2023年8…

今日头条面试真题及答案,软件测试工程师面试秘籍

试题1&#xff0e;在浏览器地址栏里输入一个网址&#xff0c;接下来会发生什么&#xff1f; 答案&#xff1a;发生的操作如下。 &#xff08;1&#xff09;浏览器查找该网址的IP地址。 &#xff08;2&#xff09;浏览器根据解析得到的IP地址向Web服务器发送一个HTTP请求。 &am…

CFI技术新探索,struct_san今日登场

一、背景 C/C开发的应用程序&#xff0c;长久以来存在内存破坏类的安全问题。当攻击者掌握了目标程序的漏洞后&#xff0c;就可以开发漏洞利用程序劫持目标程序的控制流。早期的漏洞利用是采用代码注入的方式&#xff0c;通过在缓冲区置入一段代码&#xff08;shellcode&#…

在 Tinkercad 中加快设计的 22 个技巧

在 Tinkercad 中加快设计的 22 个技巧 原文 Everyone knows that Tinkercad is the easiest way to get started in 3D design. Once you get the hang of it, you realize that it’s one of the fastest design tools available. With no software to launch or complex me…

Pytest学习教程_测试报告生成pytest-html(三)

前言 pytest-html 是一个用于生成漂亮的 HTML 测试报告的 pytest 插件。它可以方便地将 pytest 运行的测试结果转换为易于阅读和理解的 HTML 报告&#xff0c;提供了丰富的测试结果展示功能和交互性。 一、安装 # 版本查看命令 pytest版本&#xff1a; pytest --version pyte…

PHP代码审计--理论

提供资料&#xff1a; php 基础 : https://www.runoob.com/php/php-tutorial.html php是什么&#xff1f; PHP 是服务器端脚本语言。 首先在学习PHP前需要对HTML 和CSS有一定的认识 PHP 能做什么&#xff1f; PHP 可以生成动态页面内容PHP 可以创建、打开、读取、写入、关…

InnoDB引擎底层逻辑讲解——架构之磁盘架构

1. System Tablespaces区域 系统表空间是change buffer&#xff08;更改缓冲区&#xff09;的存放区域&#xff0c;这是在8.0之后重新规划的&#xff0c;在5.x版本的时候&#xff0c;系统表空间还会存放innodb的数据字典undolog日志等信息&#xff0c;在8.0之后主要主要存放更…

【程序猿周末如何才能获得充分的休息】

工作以后常常容易感到疲于奔命&#xff0c;即使在周末也没有得到高质量的休息。打工人/学生党如何过周末&#xff1f;你有哪些延长周末和下班时间的好方法吗&#xff1f;你可以选择从以下几个方向谈谈你的想法和观点。 一&#xff1a;周末的时间规划 周末双休 二&#xff1a;提…

springboot 自定义starter项目Unable to read meta-data for class

springboot 自定义starter包&#xff0c;在项目中引用&#xff0c;启动报错。 org.springframework.boot.SpringApplication [SpringApplication.java:843] Application run failed java.lang.IllegalStateException: Unable to read meta-data for class com.hxg.mail.spring…

找好听的配乐、BGM就上这6个网站,免费商用。

推荐几个音乐素材网站给你&#xff0c;各种类似、风格的都有&#xff0c;而且免费下载&#xff0c;还可以商用&#xff0c;建议收藏起来~ 菜鸟图库 https://www.sucai999.com/audio.html?vNTYxMjky 站内有上千首音效素材&#xff0c;网络流行的音效素材这里都能找到&#xf…

一起学算法(双指针篇)

概念&#xff1a; 通过两个指针&#xff0c;不断的调整区间&#xff0c;从而求出问题最优解的算法就叫“尺取法”&#xff0c;由于利用的是两个双指针&#xff0c;所以也叫作“双指针”算法&#xff0c;这里的“尺”的含义&#xff0c;主要是因为这类问题&#xff0c;最终要求解…

刷题笔记 day2

力扣 1089 复写零 思路&#xff1a;双指针 第一步&#xff1a;利用指针 cur 去记录最后一位要复写的数 &#xff0c; 利用指针 dest 指向最后一位数所要复写的位置&#xff1b; 实现过程&#xff1a;最开始 cur 指向0&#xff0c;dest 指向 -1 &#xff0c; 当arr[cur] ! …

高并发与性能优化的神奇之旅

作为公司的架构师或者程序员&#xff0c;你是否曾经为公司的系统在面对高并发和性能瓶颈时感到手足无措或者焦头烂额呢&#xff1f;笔者在出道那会为此是吃尽了苦头的&#xff0c;不过也得感谢这段苦&#xff0c;让笔者从头到尾去探索&#xff0c;找寻解决之法。 目录 第一站&…