TIL:Bash 脚本中的超时【译】

原文链接 https://heitorpb.github.io/bla/timeout/ 前几天在工作中,我们有一个 Bash 脚本,用于设置一个 Web 服务器,并等待它启动后再继续执行后续操作。这个脚本运行正常,我们也没有遇到任何问题,直到出现了一个无限循环。 我们使用 Bash 内置的 until 来检查 Web 服务器是否正常: until curl --silent --fail-with-body 10.0.0.1:8080/health; do sleep 1 done 这很好用。除非我们的 Web 服务器在启动过程中崩溃,并且我们 sleep 1 永远等待。 这里有一个实用的工具:timeout。顾名思义,这个命令可以为其他命令添加超时功能。您指定想要等待命令的时间限制,如果该时间已过,timeout 会发送一个信号来终止它,并以非零状态退出。默认情况下,timeout 发送的是 SIGTERM 信号,但您可以通过 --signal 标志来更改它,例如 timeout --signal=SIGKILL 1s foo 。 例如,timeout 1s sleep 5 将向 sleep 发送 SIGTERM 信号 1秒后: $ time timeout 1s sleep 4 real 0m1,004s user 0m0,000s sys 0m0,005s $ echo $? 124 那么接下来应该将 timeout 和 until 结合起来: timeout 1m until curl --silent --fail-with-body 10.0.0.1:8080/health; do sleep 1 done 唯一的问题是这行不通。timeout 需要一个可终止的命令,而 until 是一个 shell 关键字:你不能 SIGTERMuntil``。我们无法使用 timeout 与任何 shell 内建命令一起使用。 ...

2025-05-30 · 1 分钟 · czyt

12 个改变我生产力的个人go技巧【译】

原文链接https://dev.to/func25/12-personal-go-tricks-that-transformed-my-productivity-mne 作者 我通常在 Devtrovert 分享有关系统设计和 Go 的见解。请随时查看我的 LinkedIn Phuong Le 以获取最新帖子。 在从事生产项目时,我注意到我经常重复代码并利用某些技术,直到后来回顾我的工作时才意识到这一点。 为了解决这个问题,我开发了一个解决方案,事实证明它对我很有帮助,而且我认为它对其他人也可能有用。 下面是从我的实用程序库中随机挑选的一些有用且通用的代码片段,没有任何特定的分类或特定于系统的技巧。 1.跟踪使用时间的技巧 如果您有兴趣跟踪 Go 中函数的执行时间,您可以使用一个简单而有效的技巧,只需使用“defer”关键字的一行代码即可。您所需要的只是一个 TrackTime 函数: // Utility func TrackTime(pre time.Time) time.Duration { elapsed := time.Since(pre) fmt.Println("elapsed:", elapsed) return elapsed } func TestTrackTime(t *testing.T) { defer TrackTime(time.Now()) // <--- THIS time.Sleep(500 * time.Millisecond) } // elapsed: 501.11125ms 1.5.两阶段延迟 Go 延迟的强大之处不仅在于任务完成后的清理工作,还在于任务完成后的清理工作。这也是为了做好准备,请考虑以下事项: func setupTeardown() func() { fmt.Println("Run initialization") return func() { fmt.Println("Run cleanup") } } func main() { defer setupTeardown()() // <-------- fmt.Println("Main function called") } // Output: // Run initialization // Main function called // Run cleanup 感谢 Teiva Harsanyi 介绍了这种优雅的方法。 ...

2023-10-05 · 4 分钟 · czyt

golang http Reverse Proxy使用备忘

创建 一般使用 使用 httputil.NewSingleHostReverseProxy 即可 返回Response 当我们想实现获取通过ReverseProxy的请求结果时,可以使用自定义的 responsewriter 来实现。参考定义 func (p *ReverseProxy) ServeHTTP(rw http.ResponseWriter, req *http.Request) { .... } type ResponseWriter interface { // Header returns the header map that will be sent by // WriteHeader. The Header map also is the mechanism with which // Handlers can set HTTP trailers. // // Changing the header map after a call to WriteHeader (or // Write) has no effect unless the modified headers are // trailers. // // There are two ways to set Trailers. The preferred way is to // predeclare in the headers which trailers you will later // send by setting the "Trailer" header to the names of the // trailer keys which will come later. In this case, those // keys of the Header map are treated as if they were // trailers. See the example. The second way, for trailer // keys not known to the Handler until after the first Write, // is to prefix the Header map keys with the TrailerPrefix // constant value. See TrailerPrefix. // // To suppress automatic response headers (such as "Date"), set // their value to nil. Header() Header // Write writes the data to the connection as part of an HTTP reply. // // If WriteHeader has not yet been called, Write calls // WriteHeader(http.StatusOK) before writing the data. If the Header // does not contain a Content-Type line, Write adds a Content-Type set // to the result of passing the initial 512 bytes of written data to // DetectContentType. Additionally, if the total size of all written // data is under a few KB and there are no Flush calls, the // Content-Length header is added automatically. // // Depending on the HTTP protocol version and the client, calling // Write or WriteHeader may prevent future reads on the // Request.Body. For HTTP/1.x requests, handlers should read any // needed request body data before writing the response. Once the // headers have been flushed (due to either an explicit Flusher.Flush // call or writing enough data to trigger a flush), the request body // may be unavailable. For HTTP/2 requests, the Go HTTP server permits // handlers to continue to read the request body while concurrently // writing the response. However, such behavior may not be supported // by all HTTP/2 clients. Handlers should read before writing if // possible to maximize compatibility. Write([]byte) (int, error) // WriteHeader sends an HTTP response header with the provided // status code. // // If WriteHeader is not called explicitly, the first call to Write // will trigger an implicit WriteHeader(http.StatusOK). // Thus explicit calls to WriteHeader are mainly used to // send error codes. // // The provided code must be a valid HTTP 1xx-5xx status code. // Only one header may be written. Go does not currently // support sending user-defined 1xx informational headers, // with the exception of 100-continue response header that the // Server sends automatically when the Request.Body is read. WriteHeader(statusCode int) } 例子 package main import ( "fmt" "log" "net/http" "net/http/httputil" "net/url" "github.com/gin-gonic/gin" ) type customWriter struct { http.ResponseWriter } func NewCustomWriter(w http.ResponseWriter) *customWriter { return &customWriter{w} } func (c *customWriter) Header() http.Header { return c.ResponseWriter.Header() } func (c *customWriter) Write(data []byte) (int, error) { fmt.Println(string(data)) //get response here return c.ResponseWriter.Write(data) } func (c *customWriter) WriteHeader(i int) { c.ResponseWriter.WriteHeader(i) } func main() { router := gin.Default() router.GET("/", func(ctx *gin.Context) { targetURL, err := url.Parse("http://192.168.0.70:8090") if err != nil { log.Println(err) } proxy := httputil.NewSingleHostReverseProxy(targetURL) proxy.ServeHTTP(NewCustomWriter(ctx.Writer), ctx.Request) }) router.Run(":8899") } 封装个函数 ...

2022-09-30 · 4 分钟 · czyt

golang转换任意长度[] byte为int

package main import ( "encoding/binary" "fmt" ) func main() { slices := [][]byte{ {1}, {1, 2}, {1, 2, 3}, {1, 2, 3, 4}, {1, 2, 3, 4, 5}, {1, 2, 3, 4, 5, 6}, {1, 2, 3, 4, 5, 6, 7}, {1, 2, 3, 4, 5, 6, 7, 8}, } for _, s := range slices { fmt.Println(getInt1(s), getInt2(s)) } } func getInt1(s []byte) int { var b [8]byte copy(b[8-len(s):], s) return int(binary.BigEndian.Uint64(b[:])) } func getInt2(s []byte) int { var res int for _, v := range s { res <<= 8 res |= int(v) } return res } 参考 ● https://www.reddit.com/r/golang/comments/4xn341/converting_byte_to_int32/ ● https://forum.golangbridge.org/t/converting-single-byte-slice-to-int

2022-07-30 · 1 分钟 · czyt