升级 ubuntu 18.04 的内核

机器比较古老,不好折腾太大重装,就升级一下内核吧。

  • 查内核版本

    image-20211027153625168

     apt list | grep linux-generic*
    
  • 升级

    apt-get install linux-generic-hwe-18.04-edge
    
  • 重启

    reboot
    
  • 确认已升级

    image-20211027155519501


confd 模板语法

本文是 confd 在 github 上的文档的翻译和此文的摘抄,该文档详细介绍了confd模板的语法和结构。另外,最后我列出一些我个人常用的表达式,方便未来复用。

一、模板源

模板源以TOML编写并已 .toml 作为后缀的来定义的。默认情况下,模板源存储在/etc/confd/conf.d 目录下。模板源使用Go的库: text/template.。

必要参数

  • dest (字符串) - 目标文件。
  • keys (字符串数组) - 键数组。
  • src (字符串) - 配置模板的相对路径 。

可选参数

  • gid (int) - 应该拥有该文件的gid。默认为有效的gid。
  • mode (字符串) - 文件的权限模式。
  • uid (int) - 应该拥有该文件的uid。默认为有效的uid。
  • reload_cmd (字符串) - 重新加载配置的命令。
  • check_cmd (字符串)- 检查配置的命令。
  • prefix (字符串) - 键前缀的字符串。

[template]
src = "nginx.conf.tmpl"
dest = "/etc/nginx/nginx.conf"
uid = 0
gid = 0
mode = "0644"
keys = [
  "/nginx",
]
check_cmd = "/usr/sbin/nginx -t -c {{.src}}"
reload_cmd = "/usr/sbin/service nginx restart"

二、模板函数

map

创建接口和字符串的键值映射

{{$endpoint := map "name" "elasticsearch" "private_port" 9200 "public_port" 443}}

name: {{index $endpoint "name"}}
private-port: {{index $endpoint "private_port"}}
public-port: {{index $endpoint "public_port"}}

如果您是子模板并且想要向其传递多个值,则特别有用。

base

path.Base函数的别名 。

{{with get "/key"}}
    key: {{base .Key}}
    value: {{.Value}}
{{end}}

exists

判断键是否存在。如果找不到键,则返回false。

{{if exists "/key"}}
    value: {{getv "/key"}}
{{end}}

get

返回键与其键匹配的键值对。如果未找到键,则返回错误。

{{with get "/key"}}
    key: {{.Key}}
    value: {{.Value}}
{{end}}

gets

返回与其key匹配所有键值对,如果未找到键,则返回错误。

{{range gets "/*"}}
    key: {{.Key}}
    value: {{.Value}}
{{end}}

getv

返回与其键或可选的默认值匹配的字符串,如果未找到键且未给出默认值,则返回错误。

value: {{getv "/key"}}

getv默认值

value: {{getv "/key" "default_value"}}

getvs

返回与其键匹配所有值的字符串,如果未找到密钥,则返回错误。

{{range getvs "/*"}}
    value: {{.}}
{{end}}

getenv

返回在os.Getenv 中检索由键命名的环境变量的值。如果变量不存在,该值将为空。(可选)您可以提供一个默认值,如果该键不存在,将返回该值。

export HOSTNAME=`hostname`
hostname: {{getenv "HOSTNAME"}}

getenv默认值

ipaddr: {{getenv "HOST_IP" "127.0.0.1"}}

datetime

time.Now的别名

Generated by confd {{datetime}}
输出:
Generated by confd 2015-01-23 13:34:56.093250283 -0800 PST
Generated by confd {{datetime.Format "Jan 2, 2006 at 3:04pm (MST)"}}
输出:
Generated by confd Jan 23, 2015 at 1:34pm (EST)

更多用法,请参阅官方时间用法

split

包装器 strings.Split。分隔输入的字符串并返回一个子字符串切片。

{{ $url := split (getv "/deis/service") ":" }}
    host: {{index $url 0}}
    port: {{index $url 1}}

toUpper

strings.ToUpper的 别名 返回大写字符串。

key: {{toUpper "value"}}

toLower

strings.ToLower的 别名 。返回小写字符串。

key: {{toLower "Value"}}

json

返回map[string]interface{}形式的json值。

lookupSRV

net.LookupSRV 包装器 。通过组合net.SRV结构的所有字段按字母顺序对SRV记录进行排序,以减少不必要的配置重新加载。

{{range lookupSRV "mail" "tcp" "example.com"}}
  target: {{.Target}}
  port: {{.Port}}
  priority: {{.Priority}}
  weight: {{.Weight}}
{{end}}

etcd添加键值

etcdctl set /services/zookeeper/host1 '{"Id":"host1", "IP":"192.168.10.11"}'
etcdctl set /services/zookeeper/host2 '{"Id":"host2", "IP":"192.168.10.12"}'

创建模板源

[template]
src = "services.conf.tmpl"
dest = "/tmp/services.conf"
keys = [
  "/services/zookeeper/"
]

创建模板

{{range gets "/services/zookeeper/*"}}
{{$data := json .Value}}
  id: {{$data.Id}}
  ip: {{$data.IP}}
{{end}}

map遍历

一旦解析了JSON,就可以使用普通的Go模板函数遍历它 index

更高级的结构,如下所示:

{
  "animals": [
    {"type": "dog", "name": "Fido"},
    {"type": "cat", "name": "Misse"}
  ]
}

它可以像这样遍历:

{{$data := json (getv "/test/data/")}}
type: {{ (index $data.animals 1).type }}
name: {{ (index $data.animals 1).name }}
{{range $data.animals}}
{{.name}}
{{end}}

jsonArray

从接口返回json数组,例如: [“a”, “b”, “c”]`。

{{range jsonArray (getv "/services/data/")}}
	val: {{.}}
{{end}}

ls

返回匹配路径的所有子键,字符串等。如果找不到路径,则返回空列表。

{{range ls "/deis/services"}}
   value: {{.}}
{{end}}

lsdir

返回匹配路径的所有子键,字符串等。注意它只返回也有子键的子键。如果找不到路径,则返回空列表。

{{range lsdir "/deis/services"}}
   value: {{.}}
{{end}}

dir

返回制定键的父目录。

{{with dir "/services/data/url"}}
	dir: {{.}}
{{end}}

join

strings.Join 函数的别名 。

{{$services := getvs "/services/elasticsearch/*"}}
services: {{join $services ","}}

replace

strings.place 函数的别名 。

{{$backend := getv "/services/backend/nginx"}}
backend = {{replace $backend "-" "_" -1}}

lookupIP

net.LookupIP 函数的包装器 。包装器还按字母顺序排序IP地址。这一点至关重要,因为在动态环境中,DNS服务器通常会混淆链接到域名的地址。这将导致不必要的配置重新加载。

{{range lookupIP "some.host.local"}}
    server {{.}};
{{end}}

atoi

strconv.Atoi 函数的别名 。

{{seq 1 (atoi (getv "/count"))}}

三、我的例子

  1. 需要end包裹的关键字

    • range
    • with
  2. 获取环境变量

    {{$hostname := getenv "KELU_HOSTNAME"}}
    hostname="{{$hostname}}"
    
  3. 取值with

    {{with get (printf "/confd/%s/config" $hostname)}}
    {{ with get $node }}
    
  4. 循环range

    {{range $key, $dir := lsdir "/confd"}}
    	{{ $node := printf "/confd/%s/config" $dir }} # 字符串拼接+赋值
       
    	{{ with get $node }}
    		{{ $data := json .Value }}
    	{{end}}
    {{end}}
    
  5. 对比 eq/ne

    {{if $data.isTrue }}
    {{if ne $data.name "kelu"}}
    
    eq
    	Returns the boolean truth of arg1 == arg2
    ne
    	Returns the boolean truth of arg1 != arg2
    lt
    	Returns the boolean truth of arg1 < arg2
    le
    	Returns the boolean truth of arg1 <= arg2
    gt
    	Returns the boolean truth of arg1 > arg2
    ge
    	Returns the boolean truth of arg1 >= arg2
    
  6. 字符串拼接printf

    {{ $config := (printf "/haproxy/%s/config" $haproxy)}}
    
  7. 解析 json

    {{ with get $node }}{{ $data := json .Value }}
    
  8. 数组长度len

    {{$dir := lsdir "/confd"}}
    {{$count := len $dir}}
    
    and
    	Returns the boolean AND of its arguments by returning the
    	first empty argument or the last argument, that is,
    	"and x y" behaves as "if x then y else x". All the
    	arguments are evaluated.
    call
    	Returns the result of calling the first argument, which
    	must be a function, with the remaining arguments as parameters.
    	Thus "call .X.Y 1 2" is, in Go notation, dot.X.Y(1, 2) where
    	Y is a func-valued field, map entry, or the like.
    	The first argument must be the result of an evaluation
    	that yields a value of function type (as distinct from
    	a predefined function such as print). The function must
    	return either one or two result values, the second of which
    	is of type error. If the arguments don't match the function
    	or the returned error value is non-nil, execution stops.
    html
    	Returns the escaped HTML equivalent of the textual
    	representation of its arguments. This function is unavailable
    	in html/template, with a few exceptions.
    index
    	Returns the result of indexing its first argument by the
    	following arguments. Thus "index x 1 2 3" is, in Go syntax,
    	x[1][2][3]. Each indexed item must be a map, slice, or array.
    slice
    	slice returns the result of slicing its first argument by the
    	remaining arguments. Thus "slice x 1 2" is, in Go syntax, x[1:2],
    	while "slice x" is x[:], "slice x 1" is x[1:], and "slice x 1 2 3"
    	is x[1:2:3]. The first argument must be a string, slice, or array.
    js
    	Returns the escaped JavaScript equivalent of the textual
    	representation of its arguments.
    len
    	Returns the integer length of its argument.
    not
    	Returns the boolean negation of its single argument.
    or
    	Returns the boolean OR of its arguments by returning the
    	first non-empty argument or the last argument, that is,
    	"or x y" behaves as "if x then x else y". All the
    	arguments are evaluated.
    print
    	An alias for fmt.Sprint
    printf
    	An alias for fmt.Sprintf
    println
    	An alias for fmt.Sprintln
    urlquery
    	Returns the escaped value of the textual representation of
    	its arguments in a form suitable for embedding in a URL query.
    	This function is unavailable in html/template, with a few
    	exceptions.
    
  9. 获取字符串最后一个单词base

    {{base $dir}}
    
  10. 反释义

原文:

image-20211020164157259

在模板中要在外部包裹{{}}再加双引号:

image-20211020164303072

  1. 数组解析jsonArray

    etcd中的数据为:/confd/local/ip/static ["1.2.3.4","5.6.7.8"]

    {{range jsonArray (getv "/confd/local/ip/static")}}allow {{.}};{{end}}
    
  2. 字符串拆分为数组 spilt

    etcd中的数据为:/a/b/c/d {"target":"a,b,c,d"}

    {{ $backend := split $data.target "," }}
    {{ range $backend }}
    ...
    {{ end }}
    

参考资料


在 macOS 上配置 SSH 隧道并创建 SOCKS 代理

创建 SOCKS 代理是一种便捷的方式,可以将所有流量通过 SSH 隧道转发。以下是我在 macOS 上配置 SOCKS 代理的步骤。

创建 SOCKS 代理

  1. 打开终端: 首先,打开终端应用。

  2. 运行 SSH 命令: 输入以下命令,创建一个 SOCKS 代理:

    ssh -D 1080 user@1.2.3.4
    

    user 替换为用户名。这条命令会在本地的 1080 端口创建一个 SOCKS 代理。

配置应用程序使用 SOCKS 代理

接下来,我需要配置支持 SOCKS 代理的应用程序(如浏览器):

  1. 打开系统偏好设置: 点击苹果菜单,选择 系统偏好设置

  2. 选择网络: 在网络设置中,选择当前使用的网络连接(例如 Wi-Fi),然后点击 高级

  3. 配置代理: 在 代理 选项卡中,勾选 SOCKS 代理,并在代理服务器框中输入 127.0.0.1 和端口 1080

  4. 保存设置: 点击 ,然后 应用 保存更改。

持续运行 SSH 隧道

如果希望 SSH 隧道在后台持续运行,可以使用以下命令:

ssh -D 1080 -N user@1.2.3.4

在这个命令中,-N 参数表示不执行任何远程命令,只保持连接,这样可以让 SOCKS 代理在后台持续运行。这样,我就可以在需要时安全地转发流量。

高阶玩法

如果不想在 macOS 的系统网络代理设置中使用 SOCKS 代理,以下是几种更灵活的方式,暂时只做记录。这里假设我们想仅代理Citrix viewer这个软件。

方法 1: 使用 proxychains 工具

proxychains 是一个工具,可以强制指定的应用程序通过代理(如 SOCKS5)进行网络连接。

步骤:

  1. 安装 proxychains-ng
    • 在 macOS 上安装 `proxychains-ng:
      brew install proxychains-ng
      
  2. 配置 proxychains-ng:
    • 编辑 proxychains 的配置文件,通常在 /usr/local/etc/proxychains.conf
    • 在文件末尾,添加你的 SSH 隧道的 SOCKS 代理地址,例如:
      socks5  127.0.0.1 1080
      
  3. 使用 proxychains 启动 Citrix Viewer:
    • 在 SSH 隧道开启的情况下,使用 proxychains 来启动 Citrix Viewer,让它通过隧道访问网络:
      proxychains4 /Applications/Citrix\ Workspace.app/Contents/MacOS/Citrix\ Viewer
      
    • 这样,Citrix Viewer 的所有流量都会通过 SSH SOCKS 代理,而不影响 macOS 的全局代理设置。

方法 2: 使用 sshuttle 来转发流量

sshuttle 是一种简单的 VPN 解决方案,可以将指定的流量通过 SSH 隧道路由。不同于系统级 VPN,它允许我们控制流量的范围和转发规则。

步骤:

  1. 安装 sshuttle:
    • 在 macOS 上,使用 Homebrew 安装 sshuttle
      brew install sshuttle
      
  2. 启动 sshuttle:
    • 使用 sshuttle 来启动隧道,并将指定的流量通过 SSH 隧道。

      如果希望 sshuttle 在后台运行,可以添加 -D 参数

      sshuttle -r user@1.2.3.4 10.0.0.0/8
      sshuttle -r user@1.2.3.4 1.2.3.5/32 9.0.0.0/8 10.0.0.0/8 -D
      
  3. 验证代理是否生效

    要验证代理是否生效,你可以通过 ping 或 curl 测试是否成功通过代理。例如:

    ping 1.2.3.4
    

方法 3: 使用 Proxifier

Proxifier 是 macOS 上的一款 GUI 工具,允许为特定的应用程序(如 Citrix Viewer)单独设置代理,而不影响系统的其他应用程序。不过要注意的是这是一个付费软件。


ssh rsync 登陆时跳过host检查

SSH 公钥检查是一个重要的安全机制,可以防范中间人劫持等黑客攻击。不过我在做rsync的自动化任务时就遇到问题了:因为我的rsync的server和client都是容器启动的,host变化是很正常的事。所以必须要绕过这样的提醒错误:

The authenticity of host '192.168.0.110 (192.168.0.110)' can't be established.
RSA key fingerprint is a3:ca:ad:95:a1:45:d2:57:3a:e9:e7:75:a8:4c:1f:9f.
Are you sure you want to continue connecting (yes/no)?

或者

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that the RSA host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
e9:0c:36:89:7f:3c:07:71:09:5a:9f:28:8c:44:e9:05.
Please contact your system administrator.
Add correct host key in /home/jiangxin/.ssh/known_hosts to get rid of this message.
Offending key in /home/jiangxin/.ssh/known_hosts:81
RSA host key for 192.168.0.110 has changed and you have requested strict checking.
Host key verification failed.

在ssh配置文件中配置如下即可:

vi ~/.ssh/config 

Host 192.168.1.10
   StrictHostKeyChecking no
   UserKnownHostsFile=/dev/null

或者批量设置:

vi ~/.ssh/config 

Host 192.168.0.*
   StrictHostKeyChecking no
   UserKnownHostsFile=/dev/null

参考资料


专利相关备忘

专利和文献是我日常工作的一部分,这篇文章记录一些网站,不定期更新。

中文专利

  1. 国家专利局: http://pss-system.cnipa.gov.cn/

  2. 知嘟嘟 IPRDB,这家的平台检索很快,而且免费注册没有年费限制,检索分析都是免费的挺好用的。

  3. Patenthub http://www.patenthub.cn,有年费门槛限制,不过只是用来检索的话还是挺快的

  4. SooPAT http://www.soopat.com,好处就是 连注册都不用,直接就能用。

  5. CINPR

  6. 知网

  7. patentcloud

    image-20211008161218319

  8. 商标检索数据库,摩知轮

  9. 无效专利检索: 国知局 http://reexam.cnipa.gov.cn/

  10. 专利诉讼检索:

    • https://www.itslaw.com/
    • http://openlaw.cn/
    • https://www.faxin.cn/
  11. 企业信息检索

    • 企查查
    • 天眼查

国际专利

  1. google patents ,免费中的最强!

  2. 日本 J-PlatPat

    • 简单检索

    • OPD(One Portal Dossier)是日本全球专利案卷检索系统,,可以查9个国家/地区。

      image-20211008150236896

      image-20211008150206922

      可以下载pdf。

    • 特許・実用新案検索

    • 分类号检索PMGS

      image-20211008153042325

  3. 美 Global Dossier

  4. 欧 espacenet,可以做逻辑OR/AND/NOT搜索

    点击列表,右边显示内容。另外可以下载搜索结果列表。

    image-20211008153548498

  5. 法国 Orbin

  6. DII(Derwent Innovations Index),

  7. LENS,免费开放的专利+学术检索数据库。

    image-20211008155603643

    image-20211008155640638

  8. 语义检索octimine

  9. 欧盟外观设计专利检索 eSearch plus

  10. 日本外观检索数据库 Graphic Image Park

  11. 台湾 新颖数位iptech

文献检索

  • Sci-Hub
  • LibGen
  • Soscholar 天玑学术网中科院计算机研究所开发,涵盖 ACM、IEEE、DBLP、CITESEER,以及众多国外学者的个人博客,目前数据库内的论文储量接近 1000 万。
  • Citeseerx 免费论文搜索网以Postscrip和PDF文件格式存在的学术论文,全文达138万多篇,引文2674万多条,内容主要涉及计算机和信息科学领域,主题包括智能代理、人工智能、硬件、软件工程、操作系统等。
  • OCLC 学术论文搜索引擎计算机图书馆服务的会员制
  • Arnetminer 研究者学术搜索网该网站涵盖了100多万名研究者、300万篇论文信息、3700多万引用关系以及8000多个会议信息。
  • FindaRticles 文献论文搜索引擎涵盖艺术与娱乐、汽车、商业与经融、计算机与技术、健康与健身、新闻与社会、科学教育、体育等各个方面顶极刊物的上千万篇论文。其中大部分为免费全文资料,检索操作简单。它所拥有的文献总量达1100万篇,资料来源于杂志、定期刊物和报纸等。
  • MinimanuScript 学术文献维基百科平台维基类学术文献百科。 在MiniManuscript上你能看到其他读者在读完某篇文献后整理出来的框架:这篇论文究竟用什么方法研究了什么问题,有了怎样的发现等。
  • SemanticScholar 免费学术搜索引擎检索结果来自于期刊、学术会议资料或者是学术机构的文献。这个搜索引擎能检索到 80% 的免费论文文献,大约有 300 万份,另外它直接提供图表预览,看起来能方便研究人员省下更多筛选的工作。
  • Base Search 德国比勒菲尔德学术搜索引擎Base是有德国著名的比勒费尔德大学图书馆开发的一个多学科的学术搜索引擎。它提供对全球异构学术资源的集成检索服务。Base整合的文献大约有160个开放资源即超过200万个文档数据信息。

论文会议

  • ACM SIGKDD (Knowledge Discovery and Data Mining,简称 KDD)是数据挖掘领域的国际顶级会议。KDD Cup比赛是由SIGKDD主办的数据挖掘研究领域的国际顶级赛事,从1997年开始,每年举办一次,是目前数据挖掘领域最有影响力的赛事。

参考资料