背景shell 的判断方式go 的判断方式python 的判断方式while read line 解决方式
背景在写一个bash脚本的时候,遇到一个问题,如果脚本运行在管道之后,那么如要如何处理管道送来的数据呢?
xargs吗?
如果他有时候又是正常运行,前面没有管道呢?
所以不管用xargs还是 while read line 去接收数据,都是假设前面有管道的。
如何判断是否工作在管道之后呢?这个是主要问题。
能判断,能把管道前面的数据拿到,这就基本解决了这个问题,管道是内核中的一个缓冲区,一端是管道前命令的标准输出写入管道,管道后的命令则把管道当做标准输入读入。
shell 的判断方式# cat /tmp/1.sh
#!/bin/bash
# 判断fd 1 是否是tty, fd 1 是标准输出的fd
[[ -t 1 ]] && echo "stdout is attached to TTY"
# 判断 /dev/stdout 是否是 pipe, 后面有管道时为真
[[ -p /dev/stdout ]] && echo 'STDOUT is attached to a pipe'
# 当 fd 1 不是 tty 且 /dev/stdout 不是管道时,那么数据流被重定向了
[[ ! -t 1 && ! -p /dev/stdout ]] && echo 'STDOUT is attached to a redirection'
# 判断 fd 0 是否是 tty, 标准输入
[[ -t 0 ]] && echo "stdin is attached to TTY"
# 判断 /dev/stdin 是不是 pipe, 在管道后面为真
[[ -p /dev/stdin ]] && echo 'STDIN is attached to a pipe'
# 判断标准输入是否被重写向了
[[ ! -t 0 && ! -p /dev/stdin ]] && echo 'STDIN is attached to a redirection'
[root@fsha1 bin]# bash /tmp/1.sh
stdout is attached to TTY
stdin is attached to TTY
[root@fsha1 bin]# bash /tmp/1.sh | xargs echo ${*}
STDOUT is attached to a pipe stdin is attached to TTY
[root@fsha1 bin]# echo "haha" | bash /tmp/1.sh
stdout is attached to TTY
STDIN is attached to a pipe
[root@fsha1 bin]# bash /tmp/1.sh < /dev/null
stdout is attached to TTY
STDIN is attached to a redirection
https://www.codenong.com/911168/ : 关于bash:如何检测我的shell脚本是否通过管道运行?
有一些注意的问题需要参考上面的链接,比如这种判断用在 ssh 的时候。
go 的判断方式package main
import (
"fmt"
"os"
)
func main() {
fi, _ := os.Stdin.Stat()
if (fi.Mode() & os.ModeCharDevice) == 0 {
fmt.Println("data is from pipe")
} else {
fmt.Println("data is from terminal")
}
}
https://ask.csdn.net/questions/1036806 : 检测命令是否通过管道传输 python 的判断方式
# /tmp/py1.py
import sys
import os
if not os.isatty(sys.stdin.fileno()):
print(sys.stdin.fileno())
print(sys.stdin.read())
else:
print("standard behavior")
# sys.stdin.isatty() 也可以直接用来判断
[root@nano-kvm-11 qemu]# echo "haha" | python /tmp/py1.py 0 haha [root@nano-kvm-11 qemu]# python /tmp/py1.py standard behaviorwhile read line 解决方式
单独使用 while read line 设置一个较短的时间,来获取管道前的结果,而不去进行判断,有管道就会等待,没管道会在短时间内停止。
[root@docker-181 ~]# sleep 10; echo " haha" | while read -t 0.1 line;do echo ${line};done
haha



