日志 Linux
2018-05-03
配置
# cat /etc/logrotate.conf
weekly
su root adm
rotate 4
create
#dateext
#compress
include /etc/logrotate.d
以 Nginx 配置为例:
# cat /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily # 按日切割
missingok # 如果文件不存在,则不创建
rotate 14 # 最多保留 14 个日志文件
compress # 压缩
delaycompress # 延迟压缩
notifempty # 如果文件为空,则不创建
create 0640 www-data adm
# 可能一次切割多个日志,
# 但是后面遇到的每个脚本都只执行一次,
# 在所有日志切割之前或之后
sharedscripts
prerotate
if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
run-parts /etc/logrotate.d/httpd-prerotate; \
fi \
endscript
postrotate
invoke-rc.d nginx rotate >/dev/null 2>&1
endscript
}
其他常用选项:
dateext
部分日志需要添加日期后缀
lastaction/endscript
最后执行的指令,很有用,比如最后将日志备份到某些地方
比如:
rsync -au *.gz 192.168.64.234:/backup/nginx-logs/`hostname -s`/
参考资料与拓展阅读
架构 DNS
2018-05-02
历史
从阿帕网 (ARPANET) 时代一直到互联网的早期,网络节点比较少,都是通过本地 hosts 文件来实现主机名到 IP 地址的映射。
根据维基百科的信息,斯坦福研究所负责维护了一个公共 hosts 文件,大家会找他同步 (rfc606, rfc608)。
PS: 这个时候如果有主机名重复了谁来管?打电话过去让他们改名?
这套机制一直运行了十几年,公共 hosts 文件已经变的很大了,变化也很频繁(IP 可能已经不再那么固定了),需要经常同步。这个时候,斯坦福研究所的网络压力也越来越大了。
后来人们开始设计域名和域名相关的公共设施 (rfc805, rfc830)。最后,在 1983 年,形成了下面两个 RFC 文档:
- RFC 882, DOMAIN NAMES - CONCEPTS and FACILITIES
- RFC 883, DOMAIN NAMES - IMPLEMENTATION and SPECIFICATION
几年后(1987),正式的 DNS 标准 RFC 1034 和 RFC 1035 推出。
这套标准一直运行到现在,可能有对其进行拓展(比如 DNS 记录类型不断添加,Unicode 字符引入),但是基本技术设计没有改变。
DNS 的管理权问题
https://zhidao.baidu.com/question/1386069665602139980.html
基本流程
比如本站域名 www.markjour.com, 其完整形式应该是 www.markjour.com.
(后面多一个小数点)
DNS 软件
- BIND
- PowerDNS
- dnsmasq
- Unbound
- CoreDNS
- SmartDNS
Cache-Only DNS Server
新的发展
- 标准的 DNS 是运行在 UDP 53 端口上的。后来的 RFC 1123 增加了 TCP 的支持, 这个方案叫做 DNS over TCP, 还是在 53 端口。
- DNSCrypt, 2011 年设计的, 实现 DNS 的加密和验证,运行于 443 端口。注意:存在于 IETF 框架之外,但是好像有很多服务器支持。
- DNS over TLS (DoT), 2016 年 5 月成为规范。
RFC 7858 Specification for DNS over Transport Layer Security (TLS)
主要作用是加密传输,防止窃听。
- DNS over HTTPS (DoH), 2018 年 10 月成为规范。
RFC 8484 DNS Queries over HTTPS (DoH)
作用和 DoT 一样。
- DNS over TOR, 2019 年。
- Oblivious DNS-over-HTTPS (ODoH), 透过代理的方式,让 DoH 服务器无法获取客户端的真实 IP。同时代理无法获取 DNS 请求的内容。
参考资料与拓展阅读
NodeJS
2018-04-27
sudo apt install -y nodejs npm
# 已经不需要这句了:
# sudo ln -s `which nodejs` /usr/bin/node
# node -v
# npm -v
npm config set registry=https://registry.npm.taobao.org
sudo npm upgrade -g npm
# sudo npm install -g yarn --registry=https://registry.npm.taobao.org
curl --compressed -o- -L https://yarnpkg.com/install.sh | bash
yarn config set registry https://registry.npm.taobao.org
配置
echo registry=https://registry.npm.taobao.org > ~/.npmrc
npm config get registry
https://registry.npmjs.org/
npm config set registry=https://registry.npm.taobao.org
yarn config get registry
https://registry.yarnpkg.com
yarn config set registry https://registry.npm.taobao.org
SMTP Email
2018-04-24
RFC#821 定义的 SMTP 协议非常简单(简陋)。
1993 年,RFC#1425 SMTP Service Extensions 定义了 SMTP 协议的拓展框架。
这个向前兼容的安全拓展框架是通过 EHLO 命令来实现。
Email
2018-04-16
注意:这边不是讨论 邮箱地址的格式。
格式
含义
- SMTP 会话(投递)
- Mail From 真实投递的发信人
- Rcpt To 真实投递的收信人
- 邮件内容(显示)
From
发信人
- 如果和 Mail From 地址不同,可能会显示:由 xxx 代发
To
收信人
Cc
抄送人
Bcc
密送人
Rely-To
回复地址
- 客户端点击回复的时候用的
- 如果没有这个字段,就会回复 From 地址
Sender
发信人
Return-Path
/ Reverse-Path
/ Envelope-From
- 作用是在邮件投递出现问题的时候,邮件服务将邮件退回这个地址
- 如果我们看到这几个名字
- 可能是发信人自己在邮件中声明
- 可能是收信方收到邮件之后添加的,单独字段,或放在 Received 头中
关于抄送和密送
碳式复写纸 carbon paper
副本,抄送 carbon copy => CC
密送 blind carbon copy => BCC
按照设计,密送地址不希望被其他收信人、抄送人察觉,只是密送地址才知道自己是密送。
CC, BCC in SMTP
SMTP 服务器不处理 CC、BCC,SMTP 客户端应该自行处理
TO 地址 + CC 地址 + BCC 地址一起放到 SMTP 会话的 RCPT TO 字段
所以,按照我的理解,邮件客户端:
在一次 SMTP 会话中,如果有 3 个 TO/CC 地址,2 个 BCC 地址,应该对那 3 个地址批量发送,然后对那 2 个 BCC 地址分别加上 BCC 头,分别发送。
更稳妥一点:如果是批量发送邮件,不要放 BCC 到邮件头!!!显示一个 密送:xxx
也没啥意义。
- PS:MSN(Outlook),网易邮箱发出去的邮件,不会加 BCC 头
甚至网易可能在显示邮件原文的时候会移除 BCC 头(给网易邮箱发的 BCC 头都不见了)
- PS:Gmail,QQ 邮箱发出去的邮件,密送人会看到 BCC 头
from_addr = "from@markjour.com"
to_addrs = ["to@markjour.com"]
cc_addrs = ["cc1@markjour.com", "cc2@markjour.com"]
bcc_addrs = ["bcc@markjour.com"]
msg = f"""
From: {from_addr}
To: {", ".join(to_addrs)}
Cc: {", ".join(cc_addrs)}
Hello World
""".strip()
send_to = to_addrs + cc_addrs + bcc_addrs
server = smtplib.SMTP('smtp.126.com')
server.set_debuglevel(1)
server.login(api_user, api_key)
server.sendmail(from_addr, send_to, msg)
server.quit()
Python
2018-04-13
import logging
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
logging.basicConfig(level=logging.DEBUG)
SMTP_HOST = 'smtp.example.com'
SMTP_PORT = 587
SMTP_USERNAME = 'your_username'
SMTP_PASSWORD = 'your_password'
SMTP_STARTTLS = True
sender = 'sender@example.com'
recipients = ['rcpt01@example.com', '中国 <rcpt02@example.com>']
subject = 'Test Email'
content_text = 'This is a test email.'
content_html = '<html><h1>Hello</h1></html>'
def encode_recipient(name, addr):
pass
msg = MIMEMultipart()
msg['From'] = sender
msg['To'] = ', '.join(recipients)
msg['Subject'] = subject
msg.attach(MIMEText(content_text))
msg.attach(MIMEText(content_html))
print(msg.as_string())
def smtp_debug(self, *args):
msg = ' '.join(map(str, args))
logging.debug(msg)
smtp = smtplib.SMTP(SMTP_HOST, SMTP_PORT)
smtp._print_debug = smtp_debug
smtp.set_debuglevel(1)
smtp.ehlo()
if SMTP_STARTTLS:
smtp.starttls()
smtp.ehlo()
if SMTP_USERNAME and SMTP_USERNAME:
smtp.login(SMTP_USERNAME, SMTP_PASSWORD)
smtp.sendmail(sender, recipients, msg.as_string())
smtp.quit()
Email 时间
2018-04-10
比如:
Sun, 20 Jun 2018 00:47:04 -0700 (PDT)
Thu, 10 Jun 2021 16:10:03 -0700 (PDT)
Thu, 10 Jun 2021 08:06:31 -0700 (PDT)
定义
定义在 RFC 822 的 5. DATE AND TIME SPECIFICATION。
date-time = [ day "," ] date time ; dd mm yy hh:mm:ss zzz
day = "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun"
date = 1*2DIGIT month 2DIGIT ; day month year e.g. 20 Jun 82
month = "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" / "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
time = hour zone ; ANSI and Military
hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT]
; 00:00:00 - 23:59:59
zone = "UT" / "GMT" ; Universal Time
; North American : UT
/ "EST" / "EDT" ; Eastern: - 5/ - 4
/ "CST" / "CDT" ; Central: - 6/ - 5
/ "MST" / "MDT" ; Mountain: - 7/ - 6
/ "PST" / "PDT" ; Pacific: - 8/ - 7
/ 1ALPHA ; Military: Z = UT;
; A:-1; (J not used)
; M:-12; N:+1; Y:+12
/ ( ("+" / "-") 4DIGIT ) ; Local differential
; hours+min. (HHMM)
总结就是:
[day-of-week,] day month year hour:minute[:second] timezone
- 周几和秒是可选的,据我观察,没有邮件省略这两部分
- 周几和月份采用三字母英文缩写(首字母大写)
- 年份是 2 位数字,后来的规范更新中建议采用 4 位数字。出于兼容性考虑,一般都保留了对 RFC 822 两位数字年份的支持。
- 时区除了数字之外,可以使用
UT
、GMT
、EST
、EDT
、CST
、CDT
、MST
、MDT
、PST
、PDT
,
还有 25 个字母(J 没有使用),Z 表示 UTC/GMT 时间,A - M 表示 -1 ~ -12 时区,N - Y 表示 1 到 12 时区。
|
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
West |
A |
B |
C |
D |
E |
F |
G |
H |
I |
K |
L |
M |
Eest |
N |
O |
P |
Q |
R |
S |
T |
U |
V |
W |
X |
Y |
Python
生成符合要求的时间字符串比较简单:
import time
time.strftime('%a, %d %b %Y %H:%M:%S %z')
# 'Tue, 10 Apr 2018 09:10:05 +0800'
但是由于这个灵活度比较大,解析起来最好借助专业的库(email.utils
)来做这个事。
import time
import datetime
import email.utils
import pytz
# 解析 ############################################
date_str = 'Sun, 20 Jun 2018 00:47:04 -0700 (PDT)'
email.utils.parsedate_to_datetime(date_str)
# datetime.datetime(2018, 6, 20, 0, 47, 4, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200)))
email.utils.parsedate_tz(date_str)
(2018, 6, 20, 0, 47, 4, 0, 1, -1, -25200)
# 生成 ############################################
# email.utils.formatdate(timeval=None, localtime=False, usegmt=False)
email.utils.formatdate()
# 'Tue, 10 Apr 2018 09:10:41 -0000'
# email.utils.format_datetime(dt, usegmt=False)
dt = datetime.datetime.now()
email.utils.format_datetime(dt)
# 'Tue, 10 Apr 2018 09:16:43 -0000'
tz = pytz.timezone('Asia/Shanghai') # <DstTzInfo 'Asia/Shanghai' LMT+8:06:00 STD>
dt = datetime.datetime(2018, 4, 10, 9, 10, 0, tzinfo=tz)
# datetime.datetime(2018, 4, 10, 9, 10, tzinfo=<DstTzInfo 'Asia/Shanghai' LMT+8:06:00 STD>)
email.utils.format_datetime(dt)
# 'Tue, 10 Apr 2018 09:10:00 +0806'
Email
2018-04-07
规范
规范定义比较复杂,甚至支持注释。
我简化一下(去掉注释,去掉双引号,去掉 [IPv4]
/ [IPv6]
/ 主机名
做域):
- 格式:
域内部分@域
-
域内部分:
-
长度不超过 64
- 大小写字母 + 数字(62)
-
ASCII 标点符号(19)
!#$%&'*+-/=?^_`{|}~
-
可以加入点号(.
)隔开,不放首尾,不连续出现
-
域名
-
每一级域名 1 - 63 个字符,总长度不超过 253
这个限制和 DNS 报文设计有关
国际化域名转换成 Punycode 之后也必须遵守这个约定
- 允许包含数字、字母(大小写不敏感)和短横线(
-
)
- 短横线不能出现在首尾位置
实践
实际上的邮件地址会更加简单:
- 长度限制
- QQ 邮箱 3 - 18
- 网易邮箱 6 - 18
- Gmail 6 - 30
- 新浪邮箱 4 - 16
- 字符限制:字母数字 +
.-_
- 一般大小写不敏感
- 连字符(
.-_
)不可连续出现
- 网易免费邮箱只支持下划线,网易 VIP 邮箱支持点和下划线
- Gmail 只支持点和加号
- 在实际投递中,点和加号会被忽略
- 点可以用作单词风格
- 加号通常用做来信归类,比如注册淘宝时
+taobao
,订阅开发者头条时 +toutiao
,相关邮件就方便搜索归类。
- 部分邮箱不支持全数字(别有用途,或是避免 QQ 号冲突,或是避免手机号冲突)
- 开头结尾字符限制:
- 字母数字开头 + 字母数字结尾
- 字母开头 / 字母数字结尾
正则表达式
以规范为准,参考真实场景下的实践:
域内部分:
/[a-z0-9]+([.-_#][a-z0-9]+)+/;
域名部分:
/[a-z0-9]+(-[a-z0-9]+)?(\.[a-z0-9]+(-[a-z0-9]+)?)+/;
汇总在一起就是:
/^[a-z0-9]+([.-_#][a-z0-9]+)+@[a-z0-9]+(-[a-z0-9]+)?(\.[a-z0-9]+(-[a-z0-9]+)?)+$/;
参考资料与拓展阅读
虚拟化 云计算 OpenStack 计算机网络 LinuxNetwork
2018-03-24
相关文章:
物理设备
- VLAN 虚拟局域网,设备层面上的网络分区,网络设备提供的功能
网络报文给 VLAN Tag 分配了四个字节,其中 3 个字节用于 VLAN ID,1 个字节用于 VLAN Priority。
作为 VLAN ID 的 12bit(0-4095)中,首位两数作为保留值,也就是说 VLAN 技术支持的最大网络数是 4094。
Linux 网络技术
在 Linux 内核的网络设备管理层,虚拟设备和物理设备是同等地位。
- network namespace 网络隔离,虚拟化的基础
- bridge 网桥,相当于交换机,二层数据交换
- veth 虚拟网口,成对出现,两个虚拟网口之间可以相互连接(可以跨 namespace)
- tap/tun
- tap TAP 设备,虚拟二层网络,处理 TCP/UDP 包,
有自己的 MAC 地址,可以桥接到物理网卡
- tun TUN 设备,虚拟三层网络,处理 IP 包
- iptables 网络管理
确切的说是以 iptables 为代表的一系列网络管理技术
KVM / Neutron
- qvb neutron 网络桥
- qvo neutron 网络虚拟接口
Neutron 网络模式:
- VLAN
- VXLAN 虚拟拓展局域网,在三层 UDP 协议中封装二层数据包,突破 VLAN 的限制
- GRE Gerneral Routing Encapsulation,通用路由封装协议
英语
2018-03-18
类别 |
英语名称 |
简写 |
说明 |
名词 |
noun |
n |
- |
动词 |
verb |
v |
- |
形容词 |
adjective |
adj |
- |
副词 |
adverb |
ad/adv |
- |
介词 |
preposition |
perp |
in on at |
连词 |
conjunction |
conj |
and or but if |
代词 |
pronoun |
pron |
I you he she |
数词 |
numeral |
num |
one two three |
冠词 |
article |
art |
the a an |
感叹词 |
interjection |
interj |
oh hey |
- 名词:
- 冠词:不定冠词,定冠词,零冠词;
- 数词:基数词,序数词;