您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

Shell 输入输出重定向

1. Shell

我们在之前章节有学习 echo/printf 来将我们的需求,此时就是我们将系统的返回到我们标准终端,使得我们能够看到正常的的结果,Unix 命令认的输入设备即 stdin 为,标准和设备即 stdout 为器,我们利用可以将输入改为,或者将重新定向到其他设备或中。

我们知道了系统认的输入为,标准与为器,当我们在编写 Shell 的时候有一些非交互的操作,不能通过输入,或的结果我们不希望在器的时候,此场景就需要利用输入了。

2. Shell 输入

Linux Shell 分为两种,顾名思义,输入即改变标准的认系统输入,即改变认的系统器。

在 Linux 中一切皆,标准输入设备()和标准设备(器)在内的所有计算机硬件都是。为了表示和区分已经打开的,Linux 会给每个分配 ID,这个 ID 就是整数,被称为描述符(File Descriptor)。

如下是描述符的类型及其对应的设备。

Linux 程序在你执行任何形式的 操作时,其实都是在对描述符进行读取或写入,描述符只是打开的相关联的整数,在其背后就是硬盘上普通或管道,,器,或是网络等。

如图更为形象的展示是 Linux 系统认标准输入设备,当然可以为 file,对应的命令执行的标准与标准设备为屏幕,也可以根据需求到。

输入方向为数据从那流入程序,输入即改变认的系统输入,改变其从其他对方流入程序。

command <file,将 file 中的作为 command 的输入。

格式:

 [n]< word

注意 [n] 与 < 之间没有空格,其中将描述符 n 到 word 指代的(以只读方式打开), 如果指明 n,认就为 0,标准输入,例如:

[root@xuel--cvm-0 ~]# cat testfile.txttest content[root@xuel--cvm-0 ~]# cat 0< testfile.txttest content[root@xuel--cvm-0 ~]# cat < testfile.txttest content

我们可以看到 testfile.txttest content,在输入时,我们将描述符 0 到 testfile.txt,所以利用命令 cat 查看,结果就为的,认就是标准输入,所以可以不写 0。

[root@xuel--cvm-0 ~]# 0< testfile.txt cattest content[root@xuel--cvm-0 ~]# < testfile.txt cattest content

解析器解析到 “<” 以后会先处理,将标准输入到 file,之后 cat 再从标准输入读取指令的时候,由于标准输入已经到了 file ,于是 cat 就从 file 中读取指令了。

command <<END,从标准输入()中读取数据,直到遇见分界符 END 才停止,分界符可以是的任意字符,在此建议使用 EOF。

该输入可以很方便用于批量的输入,可以用此来,例如:

[root@xuel--cvm-0 ~]# cat > file1.txt <<EOF> hello shell> hello go> test file> EOF[root@xuel--cvm-0 ~]# cat file1.txthello shell
hello gotest file

在此利用了将 cat 的到 file1.txt 中,之后利用 <<EOF 来从标准输入中读取数据,直到遇到结束标示 EOF 停止。

例如我们在学习流程控制中的 while 循环读取就利用了输入,例如:

[root@xuel--cvm-0 ~]# cat while.sh#!/bin/bashFILE=file1.txtwhile read str; doecho $strdone <$FILE[root@xuel--cvm-0 ~]# bash while.shhello shell
hello gotest file

在此将绑定到输入上,利用 while 来逐行读取中的。

方向为数据到那个终端,即改变认的器,改变其从其他设备。

一般的应用场景多为将标准或标准分别保持到不同的,或者是我们不关心等情况等。

如下整理的标准与标准:

覆盖方式

语法:command >file

标准输入覆盖方式,直接将 command 命令的标准,以覆盖方式到中,例如:

[root@xuel--cvm-0 ~]# cat file1.txthello shell
hello gotest file[root@xuel--cvm-0 ~]# echo "test" > file1.txt[root@xuel--cvm-0 ~]# cat file1.txttest

可以看到将的原始已经覆盖掉了,也可以用来清空,例如:

[root@xuel--cvm-0 ~]# cat file1.txttest[root@xuel--cvm-0 ~]# >file1.txt[root@xuel--cvm-0 ~]# cat file1.txt

追加方式

语法:command >>file

将标准的追加到中,注意追加为不覆盖原始,例如:

[root@xuel--cvm-0 ~]# cat file1.txttest[root@xuel--cvm-0 ~]# echo "test222" >> file1.txt[root@xuel--cvm-0 ~]# cat file1.txttesttest222

覆盖方式:

语法:command 2>file

与标准一样,只是绑定标准描述符 2,例如:

[root@xuel--cvm-0 ~]# ls /nonels: 无法访问/none: 没有那个或目录[root@xuel--cvm-0 ~]# ls /none 2> error.txt[root@xuel--cvm-0 ~]# cat error.txtls: 无法访问/none: 没有那个或目录

我们可以使用 ls 查看不存在的或目录,会标准,将其到 error.txt 中。

追加方式:

语法:command 2>>file

与标准追加方式一样,只是绑定标准描述符,例如:

[root@xuel--cvm-0 ~]# abc 2>>error.txt[root@xuel--cvm-0 ~]# cat error.txtls: 无法访问/none: 没有那个或目录
-bash: abc: command not found

我们使用命令 abc,Shell 我们没有这个命令,在此就将标准以追加形式到中。

在我们使用分为标准与,当我们希望将两者都到某使用可以使用 &>,例如:

[root@xuel--cvm-0 ~]# cat totle.txt
ls: 无法访问/none: 没有那个或目录
/tmp:
limit-0.2
cvm_init.log
net_affinity.log
nohup.out
nv_driver_install.log
nv_gpu_conf.log
setRps.log
v0.2.tar.gz
virtio_blk_affinity.log

我们可以看出无论标准或都到了 totle.txt 中。

输入和也是可以组合使用的,那么这个组合主要应用于在 Shell 脚本当中产生新的的场景下,例如:

[root@xuel--cvm-0 ~]# cat > file1.txt <<EOF> hello shell> hello go> test file> EOF[root@xuel--cvm-0 ~]# cat file1.txthello shell
hello gotest file

在此就组合标准与输入组合使用。

在 Linux 系统中存在空设备,也称为黑洞设备,其为 /dev/null。当我们将到它时会被丢弃,对其也无法进行读取操作,利用它,可以在我们编写 Shell 中能够起到异常的功效,例如:

[root@xuel--cvm-0 ~]# ls / /nonels: 无法访问/none: 没有那个或目录
/:
bin  boot  data  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  selinux  srv  sys  tmp  usr  var[root@xuel--cvm-0 ~]# ls / /none >/dev/null 2>&1[root@xuel--cvm-0 ~]# ls / /none &>/dev/null

可以看到我们先将标准到 /dev/null,对于标准全部又到标准,从而达到了将全部掉。

或者我们使用 & 将标准与标准全部到 /dev/null,同样能达到的。

3. 实例

编写脚本, Linux 系统的 和,然后到中。

可以利用来分别编写 和,最后利用将信息到中。

#!/bin/bash# Description: sys check# Auth: kaliarch# Email: kaliarch@163.com# function: sys check# Date: 2020-03-29 14:00# Version: 1.0[ $(id -u) -gt 0 ] && echo "请用root执行此脚本!" && exit 1
sysversion=$(rpm -q centos-release|cut -d- -f3)line="-------------------------------------------------"[ -d logs ] || mkdir logs

sys_check_file="logs/$(ip a show dev eth0|grep -w inet|awk '{print $2}'|awk -F '/' '{print $1}')-`date +%Y%m%d`.txt"# 系统信息function get__info() {Physical_s=$(grep "physical id" /proc/info| sort | uniq | wc -l)Virt_s=$(grep "processor" /proc/info | wc -l)_Kernels=$(grep "cores" /proc/info|uniq| awk -F ': ' '{print $2}')_Type=$(grep "model name" /proc/info | awk -F ': ' '{print $2}' | sort | uniq)_Arch=$(uname -m)cat <<EOF | column -t
信息:
物理个数: $Physical_s逻辑个数: $Virt_s每核心数: $_Kernels型号: $_Type架构: $_ArchEOF}# 系统function get_mem_info() {check_mem=$(free -m)MemTotal=$(grep MemTotal /proc/meminfo| awk '{print $2}')  #KBMemFree=$(grep MemFree /proc/meminfo| awk '{print $2}')    #KBlet MemUsed=MemTotal-MemFree
    MemPercent=$(awk "BEGIN {if($MemTotal==0){printf 100}else{printf \"%.2f\",$MemUsed*100/$MemTotal}}")report_MemTotal="$((MemTotal/))""MB"        #内存总容量(MB)report_MemFree="$((MemFree/))""MB"          #内存剩余(MB)report_MemUsedPercent="$(awk "BEGIN {if($MemTotal==0){printf 100}else{printf \"%.2f\",$MemUsed*100/$MemTotal}}")""%"   #内存使用率%cat <<EOF
:${check_mem}EOF}# 定义主function sys_check() {get__infoecho ${line}get_mem_infoecho ${line}}# 执行主将到中sys_check > ${sys_check_file}# 执行测试[root@xuel--cvm-0 ~]# bash sys_check.sh[root@xuel--cvm-0 ~]# cat logs/10.0.1.15-20200329.txt信息:
物理个数:  1
逻辑个数:  1
每核心数:  1
型号:      Intel(R)  Xeon(R)    E5-26xx  v4
架构:      x86_64
-------------------------------------------------
:
             total       used       free     shared    buffers     cached
Mem:           996        920         76          0        191        600
-/+ buffers/cache:        127        868
Swap:            0          0          0
-------------------------------------------------

可以看到利用了两个来系统的信息,将其利用方式到中。

4. 注意事项

一条 shell 命令,都会继承其父进程的描述符,因此所有的 shell 命令,都会认有三个描述符;

所有输入都是由该进程所有打开的描述符控制的,Linux 一切皆,因此他们的输入也是由描述符控制;

<中分界符可以是的任意字符,在此建议使用 EOF;

在进行追加的时候可以使用追加方式,切记操作前备份老,以免异常。

5. 小结

对于特别适用于的操作或者某些不关注结果的场景,在本章节需要注意覆盖模式与追加模式的区别,灵活配合空设备对特定场景进行应用,理解三个描述符,百变不离其中灵活组合使用。


联系我
置顶