[TOC]

0x00 快速入门

主要介绍管道符与输出重定向的基础知识

1. 多命令执行

多命令顺序执行符列表

多命令执行符 格式 作用
; 命令1 ; 命令2 多个命令顺序执行,命令之间没有任何逻辑联系
&& 命令1 && 命令2 逻辑与,命令1正确执行才会执行命令2,命令1不正确执行,则命令2不会执行
shift+\shift+\ =ll 命令1 ll 命令2 逻辑或,当命令1执行不正确,则命令2才会执行,当命令1正确执行,则命令2不会执行。注释:其中shift+\意味着

例如:date ; tar -zcvf etc.tar.gz /etc ; date可以计算中间打包压缩命令执行的耗时
再如:ls && echo yes || echo no,第一个命令正确执行,输出yes,错误执行输出no


2. 管道符

命令格式:
命令1 | 命令2,有一定的编程思想在里面 命令1的正确输出作为命令2的操作对象,和逻辑与不一样

实际案例:

ls -l /etc | more   #代表将ls -l /etc的输出分屏显示
netstat -an | grep ESTABLISHED #代表搜索netstat -an输出中带有ESTABLISHED的行
netstat -an | grep ESTABLISHED | wc -l #此为多管道符命令,代表到最后统计带有ESTABLISHED的行的数目,即可看出服务器上连接了多少人


3. 标准输入输出

linux启动后会默认打开3个文件描述符:

设备 设备文件名 类型 文件描述符 内存文件名 使用符号
键盘 /dev/stdin 标准输入/读取数据 0 /proc/self/fd/0 使用 < 或 <<
显示器 /dev/stdout 标准输出数据 1 /proc/self/fd/1 使用 > 或 >>
显示器 /dev/stderr 标准错误输出 2 /proc/self/fd/2 使用 2> 或 2>>

一条shell命令执行,都会继承父进程的文件描述符因此,所有运行的shell命令,都会有默认3个文件描述符。
即对于任何一条linux 命令执行它会是这样一个过程:

先有一个输入:输入可以从键盘,也可以从文件得到
命令执行完成:成功了就会把成功结果输出到屏幕:standard output默认是屏幕
命令执行有错误:会把错误也输出到屏幕上面:standard error默认也是指的屏幕

WeiyiGeek.标准输入输出


(1)输出重定向

类型 符号 作用
标准输出重定向 命令 > 文件 以覆盖的方式,把命令的正确的输出,输出到指定文件或者设备中
标准输出重定向 命令 >> 文件 以追加的方式,把命令的正确输出,输出到指定文件或者设备之中
标准错误输出重定向 错误命令 2 > 文件 以覆盖的方式,把命令的错误的输出,输出到指定文件或者设备中
标准错误输出重定向 错误命令 2 >> 文件 以追加的方式,把命令的错误输出,输出到指定文件或者设备之中


(2)正确和错误输出同时保存

类型 符号 作用
正确输出和错误输入同时保持 命令 > 文件 2>&1 或者 命令 &> 文件 以覆盖方式,把suc与err输出都保存到同一个文件中
命令 >> 文件 2>&1 或者 命令 &>> 文件 以追加方式,把suc与err输出都保存到同一个文件中+
命令 >> suc文件 2>>err文件 把正确的输出追加到文件1中,把错误的输出追加到文件2中

实际示例:

#语法案例
command-line1 [0-2] > file #0,1,2文件描述符或&设备/dev/null
&[n] 代表是已经存在的文件描述符,&1 代表输出 &2代表错误输出 &-代表关闭与它绑定的描述符

#示例1.这个例子是讲,我们执行了任意命令,并输出到/dev/sda。
#这样的话/dev/sda 里面的文件会被命令输出的内容全部替换掉,最后丢失掉其中原有的数据。
$任意命令 > /dev/sda
ifconfig > ~/desktop/test.log ##将内容保存在日志文件中


#示例2.正确输出与错误输出都显示在屏幕了,现在需要把正确输出写入suc.txt
# 1>可以省略不写,默认所至标准输出
$ls test.sh test1.sh
ls: test1.sh: 没有这个文件和目录
test.sh


#示例3.把错误输出到err.txt,正确输出到suc.txt中
$ls test.sh test1.sh 1>suc.txt 2> err.txt # 2>是将错误输出到文件
$cat suc.txt err.txt
test.sh
ls: 无法访问test1.sh: 没有那个文件或目录
# 继续追加把输出写入suc.txt err.txt  “>>”追加操作符
$ls test.sh test1.sh 1>>suc.txt 2>>err.txt


#示例4.#&代表标准输出错误输出,将所有标准输出与错误输出 输入到/dev/null文件或者file.txt文件中.
$ls test.sh test1.sh &>/dev/null #及屏蔽stdout与stderr
$ls test.sh test1.sh >/dev/null 2>&1 #将错误输出2绑定给正确输出1,然后将正确输出发送给/dev/null设备这种常用

$ls test.sh test1.sh &>file.txt


#示例5.将错误输出信息关闭掉
$ls test.sh test1.sh 2>&-
test.sh
$ls test.sh test1.sh 2>/dev/null
test.sh
# 关闭所有输出
$ls test.sh test1.sh 1>&- 2>&- #关闭 1 ,2 文件描述符

注意事项:

  • 特别注意错误输出大于号和文件之间不能有空格!!!
  • 1、shell遇到”>”操作符,会判断右边文件是否存在,如果存在就先删除,并且创建新文件,不存在直接创建, 无论左边命令执行是否成功,右边文件都会变为空
  • 2、“>>”操作符,判断右边文件,如果不存在就先创建。以添加方式打开文件,会分配一个文件描述符[不特别指定,默认为[1,2]然后,与左边的标准输出(1)或错误输出(2) 绑定
  • 3、当命令:执行完,绑定文件的描述符也自动失效0,1,2又会空闲
  • 4、一条命令启动,命令的输入,正确输出,错误输出,默认分别绑定0,1,2文件描述符
  • 5、一条命令在执行前,先会检查输出是否正确,如果输出设备错误,将不会进行命令执行


(3)输入重定向

#基础语法
command-line [n] <file ##0,1,2文件描述符或&设备/dev/null

n >& m 将输出文件 m 和 n 合并
n <& m 将输入文件 m 和 n 合并

实际案例:

#示例1. 和输出重定向一样,Unix 命令也可以从文件获取输入,语法为: 
$cat < catfile #按下 [ctrl]+d 离开
testing

#示例2.从标准输入【键盘】获得数据,然后输出给catfile文件
$cat > file

#示例3.cat 从test.sh 获得输入数据,然后输出给文件catfile
cat >catfile <test.sh

WeiyiGeek.示例2/3

#示例4.用的最多输入重定向到文件
$cat >catfile <<eof
test a file
test!
eof
##<< 这个连续两个小符号, 他代表的是『结束的输入字符』的意思。这样当空行输入eof字符,>输入多行数据后按ctrl+D结束写入


#示例5.输入重定向描述符的妙用
$wc < test.log #wc命令原本的输入是键盘,现在重新定向为文件,当然,其实不需要<
1 3 54 #行数 单词数 字节数
#下面它会要求你不断输入,知道再遇到ddy,就会停止并做相关统计,实际工作中基本不会用到.
$wc <<ddy >test.log
This is a input content;
ddy

$cat test.log
1 5 27
#还能将将字符统计的输入到Test.log中(可以无先)

补充知识点:

  • EOF字符前面可以采用一个-,后面连接的EOF结束字符不用一定在首行(但是需要采用Tab键功能进行缩进)


4. exec 命令

描述:在上面讲的输入输出重定向,是将输入输出绑定文件或设备后。只对当前那条指令是有效的。如果需要在绑定之后,接下来的所有命令都支持的话,就需要用exec命令来绑定重定向;

#基础语法
exec 文件描述符[n] <或> file或文件描述符或设备

实际案例:

#示例1.将标准输出与fd 6绑定
$exec 6>&1
$ls /proc/self/fd/
0 1 2 3 6 #出现文件描述符6


#示例2.将命令标准输出绑定到suc.txt文件中(输出到该文件)
exec 1>suc.txt
ls -al ##执行命令,发现什么都不返回了,因为标准输出已经输出到suc.txt文件了
exec 1>&6 ##恢复标准输出


#示例3.关闭fd 6描述符
#说明:使用前先将标准输入保存到文件描述符6,文件描述符默认会打开0,1,2 还可以使用自定义描述符 。
#然后对标准输出绑定到文件,接下来所有输出都会发生到文件使用完后,恢复标准的输出,关闭打开文件描述符6。
$exec 6>&-
$ls /proc/self/fd/
0 1 2 3

WeiyiGeek.删除文件描述符

补充知识点:

#故障案例1
可能有朋友会这样用:exec 1>suc.txt ,接下来所有输出都绑定到suc.txt 文件
exec 1>&2 #恢复采用错误输出 ,1 >& 2 意思是将标准输出重定向到句柄2错误输出


#故障案例2
#打开test.sh可读写操作与文件描述符3绑定
exec 3<>test.sh
while read line<&3
do
echo $line; #循环读取文件描述符3(读取的是test.sh内容)
done

#关闭文件的输入、输出绑定
exec 3>&-
exec 3<&-
>& 将一个句柄的输出写入到另一个句柄的输入中
<& 从一个句柄读取输入并将其写入到另一个句柄输出中


#故障案例3: 直接采用exec来进行绑定
exec<a.log
while read line
do
echo $line
done

总结重定向应用通常就以下两点:

  • 1、重新设置命令的默认输入、输出,指向到自己文件(文件,文件描述符,设备其实都是文件,因为linux就是基于设备也是文件,描述符也指向是文件)
  • 2、扩展自己新的描述符,对文件进行读写操作

0x02 高级管道命令

<<EOF

描述:Here Document(”嵌入文档“)是 Shell 中的一种特殊的重定向方式,它的基本的形式如下:

<< delimiter	将开始标记 delimiter 和结束标记 delimiter 之间的内容作为输入,当遇到 delimiter则结束输入

#它的作用是将两个 delimiter(分隔符号)之间的内容(document) 作为输入传递给 command.
command << delimiter
document
delimiter

实际案例:

#示例1.下面的例子,通过 wc -l 命令计算 document 的行数:
$wc -l << EOF
This is a simple lookup program
for good (and bad) restaurants 餐厅
in Cape Town.
EOF


#示例2.在shell脚本中进行使用
#!/bin/bash
cat << EOF
This is a simple lookup program
for good (and bad) restaurants
in Cape Town.
EOF

注意:

  • 开始的delimiter前后的空格会被忽略掉\
  • 结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进


mkfifo 模块

mkfifo 使用指定的文件名创建FIFO(也称为”命名管道”),它是一种特殊的文件类型,它允许独立的进程通讯(反弹Shell你懂的)
一个进程打开FIFO文件进行写操作,而另一个进程对之进行读操作, 然后数据便可以如同在shell或者其它地方常见的的匿名管道一样流线执行.
默认情况下,创建的FIFO的模式为0666(‘a+rw’)减去umask中设置的位

#基础语法
mkfifo [options] file

#选项
-m mode, --mode=mode:设置创建的FIFO的模式为 mode, 这可以是 chmod(1) 中的符号模式,并使用默认模式作为起始点,其实就是rwx权限
GNU STANDARD OPTIONS(GNU标准选项)
--help:在标准输出上打印一条用法信息,并以成功状态退出.
--version:在标准输出上打印版本信息,然后以成功状态退出.
--:终止选项列表.

实际案例:

#示例1.mkfifo -m 使用案例
mkfifo -m 777  myfifo
cat /etc/passwd > myfifo & #将cat命令的输出作为此myfifo的输入,并放在后太运行、
[10] 6285
#再用cut命令从该myfifo中读出数据进行处理
cut -d: -f1-3 < myfifo
root:x:0
bin:x:1