前言
这部分知识几度学习几度忘却,还是需要总结梳理才能真正领会。
后台运行的脚本
重定向使用比较多的还是在我们去后台运行一个程序说起,比如这下面的操作
apps@PC-zhuxuemin:~/xuemin$ nohup ./callsystem >/dev/null 2>& 1 & [1] 3923
后台执行的地方我都记得住,主要是很多次2>& 1学会又忘记,这次围绕这个知识点进行总
箭头指向
linux一大哲学便是一切皆文件,数据输入输出则被定义为流,我们的程序就像自来水工厂一样对数据进行加工,处理好的水则对外输出。< 则是代表读取的数据源,> 则是输出目的地。linux中每个程序都有标准的输入和输出流,标准输入则是我们的键盘,标准输出就是我们的控制台。
ls输出到控制台
cat可以从文件读取,输出到控制台
默认状态下我们也没有去深究,但是这个状态其实是可以被我们去改变的
比如:
ll >ls.log read < ls.log a echo $a
read 则从一个文件中读取数据,然后结果给变量a
文件描述符
linux文件中描述符file description其实是一个结构体,是对文件的引用,说白了其实就是定义一个变量,然后我们访问变量可以读到内容。
使用exec可以绑定一个文件到 文件描述符中,比如还是刚才的文件:
echo "lslog里面内容" >ls.log exec 5< ls.log cat <& 5
我们这样就绑定了5变量,箭头<还是读取的意思,所以原来我们需要读取ls.log的写法就可以变成使用变量去读取了
看到效果其实是一样的,这里有个相当于使用变量的语法 <& 代表引用文件描述符,后面便是编号,其实反过来理解,如果直接去的&则会把5当成普通文件去读取,不就产生歧义了嘛!
lsof查看文件描述符
lsof是列出打开文件(lists openfiles)的意思,后面接进程号即可,另外$$在linux可以拿到当前bash的进程号,我们可以组合使用去查看我们定义的文件描述符:
lsof -p $$
我们可以看到红色部分有个5,其实那个就是我们变量名字啦,另外顺带看到下面有我们的0 1 2其实就是默认给我们带的,这也是为啥我们可以去使用 >& 2 类似这种操作的原因了,具体是表示啥呢,其实都有直接规定的,我们通过/dev下面可以看到绑定的情况:
ls -l /dev
还是一切皆文件,proc下面是linux进程信息的映射,我们切可以看到2 0 1指向的变量,分别就是标准错误输出,标准输入和标准输出,就是我们的控制台和键盘。
不仅如此,其实我们要建立外部链接也是可以的
exec 7<> /dev/tcp/www.baidu.com/80
系统会显示TCP的连接类型了
重定向的变量覆盖问题
回到最开始的脚本
nohup ./callsystem >/dev/null 2>& 1 &
其实这里还有个坑,如果我们写成
nohup ./callsystem 2>& 1 1>/dev/null &
这样子是有问题的,这个从程序理解可以比较方便,2>&1 其实是会把2赋值给1指向的实际内容,已经是控制台了,那么后面的覆盖1>/dev/null不会再对2起作用了