分类
linux

ssh设置心跳 防止自动超时

Server Side:

vim /etc/ssh/sshd_config
ClientAliveInterval 30
ClientAliveCountMax 60
systemctl restart sshd

Client Side:

vim /etc/ssh/ssh_config
Host *
ServerAliveInterval 30
ServerAliveCountMax 60
分类
golang

golang json.Marshal 避免转义html

在对接微信客服消息的时候,发现换行符、a标签等都被转义了。
调查发现是在对结构体调用json.Marshal发生的。

https://godoc.org/encoding/json#Marshal

String values encode as JSON strings coerced to valid UTF-8, replacing invalid bytes with the Unicode replacement rune. The angle brackets “<” and “>” are escaped to “\u003c” and “\u003e” to keep some browsers from misinterpreting JSON output as HTML. Ampersand “&” is also escaped to “\u0026” for the same reason. This escaping can be disabled using an Encoder that had SetEscapeHTML(false) called on it.

json.Marshal 默认 escapeHtml 为 true, 会转义 <、>、&

func Marshal(v interface{}) ([]byte, error) {
    e := newEncodeState()

    err := e.marshal(v, encOpts{escapeHTML: true})
    if err != nil {
        return nil, err
    }
    buf := append([]byte(nil), e.Bytes()...)

    e.Reset()
    encodeStatePool.Put(e)

    return buf, nil
}

解决办法就是自定义一个encoder

    bf := bytes.NewBuffer([]byte{})
    jsonEncoder := json.NewEncoder(bf)
    jsonEncoder.SetEscapeHTML(false)

    err = jsonEncoder.Encode(msg)
    if err != nil {
        ...
    }

    log.Println(bf.String())
分类
golang

golang 优雅关闭定时器

if !Timer.Stop() && len(Timer.C) > 0 {
      <-Timer.C
}
Timer.Reset(time.Second)

分类
golang

golang http客户端使用http代理/socks代理

网上流传的用法大都引用了 golang.org/x/net/proxy(并且使用了已经deprecateddialer),实际上现在可以直接用这种更简单的写法。

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "net/url"
)

const (
    HttpProxy  = "http://127.0.0.1:6152"
    SocksProxy = "socks5://127.0.0.1:6153"
)

func main() {
    proxy := func(_ *http.Request) (*url.URL, error) {
        return url.Parse(HttpProxy)
    }

    httpTransport := &http.Transport{
        Proxy: proxy,
    }

    httpClient := &http.Client{
        Transport: httpTransport,
    }

    req, err := http.NewRequest("GET", "https://api.ip.sb/ip", nil)
    if err != nil {
        // handle error
    }

    resp, err := httpClient.Do(req)
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        // handle error
    }

    fmt.Println(string(body))

    proxy = func(_ *http.Request) (*url.URL, error) {
        return url.Parse(SocksProxy)
    }

    httpTransport = &http.Transport{
        Proxy: proxy,
    }

    httpClient = &http.Client{
        Transport: httpTransport,
    }

    req, err = http.NewRequest("GET", "https://api.ip.sb/ip", nil)
    if err != nil {
        // handle error
    }

    resp, err = httpClient.Do(req)
    defer resp.Body.Close()

    body, err = ioutil.ReadAll(resp.Body)
    if err != nil {
        // handle error
    }

    fmt.Println(string(body))
}

可以验证:打印的响应中确实为代理IP。

分类
windows

WSL更换清华大学(TUNA)源

我安装的是Debian for WSL
目录在 C:\Users\用户名\AppData\Local\Packages\TheDebianProject.DebianGNULinux_版本号\LocalState\rootfs\etc\apt

sources.list

# deb http://deb.debian.org/debian stretch main
# deb http://deb.debian.org/debian stretch-updates main
# deb http://security.debian.org/debian-security/ stretch/updates main
# deb http://ftp.debian.org/debian stretch-backports main

# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释
deb http://mirrors.tuna.tsinghua.edu.cn/debian/ stretch main contrib non-free
# deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ stretch main contrib non-free
deb http://mirrors.tuna.tsinghua.edu.cn/debian/ stretch-updates main contrib non-free
# deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ stretch-updates main contrib non-free
deb http://mirrors.tuna.tsinghua.edu.cn/debian/ stretch-backports main contrib non-free
# deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ stretch-backports main contrib non-free
deb http://mirrors.tuna.tsinghua.edu.cn/debian-security stretch/updates main contrib non-free
# deb-src https://mirrors.tuna.tsinghua.edu.cn/debian-security stretch/updates main contrib non-free

需要先使用http源,apt install apt-transport-https后才能切换到https源。

分类
linux

在公司和个人项目中自动切换git commiter信息

代码目录 ~/Code
公司项目目录 ~/Code/Work

.gitconfig

[includeIf "gitdir:~/Code/"]
  path = .gitconfig-personal
[includeIf "gitdir:~/Code/Work/"]
  path = .gitconfig-work

.gitconfig-personal

[user]
name = solarhell
email = songjiaxin2008@gmail.com

.gitconfig-work

[user]
name = 程序员
email = 程序员@公司.com
分类
golang

golang 解析可变类型 json 字段

在接入一些php后台时,可能会遇到返回的json字段类型变化的情况(即字段类型不规范的情况)。
这时候可以选择简单的用interface去解析。
当然,还可以使用json.RawMessage来更好的匹配情况。

{
  "code": 0,
  "data": "xxx",
  "error": []
}
{
  "code": -3031,
  "data": "xxx",
  "error": {
    "code": -3031,
    "msg": "密码错误"
  }
}

这里error字段其实是可以根据外部code是否为0来判断类型的。

还有一种办法是对error这个struct定义一个unmarshal方法。

type Error interface{}
func (e Error) Unmarshal() {
}