go 问题记录(日志丢失)
问题描述:
在go程序中,通过执行一个命令启动一个子命令,并通过pipe读取子程序的标准输入和输出,通过scanner默认按行读取,此时如果子程序输出时没有携带’\n’,scanner就不会打印输出,而是会累积到缓存buf上限,最终被丢弃,直到遇到一个\n,然后输出所有的内容,默认buf缓存上限时65536,如果日志打印处还有限制,如glog就限制最大的打印字节数为4096,那么就会导致日志再次丢失。
解决方法:
不适用scanner去按行读取,直接读取管道的内容,然后设置上限,超过时或者遇到’\n’时打印
测试代码:
子程序:
#include <stdio.h>
#include <unistd.h>int main() {
int count = 0;while (1) {fprintf(stderr, "%d", count);count = (count + 1) % 10;usleep(500); // Sleep for 500,000 microseconds (0.5 seconds)
}return 0;
}
主程序:
package mainimport ("bufio""fmt""os/exec""strings""log"
)func main() {cmd := exec.Command("./test")stdout, err := cmd.StdoutPipe()if err != nil {fmt.Println("Error creating StdoutPipe:", err)return}cmd.Stderr = cmd.Stdouterr = cmd.Start()if err != nil {fmt.Println("Error starting command:", err)return}scanner := bufio.NewScanner(stdout)// scanner.Split(bufio.ScanBytes)// buf := ""// for scanner.Scan() {// buf += scanner.Text()// if strings.Contains(buf, "\n") || len(buf) >= 256 {// log.Printf("%s", buf)// buf = ""// }// }for scanner.Scan() {log.Printf("%s", scanner.Text())}if err := scanner.Err(); err != nil {fmt.Println("Error reading standard output:", err)}err = cmd.Wait()if err != nil {fmt.Println("Error waiting for command to finish:", err)}
}
修改程序:
package mainimport ("bufio""fmt""io""log""os/exec"
)func getReaderSize(rd io.Reader) {b, ok := rd.(*bufio.Reader)if ok {log.Printf("rd size: %d", b.Size())} else {log.Printf("rd is not bufio.Reader")}
}func main() {// Command to executecmd := exec.Command("./test")// Create a pipe to capture the standard output of the commandstdout, err := cmd.StdoutPipe()if err != nil {fmt.Println("Error creating StdoutPipe:", err)return}cmd.Stderr = cmd.Stdout// Start the commanderr = cmd.Start()if err != nil {fmt.Println("Error starting command:", err)return} Create a scanner to read the command's standard output//scanner := bufio.NewScanner(stdout)//scanner.Split(bufio.ScanBytes)// Read and print each line from the output//buf := make([]byte, 256)//bufLen := 0//for scanner.Scan() {// buf[bufLen] = scanner.Bytes()[0]// // buf = append(buf, scanner.Bytes()...)// bufLen += 1// if buf[bufLen-1] == '\n' || bufLen >= 256 {// log.Printf("%s", string(buf[:bufLen]))// bufLen = 0// }//}// Check for errors in scanning//if err := scanner.Err(); err != nil {// fmt.Println("Error reading standard output:", err)//}// Create a buffered reader to read from the command's stdoutreader := bufio.NewReaderSize(stdout, 256)getReaderSize(stdout)log.Printf("reader size: %d", reader.Size()) Buffer to store incomplete lines//var incompleteLine []byte// Buffer to read chunks of bytes//chunk := make([]byte, 256)////for {// // Read a chunk of bytes// n, err := reader.Read(chunk)// if err != nil {// break // Break the loop when an error occurs (e.g., when the command finishes)// }//// // Process each byte in the chunk// for i := 0; i < n; i++ {// b := chunk[i]//// // Check for newline or length exceeding 256// if b == '\n' || len(incompleteLine) >= 256 {// // Print the line// log.Printf("%s", incompleteLine)//// // Reset the incomplete line buffer// incompleteLine = nil// } else {// // Add the byte to the incomplete line buffer// incompleteLine = append(incompleteLine, b)// }// }//}for {s, err := reader.ReadSlice('\n')if err != nil && err != bufio.ErrBufferFull {if len(s) > 0 {log.Printf("reader err but exist data, reader size: %d, read string size: %d, string: %s", reader.Size(), len(s), string(s))}fmt.Println("Error reader ReadString:", err)break // Break the loop when an error occurs (e.g., when the command finishes)}log.Printf("reader size: %d, read string size: %d, string: %s", reader.Size(), len(s), string(s))}// Wait for the command to finisherr = cmd.Wait()if err != nil {fmt.Println("Error waiting for command to finish:", err)}
}
benchmark test:
package mainimport ("strconv""strings""testing"
)func stringTest1() string {var buf stringfor i := 0; i < 256; i++ {buf += strconv.Itoa(i)}return buf
}func stringTest2() string {var buf strings.Builderfor i := 0; i < 256; i++ {buf.Write([]byte(strconv.Itoa(i)))}return buf.String()
}func stringTest3() string {var buf = make([]byte, 0)for i := 0; i < 256; i++ {buf = append(buf, []byte(strconv.Itoa(i))...)}return string(buf)
}func stringTest4() string {var buf = make([]byte, 256)for i := 0; i < 256; i++ {buf[i] = '1'}return string(buf)
}func BenchmarkStringTest1(b *testing.B) {for i := 0; i < b.N; i++ {stringTest1()}
}
func BenchmarkStringTest2(b *testing.B) {for i := 0; i < b.N; i++ {stringTest2()}
}
func BenchmarkStringTest3(b *testing.B) {for i := 0; i < b.N; i++ {stringTest3()}
}
func BenchmarkStringTest4(b *testing.B) {for i := 0; i < b.N; i++ {stringTest4()}
}
benchmark test
cmd:
go test -bench . -benchmem
go test -bench=<function>
相关文章:
go 问题记录(日志丢失)
问题描述: 在go程序中,通过执行一个命令启动一个子命令,并通过pipe读取子程序的标准输入和输出,通过scanner默认按行读取,此时如果子程序输出时没有携带’\n’,scanner就不会打印输出,而是会累…...
彻底解决 MAC Android Studio gradle async 时出现 “connect timed out“ 问题
最近在编译一个比较老的项目,git clone 之后使用 async 之后出现一下现象: 首先确定是我网络本身是没有问题的,尝试几次重新 async 之后还是出现问题,网上找了一些方法解决了本问题,以此来记录一下问题是如何解决的。 …...
计算机网络第4章(网络层)
4.1、网络层概述 简介 网络层的主要任务是实现网络互连,进而实现数据包在各网络之间的传输 这些异构型网络N1~N7如果只是需要各自内部通信,他们只要实现各自的物理层和数据链路层即可 但是如果要将这些异构型网络互连起来,形成一个更大的互…...
SpringbootWeb案例
准备工作 需求说明 部门管理 部门管理功能开发包括:查询部门列表、删除部门、新增部门、修改部门 员工管理功能开发包括:查询员工列表(分页、条件)、删除员工、新增员工、修改员工 环境搭建 环境搭建步骤:1. 准备数据库表(dept、emp)…...
【初中生讲机器学习】4. 支持向量机算法怎么用?一个实例带你看懂!
创建时间:2024-02-02 最后编辑时间:2024-02-03 作者:Geeker_LStar 你好呀~这里是 Geeker_LStar 的人工智能学习专栏,很高兴遇见你~ 我是 Geeker_LStar,一名初三学生,热爱计算机和数学,我们一起加…...
CentOS下安装vlc
一、引言 vlc是一跨多媒体播放器,可以播放本地媒体文件和网络串流,帮助我们排查音视频开发过程中遇到的问题。大部分情况下,我们只需要在Windows系统下安装vlc就可以了。但有一种情况是需要在Linux下安装vlc的:我们的音视频拉流软…...
概率论中的全概率公式、贝叶斯公式解析
全概率公式 定义 全概率公式是用来计算一个事件的概率,这个事件可以通过几个互斥事件的并集来表示。这几个互斥事件称为“完备事件系”。实质是由原因推结果。 公式 用途 全概率公式通常用于计算一个事件的总概率,特别是当这个事件与几个不同的因素相关…...
亿赛通-数据泄露防护(DLP)UploadFileList;login接口存在任意文件读取漏洞 附POC软件
@[toc] 亿赛通-数据泄露防护(DLP)UploadFileList;login接口存在任意文件读取漏洞 附POC软件 免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文…...
如何使用 Google 搜索引擎保姆级教程(附链接)
一、介绍 "Google语法"通常是指在 Google 搜索引擎中使用一系列特定的搜索语法和操作符来精确地定义搜索查询。这些语法和操作符允许用户过滤和调整搜索结果,提高搜索的准确性。 二、安装 Google 下载 Google 浏览器 Google 官网https://www.google.c…...
SpringBoot实现轻量级接口反向代理、转发
目录 1、基本的对象1.1 配置类1.2 实体DTO1.3 路由代理拓展器1.4 请求对象 RestTemplate 2、核心转发代码3、暴露接口4、基础配置 前言:想实现一个轻量级的接口反向代理和转发的一个接口服务,可以通过这个服务做一些需要认证才能访问的接口给到前端使用&…...
算法训练营day21,回溯1
77. 组合 func combine(n int, k int) [][]int { //存储全部集合 result : make([][]int, 0) //存储单次集合 path : make([]int, 0) var backtrace func(n int, k int, startIndex int) backtrace func(n int, k int, startIndex int) { //当单次集合大小和k值相等ÿ…...
延伸与应用(三)婚姻与经济、运动、宗教、科技与经济
53.幸福婚姻的经济ABC方程式 夫以信先其妇,则妇以信顺其夫。上秉常以化下,下服常而应上,其不化者,百未有一也。 ——《傅子》,傅玄(217—278) 在现代的小家庭中,由于家庭…...
mac上,配置bundletool,将aab转为apk
1.第一步打开终端,安装brew 2.安装bundletool brew install bundletool 3.aab转apk bundletool build-apks --bundle/MyApp/my_app.aab --output/MyApp/my_app.apks 如果下载了bundletool--xxx.jar,脚本命令前加 java -jar bundletool-all-1.5.0.j…...
wangEditor v4的简单使用
当前文档是 wangEditor v4 版本的。 wangEditor v5 已经正式发布,可参考文档。 v5 发布之后,v4 将不再开发新功能。 介绍 English documentation wangEditor4 —— 轻量级 web 富文本编辑器,配置方便,使用简单。 官网&#…...
简单实践 java spring boot 自动配置模拟
1.概要 1.1 需求,自己写一个redis-spring-boot-starter模拟自动配置 自动配置就是在引入*-starter坐标后,可以已经spring框架的规则实现一些Bean的自动注入,并设置一些参数的默认值,且也可以在引入的工程中修改这些配置的值。这…...
BeanDefinition学习
Spring版本5.1.x Spring中的BeanDefinition是一个接口,用于描述Spring容器中Bean的元数据。BeanDefinition描述了Bean的各种属性,如名称、依赖关系、初始化方法等。这个接口通常用于在Spring的IoC容器中注册Bean,并且当容器需要创建Bean实例…...
ASP.NET的GridView控件中,实现同列内容合并
在ASP.NET的GridView控件中,实现同列内容合并的方法主要有两种:一种是使用RowDataBound事件,另一种是使用自定义定义函数 使用RowDataBound事件 这种方法是在GridView的每一行绑定数据时,比较当前行和前一行的同一列的值&#x…...
【文本到上下文 #8】NLP中的变形金刚:解码游戏规则改变者
一、说明 欢迎来到我们对不断发展的自然语言处理 (NLP) 领域的探索的第 8 章。在本期中,我们将重点介绍一项重塑 NLP 格局的突破性创新:Transformers。在我们之前对 seq2seq 模型、编码器-解码器框架和注意力机制的讨论之后&#…...
mysql主流版本5.5/5.6/5.7/8.0重置修改密码方法
最近几天来回切换各个Mysql版本重置密码,记录一下各个版本重置密码的方法。 MySql 5.5 SET PASSWORD FOR usernamelocalhost PASSWORD(new_password);MySql5.6 SET PASSWORD FOR usernamelocalhost new_password;MySql5.7 ALTER USER usernamelocalhost IDENT…...
设计模式——备忘录模式
跟多内容,前往IT-BLOG 备忘录模式(Memento Pattern): 保存对象的某个状态,以便在未来需要的时候进行数据的恢复。相当容易理解,举个简单的例子:Word 软件在编辑时按 CtrlZ 组合键时能撤销当…...
visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...
微服务通信安全:深入解析mTLS的原理与实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、引言:微服务时代的通信安全挑战 随着云原生和微服务架构的普及,服务间的通信安全成为系统设计的核心议题。传统的单体架构中&…...
Vue3 PC端 UI组件库我更推荐Naive UI
一、Vue3生态现状与UI库选择的重要性 随着Vue3的稳定发布和Composition API的广泛采用,前端开发者面临着UI组件库的重新选择。一个好的UI库不仅能提升开发效率,还能确保项目的长期可维护性。本文将对比三大主流Vue3 UI库(Naive UI、Element …...
Xcode 16 集成 cocoapods 报错
基于 Xcode 16 新建工程项目,集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...
Qt Quick Controls模块功能及架构
Qt Quick Controls是Qt Quick的一个附加模块,提供了一套用于构建完整用户界面的UI控件。在Qt 6.0中,这个模块经历了重大重构和改进。 一、主要功能和特点 1. 架构重构 完全重写了底层架构,与Qt Quick更紧密集成 移除了对Qt Widgets的依赖&…...
统计学(第8版)——统计抽样学习笔记(考试用)
一、统计抽样的核心内容与问题 研究内容 从总体中科学抽取样本的方法利用样本数据推断总体特征(均值、比率、总量)控制抽样误差与非抽样误差 解决的核心问题 在成本约束下,用少量样本准确推断总体特征量化估计结果的可靠性(置…...
