灵活使用stdout和stderr,优化EDA的LOG捕获

EDA工具的log(日志)捕获,是一个经常会用到的功能,有助于用户查看long run job的状态和错误捕获,这里一般是利用了linux下的重定向(redirect)或者输出捕获(tee),这里通过对linux这两个命令的学习梳理,用户可以根据自身需要,优化EDA工具的LOG捕获工作。闲言少叙,ICer GO!
在这里插入图片描述

在Linux下,对于IO管理有三个标记,分别如下:

0:stdin
1:stdout
2:stderr

PTS的理解

可以看到,无论是0/1/2最后都会指向/dev/pts/166这个终端号(166),可以理解,这个166终端既可以接受stdin,也可以打印stdout(如上所述)和stderr,用户在/dev/fd目录下,可以看到类似下面的结构:
在这里插入图片描述
PTS是linux下的虚拟终端(pty)的一种实现方法。这里的/dev/pts/166可以简单的理解为当前用户的具象化的虚拟终端tty。
这里表达的意思是:当前的伪终端的所有打印都会通过/dev/pts/166这个“设备”完成,这个“设备”既可以接受stdin,也可以输出stdout和stderr。

stdin(0):

在linux下,所有的输入对被归为stdin,可以是键盘输入,也可以是文件输入,键盘输入在此不赘述。
文件输入需要借助于输入重定向<实现
在这里插入图片描述
抑或利用0(stdin)结合输入重定向实现:
在这里插入图片描述

stdout(1):

输出重定向到指定设备

linux下的重定向符>,可以指向固定设备,譬如这里重定向到/dev/tty,就会带来一种类似屏幕打印的效果。
在这里插入图片描述
也可以指向linux的"null设备"。
在这里插入图片描述

输出重定向到指定文件

相较于重定向到设备,linux下的输出重定向符更多的是指向指定文件,譬如下例:
在这里插入图片描述
在使用重定向stdout命令的时候,如果命令的返回只有stdout,那么这个命令不会有任何返回信息,所有的信息都被重定向到指定文件中去了。
由于默认的>的行为是对stdout的重定向,这里就近似等同于1>,所以,一种对stdout,更为完整的重定向写法如下所示:

在这里插入图片描述

stderr(2):

日常的使用中,用户不可能保证每一个命令都可以正常执行,在这种情况下,命令的返回信息可能就会参杂非stdout的信息,linux将这一类归为stderr。譬如下例:
在这里插入图片描述
这里用户尝试ls 一个不存在的文件f4.txt。可以看到,这个时候在使用重定向输出命令的时候,终端上有了一个错误的信息输出,来表述f4.txt这个文件是不存在的。
如果这个时候查看输出重定向的消息,f1234.log。可以看到,这里只有正常的文件信息,所以,正常的重定向命令,确实只是捕获了stdout,如果用户的想实现stderr的重定向,需要使用下面的方法:
在这里插入图片描述
这个时候需要借用2>来描述对于stderr信息的处理,通过上述例子,屏幕上并没有任何信息输出,这里的stdout和stderr分别被重定向到f123.log和f4.log文件里了。

类似的用户也可以只针对stderr进行重定向,譬如:
在这里插入图片描述
这个时候,屏幕上会把正常的stdout打印出来,stderrr信息被保留到了f4.log。
由于默认的>的行为是对stdout的重定向,这里就近似等同于1>,所以,一种对stdout/stderr,更为完整的重定向写法如下所示:
在这里插入图片描述

stdout和stderr重定向同一文件

有些情况下,用户不想将stdout和stderr分开,这样的好处是可以把命令执行的所有信息都捕捉下来(stdout+stderr),这个时候需要用到一个修饰符&,譬如下例:
在这里插入图片描述
这里的重定向符号结合了修饰符,变成了&>,所有的stdout和stderr都会被重定向到f1234.log里边了。
常言道条条大路通罗马,linux就是古谚的忠实践行者,通过命令后缀2>&1的方式,也可以实现上述功能,具体见下:
在这里插入图片描述
这个方式是将stderr先重定向到stdout,然后在同一将stdout 重定向到f1234.log。
PS:对应的也可以对stdout做重定向,有兴趣的小伙伴可以试一下

重定向和屏幕捕获(tee)异同

在日常的工作中,由于EDA工具的日志都会比较长,如果简单的使用重定向,那么命令行在EDA任务完成前,屏幕都不会有任何回显,这个时候会给人一些EDA工具运行出错的误判,所以在日冲工作中,更多的工程师喜欢使用屏幕捕获(tee)这个命令:EDA工具在打印信息到屏幕上的时候,同时也会将屏显内容捕获到指定文件中:
譬如:
在这里插入图片描述
但是tee一样会有类似重定向的问题,就是对于stdout和stderr的分别对待,这个从tee的manual可以看到
在这里插入图片描述
所以说tee只能捕获屏幕上的stdout信息,而不能去捕获stderr的信息,虽然stdout和stderr都会出现在屏幕上,譬如下例:
在这里插入图片描述
但是对于EDA用户,这个是不方便的,用户总是期望捕获命令的所有输出。结合上述讲解,也可以借助修饰符&让tee完成这个任务:
- 方法一:使用命令|&进行捕获,譬如下例:
在这里插入图片描述
方法二:对stderr进行重定向后处理后的,而后用tee对stdout进行捕获
在这里插入图片描述

shell的异同

由于bash是linux默认的shell,这里对stdin/stdout/stderr(0/1/2)支持的很好,所以上述命令都可以正常使用,但是对于csh/tcsh这类基于C的shell,确实不能直接使用0/1/2进行处理的
在这里插入图片描述

从上例可以看到,2这个在bash里边标记stderr的标记字,在tcsh下是被当作argument来处理的。但是tcsh的作者还是尊重原著的,使用修饰符&,就可以让命令在bash/tcsh下实现兼容:
在这里插入图片描述
所以,对于shell之间,唯一的区别就是tcsh下无法将stdout和stderr分别处理,只能做合并,或者只捕获stdout。

EDA工具日志捕获实践

经过上边的描述,用户对于linux下的重定向和tee有了全面的认识,对于大部分日常的EDA工具,用户使用常规对stdout处理的命令就可以了,但是对于S家的StarRC工具,这个可能有一点需要特殊处理,
用户尝试对StarXtract 命令的输出进行常规输出重定向,但是这个时候尽管使用了>,但是屏幕上依然有输出
在这里插入图片描述
这个时候,再看重定向的目标文件,发现字节数竟然是0。
在这里插入图片描述
所以可以判定,StarXtract 这个命令的输出都被判定为stderr。
方法一:重定向捕获:用户需要使用2>重定向StarXtract 命令输出:
在这里插入图片描述
方法二:tee捕获:用户需要使用|&重定向StarXtract 命令输出:

在这里插入图片描述

【敲黑板划重点】

image-20240503184222477
重定向是linux基础的IO操作方式,都可以轻松使用0/1/2(bash下)进行控制,但是对于tee这个屏幕捕获的命令,是针对stdout的捕获,和重定向相比,用户只能选择把steout或者stdout和stderr统一捕获到同一文件中,不能分开捕获,这个也是符合tee的设计初衷的。
对于所有的EDA工具的屏幕输出,对于常见的shell(bash/tcsh/csh)用户可以一劳永逸的是用 “|&”的方式对stdout和stderr将屏幕输出全部捕获出来
cmd |& tee cmd.log

参考资料

刘忆智(清华大学出版社出版) Linux从入门到精通

<think>好的,用户想了解如何在编程中将stdoutstderr合并或串联处理。首先,我需要回忆一下标准输出标准错误的基本概念。记得stdout是正常输出,而stderr用于错误信息,它们默认都输出到终端,但可以重定向到文件或其他地方。 用户提到“串联处理”,可能是指将两者合并到一个流中,或者同时捕获它们。根据之前的引用资料,特别是引用[2],里面提到了使用2>&1来将stderr重定向到stdout。比如在命令行中,可以用command > output.log 2>&1,这样两个流都会写入同一个文件。但用户是在编程中实现,可能需要不同语言的例子。 接下来,我需要考虑不同编程语言中的实现方式。比如在Python中,可以通过修改sys.stdoutsys.stderr的指向,让它们都输出到同一个地方。或者使用subprocess模块运行外部命令时,合并子进程的输出。比如在subprocess.Popen中,设置stderr=subprocess.STDOUT,这样两个流就会被合并。 然后,用户可能还需要知道如何实时处理合并后的输出,比如逐行读取同时包含stdoutstderr的内容。这时候在Python中可以使用communicate()方法,或者逐行读取管道。 另外,要注意不同操作系统可能有差异,比如在WindowsUnix-like系统下的行为是否一致。不过大多数情况下,使用标准库的方法应该是跨平台的。 还需要提醒用户,合并后可能无法区分哪些是stdout,哪些是stderr,除非在输出内容中加入标记。或者,如果有需要的话,可以分别捕获然后合并,但保留顺序信息,这可能会比较复杂。 总结一下,可能的步骤是:1. 命令行中的重定向方法;2. 在编程语言中(如Python)通过重定向流或子进程处理来合并;3. 注意事项潜在问题。同时,需要引用提供的资料中的例子,比如引用[2]中的方法,确保回答有依据。</think>在编程中合并标准输出(stdout)标准错误(stderr)有多种实现方式,具体方法取决于编程语言需求场景。以下是两种典型实现方案: ### 一、命令行环境实现 通过操作系统的重定向符号实现流合并: ```bash # 合并后存入文件(覆盖模式) your_command > combined.log 2>&1 # 合并后追加到文件 your_command >> combined.log 2>&1 ``` 这里的`2>&1`表示将文件描述符2(stderr)重定向到文件描述符1(stdout)的当前位置[^2]。注意重定向顺序必须**先指定stdout目标**,再重定向stderr。 ### 二、Python编程实现 #### 方案1:重定向系统流 ```python import sys class UnifiedOutput: def write(self, message): # 在此处添加统一处理逻辑 sys.__stdout__.write(message) sys.stdout = UnifiedOutput() sys.stderr = UnifiedOutput() print("正常输出") # 将被UnifiedOutput处理 raise Exception("错误信息") # 同样进入UnifiedOutput ``` 此方法会**同时影响所有print语句异常输出**,需注意原始流的备份与恢复。 #### 方案2:子进程捕获 ```python import subprocess process = subprocess.Popen( ['your_command'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT # 关键合并参数 ) for line in process.stdout: print(f"捕获到输出: {line.decode().strip()}") ``` 此方法特别适用于**捕获外部命令的混合输出**,且能保持输出时序准确性。 ### 三、注意事项 1. **顺序保障**:合并后的输出顺序可能受缓冲机制影响,建议在关键位置添加`flush()`调用 2. **性能影响**:高频输出场景下,同步处理可能产生额外开销 3. **诊断难度**:合并后难以区分原始来源,可考虑添加前缀标记如: ```python sys.stderr.write("[ERROR] " + message) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值