管道和文件描述符
写在前面的话
在bash中一行执行多条命令,通常我们会这样 ls;pwd
或这样 (umask 077;openssl genrsa -out server.key 2048)
或这样 {ls;pwd}
在bash中把前一个命令的输出作为下一个命令的输入,通常我们会这样du -d2 /|sort -rn|head
上面的管道通过 |
来表示,如果希望创建一个命名的管道可以使用 mkfifo
命令
创建一个名为 pip1 的管道 mkfifo pip1
向管道中放入数据 echo "first line"> pip1
从管道中取出数据 【此时终端配当前指令占用,需要打开另一个终端】 cat pip1
使用文件描述符引用这个管道
sh-4.2# {mkfifo pip2;exec 7<>pip2}
sh-4.2# for ((i=1;i<10;i++));do echo $i;done >&7
sh-4.2# while true;do read -u7 a;echo $a;done
通过文件描述符创建一个消息队列,实现一个并发处理多任务的效果
#/bin/bash
#Usage:sh $0
#Function: detect ip online or down and print online ip
#version:1.0
#ip via read
printf "\033[45m please input a ip like 192.168.0.1: \033[0m"
#read -t 30 -p 'please input a ip like 192.168.0.1:' ip
read -t 30 ip
newip=`echo $ip|cut -d '.' -f1,2,3`
#thread number
fork_num=100
#mkfifo file
tempfifo="my_temp_fifo"
mkfifo ${tempfifo}
#create filescripts
exec 6<>${tempfifo}
rm -f ${tempfifo}
#
[ -e /tmp/ping.log ] && rm -f /tmp/ping.log
#echo >&6
for ((i=1;i<=${fork_num};i++))
do
{
echo
}
done >&6
#
for num in `seq 1 255`
do
{
read -u6
{
ping -c 2 ${newip}.${num} >/dev/null 2>&1
if [ $? -eq 0 ];then
echo "${newip}.${num} is online" >>/tmp/ping.log
fi
echo "" >&6
} &
}
done
wait
#print result to screen
sort -t '.' -k 4n /tmp/ping.log
printf '%s\t' 'online number:'
echo -e "\033[41m `sort -t '.' -k 4n /tmp/ping.log|wc -l` \033[0m"
#关闭6号输出和输入
exec 6>&-
exec 6<&-
rm -f /tmp/ping.log
>或1>
输出重定向:把前面输出的东西输入到后边的文件中,会删除文件原有内容。
>>或1>>
追加重定向:把前面输出的东西追加到后边的文件中,不会删除文件原有内容。
<或<0 输入重定向:输入重定向用于改变命令的输入,指定输入内容,后跟文件名。
<<或<<0输入重定向:后跟字符串,用来表示“输入结束”,也可用ctrl+d来结束输入。
2> 错误重定向:把错误信息输入到后边的文件中,会删除文件原有内容。
2>> 错误追加重定向:把错误信息追加到后边的文件中,不会删除文件原有内容。
标准输入(stdin):代码为0,使用<或<<。
标准输出(stdout):代码为1,使用>或>>。正常的输出。
标准错误输出(sederr):代码为2,使用2>或2>>。
特殊:
2>&1就是把标准错误重定向到标准输出(>&)。
>/dev/null 2>&1
等价于 1>/dev/null 2>/dev/null
>/dev/null 2>&1
的作用
如果定时任务规范结尾不加 >/dev/null 2>&1,很容易导致硬盘inode空间被占满,从而系统服务不正常(var/spool/clientmqueue邮件临时队列目录,垃圾文件存放于此,如果是centos 6.4系统,默认不装sendmail服务,所以不会有这个目录。)