LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1069|回复: 10

readcd的输出好奇怪

[复制链接]
发表于 2006-9-17 00:52:57 | 显示全部楼层 |阅读模式
既不是stdout也不是stderr,和它类似的还有wget什么的,就是那个字符式的进度条。我想在python中用pipe获取readcd的的输出,用popen,结果发现它的输出无法用popen获得。给我的感觉就是在管道之前完成的。k3b中可以获取这个输出,不知道它是怎么做的。

哪位高人给看看?
发表于 2006-9-17 20:58:04 | 显示全部楼层
Post by cobranail
既不是stdout也不是stderr,和它类似的还有wget什么的,就是那个字符式的进度条。我想在python中用pipe获取readcd的的输出,用popen,结果发现它的输出无法用popen获得。给我的感觉就是在管道之前完成的。k3b中可以获取这个输出,不知道它是怎么做的。

哪位高人给看看?

一般进程启动时,默认会打开三个描述符:STDIN,STDOUT,STDERR。

既然是默认的,有些程序也可以不必默认,像这类无法从管道得到输出的程序很有可能采用了某些步骤来更改这些默认。最常用的做法类似如下:

伪代码:
[PHP]
close(STDOUT);
open("/dev/tty");
enter_process();
[/PHP]

一般的管道处理如下(忽略无关的细节):
伪代码:(以 ls | less为例)
[PHP]
生成一个管道;
if (fork() == 0)
{
      在子进程里安排默认的输入指向管道的读端;
      exec("less");     // 启动子进程(ls)
}
else
{
     在父进程里安排默认的输出指向管道的写端;
    exec("ls");    // 启动父进程(less)
}
[/PHP]

这里有一个问题:如果子进程不使用默认的安排,那么前面做的安排是没有用的,就像上面readcd做的一样,我lsof了一下这个进程打开的东西,如我所料:
它做了上面第一个伪代码做的事情:
1, 关闭了标准输出(这令前面所做的安排失效)
2, 把标准输出的描述符重新打开为/dev/tty;   //注:/dev/tty在LINUX的设备文件里描述为:当前终端设备。


SO, 管道失效了。
我尝试想了一下有没有解决的办法,但没想到,有好计的兄弟写写办法
回复 支持 反对

使用道具 举报

发表于 2006-9-17 21:35:27 | 显示全部楼层
用 括号 包起来?
回复 支持 反对

使用道具 举报

发表于 2006-9-17 22:02:41 | 显示全部楼层
wget 不是打印到stderr吗?

我在cmd.exe下都能wget url 2>logfile,或者wget -o logfile


  1. C:\Documents and Settings\troll>wget http://linuxsir.cn/ 2>log


  2. C:\Documents and Settings\troll>type log
  3. --21:58:59--  http://linuxsir.cn/
  4.            => `index.html'
  5. Resolving linuxsir.cn... 211.93.98.20
  6. Connecting to linuxsir.cn|211.93.98.20|:80... connected.
  7. HTTP request sent, awaiting response... 302 Found
  8. Location: http://www.linuxsir.cn/main [following]
  9. --21:59:01--  http://www.linuxsir.cn/main
  10.            => `main'
  11. Resolving www.linuxsir.cn... 211.93.98.20
  12. Reusing existing connection to linuxsir.cn:80.
  13. HTTP request sent, awaiting response... 301 Moved Permanently
  14. Location: http://www.linuxsir.cn/main/ [following]
  15. --21:59:03--  http://www.linuxsir.cn/main/
  16.            => `index.html'
  17. Reusing existing connection to linuxsir.cn:80.
  18. HTTP request sent, awaiting response... 200 OK
  19. Length: unspecified [text/html]

  20.     0K .......... ......                                       987.83 KB/s

  21. 21:59:04 (987.83 KB/s) - `index.html' saved [17002]
复制代码
回复 支持 反对

使用道具 举报

发表于 2006-9-17 22:06:47 | 显示全部楼层

  1.        f=file Specify  the  filename  where  the output should be
  2.               written or the inout should be  taken  from.  Using
  3.               '-'  as  filename  will  cause readcd to use stdout
  4.               resp. stdin
复制代码
回复 支持 反对

使用道具 举报

发表于 2006-9-17 22:40:08 | 显示全部楼层
sure.
标准出错没有被更改,所以可以。这个是楼主没有测试清楚。
但标准输出被更改了。这个的输出无法由重定向或管道得到的。

f=file
这个参数是指把从设备中读出的数据写到哪里去,如果是-表示写到标准输出。
而楼主我猜是想得到下面这样的输出:
[PHP]
# readcd dev=/dev/hdb sectors=150-10000 f=cdimage.raw
Read  speed:  9152 kB/s (CD  52x, DVD  6x).
Write speed:     0 kB/s (CD   0x, DVD  0x).
Capacity: 338515 Blocks = 677030 kBytes = 661 MBytes = 693 prMB
Sectorsize: 2048 Bytes
Copy from SCSI (0,1,0) disk to file 'cdimage.raw'
end:     10000
addr:    10000 cnt: 58
Time total: 10.684sec
Read 19700.00 kB at 1843.9 kB/sec.
[/PHP]
回复 支持 反对

使用道具 举报

发表于 2006-9-17 22:43:12 | 显示全部楼层
  1. Readcd:

  2. -       split read_capacity() into read_capacity() and print_capacity()
  3.         to make finally sure that readcd will not print to stdout
复制代码


如果不分开,那就糟糕了。
回复 支持 反对

使用道具 举报

发表于 2006-9-17 22:50:04 | 显示全部楼层
应该也是到stderr。
回复 支持 反对

使用道具 举报

发表于 2006-9-17 22:56:19 | 显示全部楼层
Post by troll
应该也是到stderr。

按上面给出的命令,加个2 > file.log
也是不行的,终端得到的输出不会重新向,我用lsof查看到0描述符是指向/dev/tty.
回复 支持 反对

使用道具 举报

发表于 2006-9-17 23:19:33 | 显示全部楼层
奇怪,某个版本的变更上有

  1. Verbose output now goes to stderr to allow readcd | cdrecord
复制代码


http://cvs.opensolaris.org/sourc ... .01/readcd/readcd.c

你看一下源码,应该不错。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

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