LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: enruan

如何将标准错误输出重定向到一个文件的同时在屏幕上也显示,谢谢[基本解决]

 关闭 [复制链接]
发表于 2004-4-12 12:54:05 | 显示全部楼层
最初由 enruan 发表
晕,好使是好使,不过,为什么,怎么会这样?

不是已经把1重定到/dev/null了吗?

1. 2>&1  #使文件描述符2成为输出文件描述符1的副本,注意,此时文件描述符1还没有被重定向
2. >/dev/null #等价于1>/dev/null,把文件描述符1重定向到/dev/null,这时候的标准输出就变成它的副本即文件描述符2了

相反,如果两者颠倒顺序,那标准输出连同它的副本都会被重定向到/dev/null,这是一个逻辑问题。

  1. [root@home i386]# make 1>/dev/null 2>&1
  2. [root@home i386]# make 2>&1 1>/dev/null
  3. make: *** No targets specified and no makefile found.  Stop.
复制代码

兄弟现在明白了嘛?
 楼主| 发表于 2004-4-12 13:04:15 | 显示全部楼层
恩,非常谢谢,再想想,懂了一定报告,

还能再给详细解释一下
这个的吗?

exec 9>&1
cmd 2>&1 >&9 9>&− | tee logfile 9>&−
exec 9>&−


没看懂,
有点儿乱,
把我脑子都一起给重定向了


或者给个链接,
 楼主| 发表于 2004-4-12 13:11:37 | 显示全部楼层
恩,差不多明白一点儿了,
试一下这个命令就明白了
  1. make 2>1 1>/dev/null
复制代码


这个&根C语言里的取址差不多
发表于 2004-4-12 13:13:19 | 显示全部楼层
exec 9>&1 #把fd1的指针复制到fd9,即dup(1,9),或者干脆理解为fd9=fd1
#注意,此时fd9和fd1同时指向一个文件。也可认为将fd1的指针保存在fd9中一份
cmd 2>&1 >&9 9>&− | tee logfile 9>&−
#这一句比较麻烦
#首先shell创建一个pipe,然后分别fork两个subshell
#看看第一个subshell做了什么?
#首先每个subshell都精确拷贝一份父进程的fd表,即0,1,2和9都复制过来了
#然后将fd1指向pipe文件,此时fd9仍然保存着父进程中fd1的文件指针,如果父进程没有重定向的话,就是stdout
#然后处理这段2>&1 >&9 9>&−重定向命令。既
#fd2=fd1; fd1=fd9; fd9=null
#结果是fd2指向fd1原先指向的pipe文件,fd1指向fd9指向的文件,即stdout,然后将fd9关闭,由于这时fd1和fd9同时指向同一个文件stdout,所以stdout并没有真正关闭,只是减少打开次数。
#最后subshell执行cmd命令,cmd要输出时取fd1中的指针,即stdout,输出错误时,取fd2中的指针,即pipe,这样tee从pipe中只得到了cmd输出的错误信息。
#再看看第二个subshell做了什么?
#同样精确拷贝一份父进程的fd表
#然后将fd0指向pipe文件。
#然后处理这段 9>&−重定向命令。既关闭fd9。

exec 9>&− #回到父进程,关闭fd9
 楼主| 发表于 2004-4-12 13:16:19 | 显示全部楼层
谢谢,
收到
发表于 2004-4-12 13:22:42 | 显示全部楼层
精彩。:cool:
 楼主| 发表于 2004-4-12 13:24:02 | 显示全部楼层
强,好强

看我理解的对不对,

1.File Descriptor(FD) 相当于指针,里面隐藏了具体的实现
2.管道定位符(|)的优先级是最高的
3.&相当于取址
 楼主| 发表于 2004-4-12 13:33:54 | 显示全部楼层
最初由 r2007 发表

#结果是fd2指向fd1原先指向的pipe文件,fd1指向fd9指向的文件,即stdout,然后将fd9关闭,由于这时fd1和fd9同时指向同一个文件stdout,所以stdout并没有真正关闭,只是减少打开次数。


是不是说这样也行啊?

  1. exec 9>&1
  2. cmd 2>&1 >&9 | tee logfile
  3. exec 9>&-
复制代码

子shell退出的时候是不是所有的fd都自动关了?
发表于 2004-4-12 13:38:12 | 显示全部楼层
必须得显式关闭。
在Linux(UNIX)编程中,/dev/fd 目录下的0,1,2,3,等文件,的确是指内存打开的文件的文件描述符!打开文件/dev/fb/n等效于复制描述符n(假述描述符n是打开的),BSD系统是支持这种特征的,比如fb=open("/dev/fd/0",mode);等效于fb=dup(0);描述符0和fd共享同一文件表项,一般情况下是由shell使用的,允许程序以对待其他路径名一样的方式使用路径名参数来处理标准输入和标准输出,如filter file2| cat file1 - file3 | lpr。首先cat读file1,接着读其标准输入(就是filter file2命令的输出),然后读file3,如系统支持/dev/fd,则可以删除cat对-的特殊处理,也就可以键入以下命令filter file2 | cat file1 /dev/fd/0 file3 | lpr
/dev/fd提高了文件名参数的一致性.

  1. [root@home dev]# exec 9>&1
  2. [root@home dev]# id 2>&1 1>&9
  3. uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
  4. [root@home dev]# ls /dev/fd
  5. 0  1  2  3  9
  6. [root@home dev]# exec 9>&-
  7. [root@home dev]# ls /dev/fd
  8. 0  1  2  3
复制代码
 楼主| 发表于 2004-4-12 14:13:20 | 显示全部楼层

Faint,why


  1. root # [color=green](make;date;sleep 5;make;date) 2>logfile | cat logfile[/color]
  2. -bash: make: command not found
  3. root # [color=green]more logfile[/color]
  4. -bash: make: command not found
  5. -bash: make: command not found
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表