glab 是一款使用 Go 语言实现的和 GitLab 实例交互的命令行工具。
之前是在 GitHub 上开发,但在 2022 年 11 月 22 之后,被 GitLab 官方采用,变成了官方支持的 cli 工具。
macOS & Linux 使用 Homebrew:
brew install glab
配置文件的地址在本地 ~/.config/glab-cli/
。
❯ cat .config/glab-cli/config.yml
# What protocol to use when performing git operations. Supported values: ssh, https
git_protocol: https
# What editor glab should run when creating issues, merge requests, etc. This is a global config that cannot be overridden by hostname.
editor:
# What browser glab should run when opening links. This is a global config that cannot be overridden by hostname.
browser:
# Set your desired markdown renderer style. Available options are [dark, light, notty] or set a custom style. Refer to https://github.com/charmbracelet/glamour#styles
glamour_style: dark
# Allow glab to automatically check for updates and notify you when there are new updates
check_update: false
# Whether or not to display hyperlink escapes when listing things like issues or MRs
display_hyperlinks: false
# configuration specific for gitlab instances
hosts:
gitlab.com:
# What protocol to use to access the api endpoint. Supported values: http, https
api_protocol: https
# Configure host for api endpoint, defaults to the host itself
api_host: gitlab.com
# Your GitLab access token. Get an access token at https://gitlab.com/-/profile/personal_access_tokens
token:
# Default GitLab hostname to use
gitlab_host:
token: glpxxx
apt_host: gitlab_host
git_protocol: https
api_protocol: https
user: gitlab_username
host: gitlab.com
附加填充里面的 token
等信息即可。
GITLAB_URL=
# or GITLAB_HOST=
GITLAB_TOKEN=
glab completion -s zsh > /path/to/zsh/completion
可以通过 echo $FPATH
来查看本机 Zsh 的 completion 文件路径。
创建 Merge Request:
glab mr create -a username -t "fix something"
glab mr create --autofill --labels bugfix
glab mr create --squash-before-merge --remove-source-branch -a username -t "feat: message"
合并
glab mr merge 123
glab mr note -m "needs to do before it can be merged" branch-foo
同意:
glab mr approve {id | branch} [flags]
glab mr approve 234
glab mr approve 234 456
glab mr approve branch-1
glab mr approve branch-1 branch-2
[[2019-06-20-gitlab-cli-merge-request]]
一直使用 Netdata 来作为 VPS 的监控,配合 Netdata Cloud 来作为监控面板体验一直都不错。不过最近有一台机器经常发送邮件告警:
outbound_packets_dropped_ratio
看这个告警一头雾水,虽然每个词都懂,但就是不知道表示的什么含义。所以搜罗各种资料学习一下。
详细的解释 Netdata 也给了出来:
Details: ratio of outbound dropped packets for the network interface venet0 over the last 10 minutes
过去 10 分钟内网卡 venet0 出站的流量丢包率。
那具体什么是 dropped packets 呢?在 Linux 下有很多原因会出现丢包,有可能是网络不稳提,或者网络拥堵,或者应用无法处理负载。
❯ sudo netstat -i
Kernel Interface table
Iface MTU RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
br-c834d 1500 7024713 0 0 0 5439423 0 0 0 BMU
br-f28aa 1500 446015 0 0 0 7656772 0 0 0 BMRU
br-f50ea 1500 5779300 0 0 0 6093954 0 0 0 BMRU
docker0 1500 0 0 0 0 0 0 0 0 BMU
lo 65536 38808638 0 0 0 38808638 0 0 0 LRU
venet0 1500 78213871 0 0 0 114697804 0 25737 0 BOPRU
venet0:0 1500 - no statistics available - BOPRU
vethd37c 1500 151555 0 0 0 209478 0 0 0 BMRU
vethe8b7 1500 8254 0 0 0 134561 0 0 0 BMRU
可以看到图中 venet0
这块网卡在 TX-DRP
上确实是有一定的丢包。
显示网卡的统计信息:
netstat -s
# 显示 tcp
netstat -s -t
# 显示 udp
netstat -s -u
netstat -s
的结果
Ip:
Forwarding: 1 //开启转发
31 total packets received //总收包数
0 forwarded //转发包数
0 incoming packets discarded //接收丢包数
25 incoming packets delivered //接收的数据包数
15 requests sent out //发出的数据包数
Icmp:
0 ICMP messages received //收到的ICMP包数
0 input ICMP message failed //收到ICMP失败数
ICMP input histogram:
0 ICMP messages sent //ICMP发送数
0 ICMP messages failed //ICMP失败数
ICMP output histogram:
Tcp:
0 active connection openings //主动连接数
0 passive connection openings //被动连接数
11 failed connection attempts //失败连接尝试数
0 connection resets received //接收的连接重置数
0 connections established //建立连接数
25 segments received //已接收报文数
21 segments sent out //已发送报文数
4 segments retransmitted //重传报文数
0 bad segments received //错误报文数
0 resets sent //发出的连接重置数
Udp:
0 packets received
...
TcpExt:
11 resets received for embryonic SYN_RECV sockets //半连接重置数
0 packet headers predicted
TCPTimeouts: 7 //超时数
TCPSynRetrans: 4 //SYN重传数
或者可以使用 ip
命令:
❯ ip -s link show venet0
2: venet0: <BROADCAST,POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN mode DEFAULT group default
link/void
RX: bytes packets errors dropped overrun mcast
30619319736 78217051 0 0 0 0
TX: bytes packets errors dropped carrier collsns
32292008558 114701118 0 25738 0 0
为了找出 Linux 服务器为什么 drop packets 可以借助 dropwatch。这个工具可以用来诊断 Linux networking stack 的问题,主要是查看协议栈丢包问题。
安装必要的工具:
sudo apt-get install libpcap-dev libnl-3-dev libnl-genl-3-dev binutils-dev libreadline6-dev autoconf libtool pkg-config build-essential
安装完之后执行 libtoolize
,这会拷贝,连接必要的脚本,包括 ltmain.sh
。
然后手动编译:
git clone https://github.com/nhorman/dropwatch
cd dropwatch
./autogen.sh
./configure
make
make install
因为我是用 docker 安装,所以需要进入 netdata 容器:
docker exec -it netdata /bin/sh
然后执行:
/etc/netdata/edit-config health.d/net.conf
其中的第 107 行即可。
CodeWars 是一个面向工程的代码挑战网站。不同于 [[LeetCode]] 侧重于考察算法,CodeWars 更注重与工程代码,提供了基础的单元测试,以及不同语言的实现。
相较于 LeetCode CodeWars 上面的问题相对比较直接,有些甚至可以用来学习一些编程语言的特性。和 LeetCode 一样带有讨论版,可以通过讨论版来学习。
CodeWars 中也包含一些基础的算法,随着 Rank 越来越高也会有比较难的题目。
在注册进入 CodeWars 之后,会让用户选择不同的模式。
基础,升级,练习,Beta,随机。可以根据自己的需求选择。
如果看完上面的介绍你觉得 CodeWars 不错的话,可以点击 这里 来注册。如果你觉得又可以分享的解题思路,也可以点个 关注 一起来讨论。
eu.org 是欧盟组织下面的域名,EU 代表欧盟,Paul Mockapetris 在 1996 年的 9-10 月份创建了这个域名的 DNS 服务器。现在对个人和组织是免费注册的。
“EU.org, free domain names since 1996”。
eu.org 是 Google 认可的顶级域名。
优点:
缺点:
eu.org 在国内使用 http 会被被强行重置,配合 HTTPS 才可正常访问。
申请页面 https://nic.eu.org/arf/ 注册账号,验证邮箱。
点击 New Domain 申请域名。
在申请域名的时候需要提前填写 DNS 信息,但是 Cloudflare 不能提前添加未注册的域名,所以不能用 Cloudflare。
这里可以使用:
Hurricane Electric Hosted DNS(HE) NS Records:
DNSPOD 的 NS Record 一般都是 XXX.dnspod.com
之后 EU.org 会开始验证 NS 记录。如果没有问题最后的日志会是 done
。
---- Servers and domain names check
Getting IP for PHIL.NS.CLOUDFLARE.COM: 108.162.193.137 172.64.33.137 173.245.59.137
Getting IP for PHIL.NS.CLOUDFLARE.COM: 2803:f800:50::6ca2:c189 2606:4700:58::adf5:3b89 2a06:98c1:50::ac40:2189
Getting IP for VERA.NS.CLOUDFLARE.COM: 172.64.32.147 108.162.192.147 173.245.58.147
Getting IP for VERA.NS.CLOUDFLARE.COM: 2803:f800:50::6ca2:c093 2a06:98c1:50::ac40:2093 2606:4700:50::adf5:3a93
No error, storing for validation...
Saved as request 202303xxxxxxxx-arf-3xxxx
Done
这个过程的时间不确定,可能会是 1 天,也可能好几个星期,最后注册邮箱中会收到 EU.org 发过来的邮件,标题一般是 request [20210906172103-arf-xxxx] (domain test.EU.ORG) accepted
,这表示域名注册成功了。
Eu.org 在验证 NS 的过程中可能会出现如下错误:
SOA from NS1.HE.NET at 216.218.130.2: Error: Answer not authoritative (148.835 ms)
这个时候注意在前面选项 Name Servers 中选择 server names 单选项。
当 eu.org 域名申请完毕,可以将域名添加到 Cloudflare 管理。
首先需要在 eu.org 管理后台中修改域名的 nameservers 修改成 Cloudflare 的 NS 地址。
通常是:
这两个地址可以在 Cloudflare 后台添加域名之后获得。
在 Cloudflare 添加新申请的域名,如果添加的时候提示:
eu.org is not a registered domain
或者提示这个域名没有注册,就等待一下 EU.org 刷新 WHOIS,然后等待一会儿再尝试添加。
在看上一本 [[金融的本质]] 时突然对利率的变动比较好奇,所以就发现这一本《利率史》,一本关于利率变化历史的书籍。
在 [[金融的本质]] 一书中可以看到美联储可以通过影响隔夜拆借利率进而来影响整体市场的利率,从而通过利率来调控宏观经济。为什么利率对整个经济有如此巨大的影响?美联储加息成为了 2022 年全球经济的关键字。而国内房地产市场萧条,央行为什么通过调整房贷利率进而进一步影响房地产市场?这些问题都是我想通过这一本书想要了解的。
本书的作者是[[悉尼 霍默]],债券经纪人,职业早期创办了自己的债券公司,开了固定收益分析的先河。霍默率先应用了相对价值分析、收益曲线以及金融世界与经济的关系等分析工具。他是使用金融市场资金流动分析的第一人,远远早于美联储正式采用这种分析手段。1961 年来到所罗门兄弟公司,后组建并管理第一个严格局限于固定收益的研究部门。霍默首次提出将债券和其利息剥离,分别销售。
作者于 1983 年去世,本书的第四版由理查德·西勒修订,在第三版的基础上新增了 1990 年到 2005 年的世界。
就如书名所述,这是一本关于利率历史的书。作者通过对古代(史前史,美索不达米亚,希腊,罗马),中世纪,文艺复兴,以及近现代近 4000 年的经济史来叙述全世界各个地区的利率变化,进而去观察地区经济,以及民族兴盛和衰亡的历史。
公元前 1800 年,汉漠拉比法典就已经出现了对债务人和债权人相关的法律。 公元 600 年,希腊的索伦法典也对个人债务做出了规定,取消了利率的限制,豁免了过度的债务,以及取消个人劳役偿债。
公元前 450 年,罗马的《十二铜表法》也对信贷有所规定,贷款的利息被限制在每年不超过 8.333%,高于法定上限的利息将被处以 4 倍的赔偿。允许个人劳役偿债,但是得保证奴隶的健康。
公元 800 年《查理曼法典》,禁止一切贷款。
宗教改革之后,现代欧洲对收取利息合法化,利率成为了经济学家、金融家和政治家讨论的焦点,是放任自由还是国家控制。最终英国走了索伦的路子,废除了对利率的所有法律限制,而美国各州则在自己的高利贷法中确定了固定的利率上限,继承了汉谟拉比和古罗马的法律传统。
最高利率,伯林的 10000% ,最低纽约的 0.01% 。
20 世纪前 90 年,多事之秋,四大政治事件
三大经济事件:
这些事件对美国经济和利率产生了巨大影响。
利率是各国政府最直接影响的价格之一,历史的最终裁决会将近几十年利率幅震荡的一部分原因与政治因素联系在一起。
1917 年开始美联储采用欧洲已经使用很久的方式来影响利率,从而根本上改变了美国货币市场结构。通过集中银行储备金、设立最后贷款人机制,该立法终结了短期利率的无规律上涨(过去,只要出现急需贷款额超过资金供应量,就会出现短期暴涨)。短期利率仍然随着信贷供求关系的变化而起伏,但是有了封顶保底。建立美联储主要是希望通过短期商业借贷来提供一种灵活货币以服务于贸易。然而第一次世界大战不久就爆发,巨额的政府新债改变了货币市场,提升了美联储的政治责任。在接下来的几十年中,政府债务取代了银行和美联储银行投资组合中的商业票据的地位。新政、大萧条和第二次世界大战强化了这种趋势。并且利用低利率来促进就业,已经成为了一种政治目标。1921 年以前,美国的利率通常平均远远高于长期债券收益率,而在 1921 年之后,短期利率通常平均低于长期债券的收益率。
通胀在 1974 年达到两位数,OPEC 组织在 1973 年末实施石油价格急剧上涨措施,通胀蔓延到自由世界大部分地区。1974,1975 年的衰退降低里通胀率,但是 1979~1981 年通胀再次席卷而来,再次回到两位数,1979 年又一次石油价格飙升,物价飞涨,1980 年代的衰退对通胀几乎没有影响。利率上升到了美国历史上的最高水平,导致了 1981,1982 年的严重衰退,之后,通胀率在 80 年代后几年减弱到 3~5%。利率和收益率也随之下滑。
从 1946 年到 1981 年,美国经历了历史上最长的一个债券熊市,持续 35 年。
四件政治大事(一战、罗斯福新政、二战以及 1989 年前的冷战)和三大经济事件(建立美联储、经济大萧条以及 1965 年开始的大幅通胀)对于美国经济及美国利率产生了尤其重大的影响
1970 年以后的 20 年里,日本发展成为世界金融大国,从 20 世纪 50 年代开始到 70 年代,政府确定了几个重点发展对象,包括炼油、化工、工业机械和电子电器。高速发展阶段,日本采用豁免利息税的储蓄账户来鼓励个人大量存款。然而,日本的金融市场远不如西欧和北美发达,利率相对比较高;金融业比较分散,而不是集中的形式,利率受到管制,与其他国家的金融交易也受到控制。
70 年代中期,日本发生金融改革,浮动汇率,1973 年第一次石油危机,造成了管制型旧金融系统的紧张,经济已经发展到了规模巨大、在国际上非常重要的成都,无法在严格管制、封闭的金融系统下继续。日本在 1975 年放松了金融系统的大部分管制。日本货币市场和债券市场得以发展,伴随日本股市的发展,越来越向国外开放。尤其是 1975 年政府通过发行债券进行了大规模的融资以弥补财政赤字。
90 年代开始,日本的金融自由完善了许多,日本已经不再是一个高利率的国家。而事实上 80 年代,日本就成为了利率最低的国家之一。
在谈论所有其他的概念之前,我们先来回答一个问题,什么是利率?
利率的英文叫做 interest rate, 是利息率的简称。在 Longman 词典中的解释是:
the percentage amount charged by a bank etc when you borrow money, or paid to you by a bank when you keep money in an account there
新闻中常常提到美联储加息或降息,很多人都会误认为美联储可以直接决定利率,而事实是美联储只能通过控制货币供给量来决定短期利率。但是影响经济最重要的是实际利率或者称为通胀调整利率(市场利率减去通胀率)。实际利率才是对资本决策最有实质性影响的。美联储影响长期实际利率的能力是间接的。实际利率受到经济因素影响,包括经济前景这些是不受美联储控制的。
作者试图通过漫漫历史长河的利率变化来给读者展示国家和文明的兴衰,作者认为在一个自由市场条件下,长期利率的趋势可以帮助分析这个国家的经济和政治状况。
几乎在所有的教科书或百科上面都会提到,几乎所有的国家都会将利率作为调节宏观经济的重要工具,当经济过热,通胀上升的时候就提高利率,收紧信贷。当通胀得到控制,便把利率适当的调低。
就如作者所说,本书的目的并不是为了探讨利率波动对于社会和经济方面带来的后果,而只是要搜寻、记录并分析多个国家数世纪中通行利率。
在我个人看来本书的一大优点同样也是其最大的缺点,就是数据太翔实,大面积的原始数据,以至于欠缺了作者更深入的思考和总结。并且这些数据大大影响了阅读体验,不过如果是作为一本参考书来说,倒是非常不错的资料。
Elasticsearch 既然作为一个全文检索引擎,那么自然需要将数据导入,让 Elasticsearch 去索引。
Elasticsearch(后简写为 ES) 的基本单元是文档,使用 JSON 来描述。
有很多方法可以把数据导入到 ES:
导入数据前要了解的知识。
如果数据文件比较简单,只有单层 JSON 结构,并且小于 1MB,可以使用 POST 请求直接将数据提交到 ES。
假设有数据 accounts.json
:
{"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"amberduke@pyrami.com","city":"Brogan","state":"IL"}
然后可以使用如下命令导入:
curl -u admin:my_elastic_pass -H 'Content-Type: application/json' -XPOST 'http://localhost:9200/accounts/_doc/_bulk?pretty' --data-binary @accounts.json
返回:
{
"_index" : "accounts",
"_id" : "_bulk",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
可以通过如下命令来查看所有索引的情况:
curl "localhost:9200/_cat/indices?v"
然后访问 Kibana,在后台就可以查询导入的内容:
这里使用官方的样例数据:
wget https://download.elastic.co/demos/kibana/gettingstarted/accounts.zip
unzip accounts.zip
curl -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary @accounts.json
需要注意的是如果使用 Bulk 批量导入,那么格式需要按照:
action_and_meta_data\n
optional_source\n
action_and_meta_data\n
optional_source\n
....
action_and_meta_data\n
optional_source\n
或者可以在 Kibana 后台,点击侧边栏 Dev Tools,然后在编辑框中输入:
POST bank/_bulk
{"index":{"_id":"1"}}
{"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"amberduke@pyrami.com","city":"Brogan","state":"IL"}
{"index":{"_id":"6"}}
{"account_number":6,"balance":5686,"firstname":"Hattie","lastname":"Bond","age":36,"gender":"M","address":"671 Bristol Street","employer":"Netagy","email":"hattiebond@netagy.com","city":"Dante","state":"TN"}
省略...
最后点击执行。
执行成功后,可以运行 curl localhost:9200/bank/_search
,如果返回值中 value
是导入的条数就表示成功了。
Logstash 是开源的服务器端数据处理管道,能够同时从多个来源采集数据、转换数据,然后将数据发送到 Elasticsearch 中。Logstash 的官方文档请参见:https://www.elastic.co/guide/en/logstash/current/getting-started-with-logstash.html
[[Elasticsearch]] 是基于 [[Lucene]] 开源的全文搜索引擎。提供 RESTful 接口,可以实现精确快速的实时检索。
[[Kibana]] 是一个基于 Web 的可视化前端。还有一个 [[elasticsearch-head]] 也是一个 Elasticsearch 的前端,不过这里因为 Kibana 使用场景更加广泛,就选择 Kibana。
创建 network:
docker network create elastic
这里仅演示单节点的 Elasticsearch 搭建过程,如果要搭建集群模式,可以自行参考官网。
version: "3.0"
services:
elasticsearch:
container_name: es
image: elasticsearch:8.3.2
environment:
- xpack.security.enabled=false
- "discovery.type=single-node"
- "ELASTIC_PASSWORD=${ELASTIC_PASSWORD}"
networks:
- elastic
ports:
- 9200:9200
kibana:
container_name: kibana
image: kibana:8.3.2
environment:
- ELASTICSEARCH_HOSTS=http://es:9200
networks:
- elastic
depends_on:
- elasticsearch
ports:
- 5601:5601
networks:
elastic:
driver: bridge
Docker compose 会启动两个容器,一个容器运行 Elasticsearch,使用端口 9200,一个容器运行 Kibana 使用端口 5601.
两个镜像最新的版本可以分别在这里查看:
使用如下的命令检查 Elasticsearch 的状态:
❯ curl http://localhost:9200
{
"name" : "d9f0b969f13c",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "VRWzzZpISPugOCQadlC88A",
"version" : {
"number" : "8.3.2",
"build_type" : "docker",
"build_hash" : "8b0b1f23fbebecc3c88e4464319dea8989f374fd",
"build_date" : "2022-07-06T15:15:15.901688194Z",
"build_snapshot" : false,
"lucene_version" : "9.2.0",
"minimum_wire_compatibility_version" : "7.17.0",
"minimum_index_compatibility_version" : "7.0.0"
},
"tagline" : "You Know, for Search"
}
当启动 Elasticsearch 之后会产生一些证书,这些证书用来安全的在 Kibana 中访问 Elasticsearch。
http_ca.crt
:CA 证书,用来签名 HTTP 请求http.p12
:Keystore that contains the key and certificate for the HTTP layer for this node.transport.p12
:Keystore that contains the key and certificate for the transport layer for all the nodes in your cluster.http.p12
和 transport.p12
是密码保护的 PKSC#12 keystore。
可以使用如下命令获取 http.p12
密码:
bin/elasticsearch-keystore show xpack.security.http.ssl.keystore.secure_password
可以使用如下命令获取 transport.p12
密码:
bin/elasticsearch-keystore show xpack.security.transport.ssl.keystore.secure_password
等待容器启动之后可以直接访问 Kibana http://localhost:5601/
FFmpeg 可以使用 -i
参数来输入一个或多个文件,但有些时候会有一些将多个文件串联成一个文件的需求。比如将多个视频合并成一个视频文件,将多个音频文件合并和一个长音频文件。这个时候就需要使用到 FFmpeg 的 concat demuxer
。
concat demuxer
是 FFmpeg 1.1 引入的。主要可以用来合并多个媒体文件。
FFmpeg 有两种方式可以串联相同的文件:
demuxer
更加灵活,需要相同的编码,容器格式可以不一样。而 protocol
则需要容器的格式也一致。
demuxer
通过从一个固定格式的文件中读取文件列表,然后 FFmpeg 可以对这些文件一同处理。
创建文件 mylist.txt
,包含所有想要串联的文件:
# this is a comment
file '/path/to/file1.wav'
file '/path/to/file2.wav'
file '/path/to/file3.wav'
注意,这里的 #
是注释语句。文件中的文件路径可以是绝对的或相对的路径,然后就可以使用 FFmpeg 对这多个文件 stream-copy 或者 re-encode(重新编码) :
ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.wav
如果路径是相对的,这里的 -safe 0
可以省略。
如果有多个文件要添加到 mylist.txt
文件中,可以使用 Bash 脚本批量生成:
# with a bash for loop
for f in *.wav; do echo "file '$f'" >> mylist.txt; done
# or with printf
printf "file '%s'\n" *.wav > mylist.txt
demuxer
在文件流级别工作,concat protocol
在文件级别工作。特定的文件(比如 MPEG-2 传输流,或者其他)可以串联起来。
下面的命令将三个 MPEG-2 TS 文件串联到一起,不重编码:
ffmpeg -i "concat:input1.ts|input2.ts|input3.ts" -c copy output.ts
某些情况下,多个文件可能使用不同的编码,那么上面的命令就都无法使用。
如果要让 concat filter 工作,输入的文件必须拥有相同的 frame dimensions (eg. 1920*1080 pixels) 并且要有相同的 framerate。
假设有三个文件需要串联起来,每一个文件都有一个视频流和一个音频流:
ffmpeg -i input1.mp4 -i input2.webm -i input3.mov \
-filter_complex "[0:v:0][0:a:0][1:v:0][1:a:0][2:v:0][2:a:0]concat=n=3:v=1:a=1[outv][outa]" \
-map "[outv]" -map "[outa]" output.mkv
来拆解一下命令,首先指定所有的输入文件,然后实例化一个 -filter_complex
filtergraph
然后:
[0:v:0][0:a:0][1:v:0][1:a:0][2:v:0][2:a:0]
告诉 ffmpeg 使用输入文件中的哪一个流,然后发送给 concat filter。在这个例子中,第一个文件的视频流 0 [0: v:0]
和音频流 0 [0: a:0]
,第二个文件的视频流 0 [1: v:0]
和音频流 0 [1: a:0]
。
concat=n=3:v=1:a=1[outv][outa]
这个就是 concat fitler, n=3
告诉 filter 这里有三个输入分段,v=1
则表明每一个分段有一个视频流,a=1
表明每一个分段有一个音频流。filter 然后将这些分段连接产生两个输出流, [outv]
和 [outa]
两个输出流的名字。
注意的是两侧的双引号是必须的。
然后使用这些输出流,将他们 组合成输出文件 :
-map "[outv]" -map "[outa]" output.mkv
这行告诉 FFmpeg 使用 concat filter 的结果,而不是直接使用输入的 streams。
有一个叫做 mmcat 的 Bash script,可以在老版本的 FFmpeg 中实现 concat filter。
Hestia CP 是一个开源的 Linux 服务器控制面板(Control Panel),HestiaCP fork 自另一款流行的控制面板 VestaCP 。由于 VestaCP 开发和维护趋于停止,很多安全问题和漏洞没有及时修复,所以有人从 VestaCP 拉出新分支进行开发和维护。Hestia 可以作为 aaPanel(宝塔面板)的很好的开源代替。
HestiaCP 提供了一个简单干净的网页界面,给网站维护人员提供了更加简单的方式维护网页服务器。HestiaCP 提供了很多功能,包括
HestiaCP 还提供了基于命令行的管理工具,具体可以见 文档。
另一个值得一说的功能就是,HestiaCP 提供了一键安装网站(Quick Install App)的功能,默认提供了一些非常受欢迎的网页应用,包括 [[WordPress]], [[Drupal]], [[Joomla]], [[Opencart]], [[PrestaShop]], [[Lavarvel]], [[Symfony]] 等等。
在接触 Hestia 之前,有段时间直接使用 LNMP,或者使用 [[aapanel]],但后来发现 aaPanel 的 License 或许存在某些问题,并且在读了 Stallman 的 著作 之后对自由软件的认识更深刻了一些,所以直接替换成 GPL 发布的 Hestia。作为 aaPanel 的开源代替品,发现 Hestia 还是非常不错的。
后台演示:
sudo
本文中演示在 Ubuntu 20.04 上安装 HestiaCP。整个过程可能会需要 15 分钟左右。
安装脚本:
wget https://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.sh
bash hst-install.sh
可以通过 安装器 自己选择安装的组件。选择组件之后会产生一个命令:
wget https://raw.githubusercontent.com/hestiacp/hestiacp/release/install/hst-install.sh
sudo bash hst-install.sh --apache no --phpfpm yes --multiphp no --vsftpd yes --proftpd no --named yes --mysql yes --postgresql no --exim yes --dovecot yes --sieve no --clamav no --spamassassin no --iptables yes --fail2ban yes --quota no --api yes --interactive yes --with-debs no --port '8083' --hostname 'your_hostname' --email 'i@youremail.com' --password 'your_password' --lang 'en'
你可以根据自己的需要自行选择需要的组件。可以在官网 文档 中查看默认会安装的组件。
安装完成之后会在日志中看到后台登录的链接,以及默认的用户名(admin)和密码。脚本执行完成后可能会需要一次重启来完成安装。
访问 https://ip:8083
,或者如果已经配置了域名 A 记录指向该 IP,也可以使用域名加端口来访问。
安装过程中如果遇到:
[ * ] Installing dependencies...
!!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
WARNING: Your network configuration may not be set up correctly.
Details: The netplan configuration directory is empty.
You may have a network configuration file that was created using systemd-networkd.
It is strongly recommended to migrate to netplan, which is now the
default network configuration system in newer releases of Ubuntu.
While you can leave your configuration as-is, please note that you
will not be able to use additional IPs properly.
If you wish to continue and force the installation,
run this script with -f option:
Example: bash hst-install-ubuntu.sh --force
!!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
Error: Unable to detect netplan configuration.
这个错误是因为 Ubuntu 没有使用 netplan,或者 VPS 主机提供的镜像没有使用 netplan,但是 /etc/netplan
文件夹存在,这就导致 HestiaCP 安装脚本执行过程中判断错误。
解决方案:查看 /etc/netplan
文件夹,如果配置文件夹是空的,那么可以直接删除该文件夹,如果确定自己已经使用了 netplan 作为网络配置,那么检查一下网络配置。
在完成安装访问后台的时候,浏览器会报 Your connection is not private 的错误,这是因为 SSL 证书缺失了。
可以使用 v-add-letsencrypt-host
命令来申请证书。
不过我在执行的过程中发生一些问题,报错:
Error: Let's Encrypt validation status 400 (xxx.einverne.info). Details: Unable to update challenge :: authorization must be pending
Error: Let's Encrypt SSL creation failed
查看发现因为在机器上安装了 Docker,所以虚拟了一个网络端口,在后台 Web 查看域名的时候,看到其中关联的 IP 地址是一个本地的地址 172.17.0.1
,把这个地址修改成 VPS 的真实 IP 地址。然后重新执行命令即可。
如果出现其他的错误,也可以到如下的目录中查看日志:
/var/log/hestia/LE-user-domain-timestamp
虽然以 admin
登录可以在后台做任何事情,但是还是推荐创建一个新用户,以新用户的身份来操作。
创建完用户之后以该用户登录,然后在 Web 中,选择添加域名。
添加的过程中有如下配置:
在高级选项中:
www.yourdomain.com
指向你的域名AWStats
,可以到其 官网 查看/home/your_user/web/your_website/public_html/
可以在 /usr/local/hestia/data/templates/web/nginx/
目录下查看到默认的 Nginx 配置模板。其中的默认模板:
default.tpl
default.stpl
可以将默认的模板拷贝到新的文件修改:
cp original.tpl new.tpl
cp original.stpl new.stpl
cp original.sh new.sh
模板中支持的变量可以参考官网
默认情况下 HestiaCP 使用 8083 端口,当然在安装的时候也可以指定,但是如果安装完成之后想要调整端口,可以使用如下的命令:
v-change-sys-port 2083
更改 admin 用户密码
v-change-user-password admin yourpass
或者更改其他任何用户的密码。
v-change-sys-hostname your.hostname
强制主机名使用 SSL
v-add-letsencrypt-host
v-add-web-domain-ssl-hsts 'admin' 'hcp.domain.com'
v.add-web-domain-ssl-force 'admin' 'hcp.domain.com'
rm -fr /usr/local/hestia/install/rhel
rm -fr /usr/local/hestia/install/ubuntu
rm -fr /usr/local/hestia/install/debian/7
rm -fr /usr/local/hestia/install/debian/8
rm -fr /usr/local/hestia/install/debian/9
touch /etc/iptables.up.rules
v-add-firewall-rule ACCEPT 0.0.0.0/0 22 TCP SSH
v-add-firewall-rule ACCEPT 0.0.0.0/0 5566 TCP HestiaCP
source /etc/profile
PATH=$PATH:/usr/local/hestia/bin && export PATH
可以使用命令行:
v-update-sys-ip 1.2.3.4
v-rebuild-web-domains admin
v-rebuild-mail-domains admin
HestiaCP 是 VestaCP fork,VestaCP 开发和维护趋于停止,存在许多漏洞和安全性问题。VestaCP 是第一个 Nginx 的 GUI 控制面板。在 VestaCP 之前有很多 CLI-only 的管理工具。
[[Elasticsearch]] 是一款基于 [[Lucene]] 的开源的、分布式的搜索引擎。提供一个分布式、多租户的全文搜索引擎。提供 HTTP Web 界面和 JSON 格式接口。
Elasticsearch 由 Java 实现,是目前最流行的大数据存储、搜索和分析引擎。
GitHub:https://github.com/elastic/elasticsearch
大数据要解决三个问题:
但 Elasticsearch + Kibana 的组合可以快速解决如上提到的问题。
Elasticsearch 是面向文档的,存储整个文档或对象,内部使用 JSON 作为文档序列化格式。
在使用 Linux 安装之前设置 vm.max_map_count
至少是 262144.
使之生效:
sudo sysctl -w vm.max_map_count=262144
让系统重启之后也生效,需要编辑 /etc/sysctl.conf
添加一行:
vm.max_map_count=262144
通过 docker-compose 安装。
也可以下载手动安装。
我个人推荐在本地使用单节点安装启用。
默认情况,Elasticsearch 通过 9200 端口对外提供 REST API。Kibana 的默认端口是 5601。
如果遇到如下问题,请查看是否设置了 vm.max_map_count
。
es03_1 ERROR: [1] bootstrap checks failed. You must address the points described in the following [1] lines before starting Elasticsearch.
单节点的 Elasticsearch 可以使用 Docker 在本地启用,参考这里。
常用命令:
docker network create elastic
docker run --name es --net elastic -p 9200:9200 -p 9300:9300 -it docker.elastic.co/elasticsearch/elasticsearch:8.3.1
docker exec -it es /usr/share/elasticsearch/bin/elasticsearch-reset-password
Node,节点,Elasticsearch 运行实例,集群由多个节点组成。节点存储数据,并参与集群索引、搜索和分析。
Shard, 分片,数据中的一小部分,每一个分片是一个独立的 Lucene 实例,自身也是一个完整的搜索引擎。
索引会存储大量的数据,这些数据会超出单个节点的硬件限制,例如,占用 1TB 磁盘空间的 10 亿个文档的单个索引可能超出单个节点的磁盘容量,所以 Elasticsearch 提供了索引水平切分(Shard 分片)能力。
创建索引时只需要定义所需分片数量。每一个分片本身就是一个具有完全功能的独立「索引」,可以分布在集群中的任何节点上。
文档会被存储并被索引在分片中。但是当我们使用程序与其通信时,不会直接与分片通信,而是通过索引。
当集群扩容或缩小时,Elasticsearch 会自动在节点之间迁移分配分片。
分片分为:
从分片是主分片的副本,提供数据的冗余副本,在硬件故障时提供数据保护,同时服务于搜索和检索只读请求。
索引中主分片的数量在索引创建之后就固定了,但是从分片数量可以随时改变。
设置三个主分片和一组从分片
PUT /blogs
{
"settings" : {
"number_of_shards" : 3,
"number_of_replicas" : 1
}
}
分片很重要:
Index, 索引。在 Elasticsearch 中,存储数据的行为叫做索引 Indexing,在索引数据值前,要决定数据存储在哪里。
单个集群中可以定义任意多索引。
一个 Elasticsearch 集群可以包含多个索引(数据库),可以包含很多类型(表),类型中可以包含很多文档(行),文档中包含很多字段(列)。
关系数据库 -> 数据库 -> 表 -> 行 -> 列 (column)
Elasticsearch -> 索引 -> 类型 -> 文档 -> 字段(field)
在 Elasticsearch 中索引有不同的含义。
索引就是 Elasticsearch 提供的「数据库」。
为文档创建索引,就是将文档存储到索引(数据库)中的过程,只有建立了索引才能被检索。
在关系型数据库中为某一列添加索引,是在文件结构中使用 B-Tree 加速查询。在 Elasticsearch 和 Lucene 中使用 Inverted index (反向索引)的结构来实现相同的功能。
通常文档中的每一个字段都被创建了索引(有一个反向索引)
假如要创建员工名单:
PUT /corp/employee/1
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
employee
类型corp
索引中Document 文档,可被索引的基本信息单元。文档以 JSON 表示。单个索引理论上可以存储任意多的文档。
副本在分片或节点发生故障时提供高可用。
分片和对应的副本不可在同一个节点上
副本机制,可以提高搜索性能和水平扩展吞吐量,因为可以在所有副本上并行搜索。
默认情况下,Elasticsearch 中的每个索引都分配一个主分片和一个副本。集群至少需要有两个节点,索引将有一个主分片和一个完整副本。
Elasticsearch 提供了灵活的查询语言,可以完成更加复杂的搜索任务。
使用 JSON 作为主体:
GET /megacorp/employee/_search
{
"query" : {
"match" : {
"last_name" : "Smith"
}
}
}
Elasticsearch 有一项功能叫做 Aggregation,类似于 GROUP BY,但是更强大。结合查询语句可以实现非常多的聚合操作。
Elasticsearch 可以被扩展到上百成千台服务器来处理 PB 级别的数据。Elasticsearch 是分布式的。用户在使用的过程中不需要考虑到分片,集群等等,这些都是 Elasticsearch 自动完成的:
集群健康状态查询:
GET /_cluster/health
{
"cluster_name": "elasticsearch",
"status": "green", <1>
"timed_out": false,
"number_of_nodes": 1,
"number_of_data_nodes": 1,
"active_primary_shards": 0,
"active_shards": 0,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 0
}
其中 status 有三个状态:
集群健康状况:
GET /_cat/health?v
列出节点信息:
GET /_cat/nodes?v
列出集群中索引信息:
GET /_cat/indices?v
创建索引:
PUT /customer?pretty
GET /_cat/indices?v