开发工具 Ubuntu Linux
2019-04-26
Ubuntu 19.04 与 4/19 发布,生命周期 9 个月。我提前两个月就定着日程在等,总是克制不住追新的冲动,哈哈。
好像主要就是:
- 内核升级到 5.0(4.x 升级到 5.0 其实没有什么大变化,主要是老人家高兴)
- GNOME 3.32,之前是 3.30
do-release-upgrade
由于审计过程中意外中断,导致出现了一些问题,这里做个记录。
声明:这些问题,是非正常升级流程出现的,不是说是 Ubuntu 的问题。
DB MySQL
2019-04-19
在开源中国每日动弹中看到这么一道题目,蛮有意思,还学到了一个新的 MySQL 语法:CTE。
NodeJS
2019-04-17
线上某些基于 nodejs 的服务时不时看到这种进程,而且一直都在:
root 25997 1 0 Mar25 ? 00:00:00 /root/.nvm/versions/node/v10.14.2/bin/node /root/.nvm/versions/node/v10.14.2/lib/node_modules/npm/node_modules/update-notifier/check.js {"pkg":{"name":"npm","version":"6.4.1"}}
经过检查判断,这是 npm 带来的一个依赖模块,用来做版本检测。
Python Email DKIM
2019-04-16
- pydkim
- https://pypi.org/project/pydkim/
- https://hewgill.com/pydkim/
- NOTE: This page describes the last release of pydkim from 2008. The latest version is a fork found at dkimpy in Launchpad and is under active development.
- 最新版本是 2008/06 发布的 v0.3
- dkimpy
- https://pypi.org/project/dkimpy/
- https://launchpad.net/dkimpy
- 最新版本是昨天发布的 v0.9.2
Date |
Version |
2023-07-28 |
1.1.5 |
2023-05-12 |
1.1.4 |
2023-04-30 |
1.1.3 |
2023-04-09 |
1.1.2 |
2023-03-10 |
1.1.1 |
2023-02-25 |
1.1.0 |
2023-04-30 |
1.0.6 |
2020-08-09 |
1.0.5 |
2020-04-06 |
1.0.4 |
2020-01-15 |
1.0.3 |
2019-12-31 |
1.0.2 |
2019-12-15 |
1.0.1 |
2019-12-09 |
1.0.0 |
2019-12-24 |
0.9.6 |
2019-10-07 |
0.9.5 |
2019-09-25 |
0.9.4 |
2019-08-09 |
0.9.3 |
2019-04-15 |
0.9.2 |
2018-12-09 |
0.9.1 |
2018-10-30 |
0.9.0 |
说明
默认签名字段(28 个):
cc, content-description, content-id, content-transfer-encoding, content-type,
date,
from,
in-reply-to,
list-archive, list-help, list-id, list-owner, list-post, list-subscribe, list-unsubscribe,
message-id, mime-version,
references, reply-to, resent-cc, resent-date, resent-from, resent-message-id, resent-sender, resent-to,
sender, subject,
to
d = dkim.DKIM('')
print(b', '.join(d.should_sign | d.frozen_sign))
b'list-unsubscribe, content-id, list-id, mime-version, resent-date, sender, cc, reply-to, content-type, list-owner, resent-message-id, resent-cc, resent-from, to, content-description, date, list-post, in-reply-to, content-transfer-encoding, from, references, list-help, subject, list-archive, resent-sender, list-subscribe, message-id, resent-to'
print(b', '.join(sorted(d.should_sign | d.frozen_sign)))
b'cc, content-description, content-id, content-transfer-encoding, content-type, date, from, in-reply-to, list-archive, list-help, list-id, list-owner, list-post, list-subscribe, list-unsubscribe, message-id, mime-version, references, reply-to, resent-cc, resent-date, resent-from, resent-message-id, resent-sender, resent-to, sender, subject, to'
示例
准备实验用的密钥对。
openssl genpkey -algorithm RSA -out /tmp/private_key.pem
openssl rsa -in /tmp/private_key.pem -check
openssl rsa -pubout -in /tmp/private_key.pem -out /tmp/public_key.pem
import dkim
domain = 'mail.markjour.com'
selector = 's20190416'
with open('/tmp/private_key.pem', 'rb') as f:
privkey = f.read().strip()
# dkim.parse_pem_private_key(privkey)
message = """
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=utf-8
Date: Mon, 24 Sep 2018 12:31:21 +0000 (UTC)
From: Admin <no-reply@mail.markjour.com>
Mime-Version: 1.0
Subject: Hello World
Message-ID: <n4F5zz24LXvYqPHVrZLPJokasT7MlLxYQx6g>
Reply-To: sender@mail.markjour.com
To: kwicoo@gmail.com
List-Unsubscribe: <mailto:unsubscribe@mail.markjour.com?p=Ahi2DRmdOnTdpsDzPClCPqbpwmFyjvGJV2xfJGWqw6eFEKRwI402QeoSsFrArTw1s48A59f60pLl0x71ojsQSWERnp3aMZA6YvEw>
X-SMTP-ID: c89cf6a5-22b7-4d1a-9bce-9f91a6be1bfb
HELLO WORLD
""".strip().encode()
# dkim.rfc822_parse(message)
# print(dkim.DKIM(message).default_sign_headers())
# [b'Content-Transfer-Encoding', b'Content-Type', b'Date', b'From', b'Mime-Version', b'Subject', b'Message-ID', b'Reply-To', b'To', b'List-Unsubscribe', b'From']
signature = dkim.sign(message, selector.encode(), domain.encode(), privkey)
print(signature.decode())
# DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=mail.markjour.com;
# i=@mail.markjour.com; q=dns/txt; s=s20190416; t=1555392275;
# h=content-transfer-encoding : content-type : date : from :
# mime-version : subject : message-id : reply-to : to : list-unsubscribe
# : from; bh=qg03cTlGc4OH4uPv7BGgoUyhgh23r+o1O6qzYOLixvA=;
# b=sJ09G6hHPaP6AMp2mqUXjEZ+BfUFz0o6nbpXWxJ4/OG0o9ZwPSj8aJibZtJjTKP3k/TR/
# 6SD543V8iNw+JwwM+XLOUZa0iduK+QkedccqNl5Hcfc9UI/U11NoHz76B3csL9KE9tb40jF
# mlLCuVUjci4HlOfEoKF8Ame8yWDHXVoNS/YT9/OSSc5q5q+qp6OX6PvzzxDomCHC6kbhOdv
# Yc/KEXrMQ1JQ971pRUBNQK3eN7bV7g1BwXuMEuhdwDa4aZ4YYcakKywo4Oey7bIy1E7evZN
# 5rUitRExLH4dQNrhxoZd4c3QOjd4ROTwseAaMN10U/egzDXjcw2q0UUC1UKQ==
append_headers = [b'x-smtp-id']
d = dkim.DKIM(message)
include_headers = d.default_sign_headers()
include_headers.extend(append_headers)
signature = d.sign(selector.encode(), domain.encode(), privkey, include_headers=include_headers)
print(signature.decode())
# DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=mail.markjour.com;
# i=@mail.markjour.com; q=dns/txt; s=s20190416; t=1555392275;
# h=content-transfer-encoding : content-type : date : from :
# mime-version : subject : message-id : reply-to : to : list-unsubscribe
# : from : x-smtp-id; bh=qg03cTlGc4OH4uPv7BGgoUyhgh23r+o1O6qzYOLixvA=;
# b=MTSeE8X3R+8bn+kkJaX5j/OKPMe+sdombmmwK5zME3SHBqiOLbxCwOGyh3qJKXdLpJlEg
# pBnsDmNEjgC/rtBoclvnlCsaN7OFcZIe6ehfjwGeaw41r38Y8IgUQCkuN+IiL8FN1IiMI2f
# kSayumwcOCAwmA4yJfu8n1v4W416jXt775YKR+1bt2Df1fNA6FnfoSMTqZl7rHn9zo76Efg
# yvm7M0uT3uz0NZbJtqOnMFzRri9TEj4jYiCgsNaBYA9prbZlA02svoJx9qIJ2mKA+EcVpxK
# IsEAY4ZXzXfhynKLeOYGK786ghiZrtsQYGbP6c1fAzTNy+fLJzRFozsV/wEQ==
headers = set(dkim.DKIM.SHOULD) | set(dkim.DKIM.FROZEN) | append_headers - set(dkim.DKIM.SHOULD_NOT)
signature = dkim.sign(message, selector.encode(), domain.encode(), privkey, include_headers=headers)
print(signature.decode())
# DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=mail.markjour.com;
# i=@mail.markjour.com; q=dns/txt; s=s20190416; t=1555392275;
# h=in-reply-to : x-smtp-id : content-type : cc : content-id : list-post
# : date : resent-from : list-owner : list-id : to : content-description
# : list-subscribe : message-id : sender : mime-version :
# resent-message-id : list-help : content-transfer-encoding : resent-cc
# : resent-date : list-unsubscribe : references : resent-sender : from :
# list-archive : subject : resent-to : reply-to;
# bh=qg03cTlGc4OH4uPv7BGgoUyhgh23r+o1O6qzYOLixvA=;
# b=lLJafHJ8B/DoO4FncLp+BIHaPy4xsq7dRAWjzAvkRoDSwjcg3EloW0FsCXS45EkmwmBZC
# Vks7zeOR1CS8oxcpauhxj1XnlwfcwLWtAQ3pogQTzNh4EEUFiNfgJTdXefAh7cpGHolQmy7
# w2TBXDPx+Ikynw2tNnGOBduLWi+BH3Et8KGaskR4D9QHWSrk4pqeaNannNhDPUfE98d2fS3
# kKBvqiEaTubQBdi8VXcl8J4R1SfdJZR2NfBJkPjJejlwTJaSytF2zyberpgflj0sEc8iHvM
# 2UQRcpxqm8GMRyzzKAXBSTzQhmaTOHntGokDTunNlUc/izFFRJm9SFiVq64g==
OpenDKIM
使用 opendkim-genkey 生成签名私钥和 DNS 配置文件:
$ opendkim-genkey --verbose --domain=mail.markjour.com --selector=s20190416 --directory=/tmp/
opendkim-genkey: generating private key
opendkim-genkey: private key written to s20190416.private
opendkim-genkey: extracting public key
opendkim-genkey: DNS TXT record written to s20190416.txt
域名配置好之后,可以使用 opendkim-testkey
检查:
$ opendkim-testkey -d test.markjour.com -k /tmp/private_key.pem -s s20190416 -v
opendkim-testkey: 's20190416._domainkey.test.markjour.com' record not found
存储
2019-04-14
有空思考一下几种场景下的文件存储方案。
- 场景 1. Web 静态资源
- 场景 2. 虚拟化中的卷存储
- 场景 3. 邮件系统中的邮件
- 场景 4. 大量图片,音频,视频(二进制)
- 场景 5. 大量日志(文本)
开发者
2019-04-14
突然想了解一下我们 SMTP 服务中的入栈邮件大小,于是写了点脚本分析一下。
先上结论:
WebDev 安全
2019-04-09
某用户委托安全公司对本司(SendCloud)短信发送业务做安全检测,发现咱们的上游通道某一环节的安全漏洞。
跟踪这个过程,真的十分有趣。
这是 XSS 第一次发生在我身边,怎么也不会想到有人会犯这么弱智的错误。最基本的页面输出转义都没做。
页面内容输出转义、SQL 防注入、表单的 CSRF token 校验,应该算是 Web 站点搭建的基础工作吧!
Linux
2019-04-04
以我本地系统(Ubuntu)上的 supervisord 为例。
ps -ef | grep supervisord
/ pgrep supervisord
sudo cat /proc/1553/maps
sudo gdb attach 1553
- gdb 中导出指定区域内存
dump memory /tmp/1553-heap.mem 0x564a7e667000 0x564a7eb25000
- 显示内存数据
strings -n 10 /tmp/1553-heap.mem
ASCII 格式的展示,过滤掉长度少于 10 的行。
关于 /proc/pid/maps
文件的格式
内存映射(mmap):
- 文件映射,将整个文件或文件的一部分映射到内存中
- 匿名映射,创建一个全为 0 的内存空间
这里的 maps 文件就是内存映射的一个情况。
- 内核操作集:proc_pid_maps_op,导出函数:show_map(没接触过内核开发)
- 可以
sudo head /proc/self/maps
试试。当前进程的内存映射信息表,软链接。
- Linux 内存管理单元数据结构:
vm_area_struct
$ sudo head /proc/1553/maps
564a7d858000-564a7d8a5000 r--p 00000000 08:01 3018208 /usr/bin/python2.7
564a7d8a5000-564a7da56000 r-xp 0004d000 08:01 3018208 /usr/bin/python2.7
564a7da56000-564a7db65000 r--p 001fe000 08:01 3018208 /usr/bin/python2.7
564a7db66000-564a7db68000 r--p 0030d000 08:01 3018208 /usr/bin/python2.7
564a7db68000-564a7dbde000 rw-p 0030f000 08:01 3018208 /usr/bin/python2.7
564a7dbde000-564a7dc02000 rw-p 00000000 00:00 0
564a7e667000-564a7eb25000 rw-p 00000000 00:00 0 [heap]
7fe8e4308000-7fe8e4448000 rw-p 00000000 00:00 0
7fe8e4448000-7fe8e444c000 r--p 00000000 08:01 1840428 /lib/x86_64-linux-gnu/libexpat.so.1.6.8
7fe8e444c000-7fe8e446d000 r-xp 00004000 08:01 1840428 /lib/x86_64-linux-gnu/libexpat.so.1.6.8
- 第一列:address 地址。[vm_start, vm_end),即起始地址-结束地址。
- 第二列:perms 权限。vm_flags,前三位分别是
r
/w
/x
,不必说,第四位有两种值:p
或 s
,分别表示私有 private 或共享 shared。
- 第三列:offset 偏移。vm_pgoff,如果是从文件映射到内存,那么偏移值表示从这个文件的指定位置开始,否则就会是
00000000
我猜,可能比较多的是用在拓展库之类的方面。
- 第四列:dev 设备。主设备号:次设备号,同样适用于从文件映射到内存的情况,表示文件所存放的设备。
- vm_file->f_dentry->d_inode->i_sb->s_dev
- 第五列:inode FS索引节点。同样适用于从文件映射到内存的情况,表示文件所存放的 “块”(或者叫 “区域” 吧)。
- vm_file->f_dentry->d_inode->i_ino
- 0 表示不关联,dev 字段也应该为
00000000
- 第六列:pathname 文件名
- 文件名
- 这段虚拟内存在进程中的角色,常见的:
[heap]
堆
[stack]
栈,主线程(main process)
[stack:1001]
栈,线程 ID 我还没见到过这样的情况
[vdso]
[vvar]
[vsyscall]
- 匿名映射
其他
- 据说,主线程申请内存(malloc)会显示
[heap]
,子线程申请则是匿名映射。
- 子线程的栈空间动态分配,匿名。这就是我没看到一例类似
[stack:1001]
情况的原因么?
-
从 maps 文件记录上看,增加一个子线程,在 maps 文件中就增加了两条记录,分别是子线程的栈空间和栈保护页的记录。默认情况下,pthread为子线程预留的栈空间大小为1MB,栈保护页为4KB(这主要跟页大小相关)。
#!/usr/bin/env python
import re
maps_file = open('/proc/self/maps', 'r')
mem_file = open('/proc/self/mem', 'r', 0)
for line in maps_file.readlines(): # for each mapped region
m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r])', line)
if m.group(3) == 'r': # if this is a readable region
start = int(m.group(1), 16)
end = int(m.group(2), 16)
mem_file.seek(start) # seek to region start
chunk = mem_file.read(end - start) # read region contents
print chunk, # dump contents to standard output
maps_file.close()
mem_file.close()
sudo awk -n -F '[- ]' '/\[heap\]/ {h="0x"$2-"0x"$1+1;printf("%d bytes (%.2f MB)\n",h,h/1024/1024)}' /proc/1553/maps
python -c "import sys;a,b=sys.argv[1].split('-');ai=int('0x'+a,16);bi=int('0x'+b,16);x=(bi-ai+1);y=x/(1024*1024);print('%d Bytes (%.2f MB)'%(x,y));" 55854b0f5000-55855a372000
参考资料或拓展阅读
- colin.guru,Dumping Ram From Running Linux Processes
- StackOverflow,How to identify STACK and HEAP segments in /proc/$PID/maps file?
- StackOverflow,How do I read from /proc/$pid/mem under Linux?
- CSDN,linux proc maps文件分析
MySQL DB
2019-03-29
问题
mysql> status
--------------
mysql Ver 14.14 Distrib 5.7.25, for Linux (x86_64) using EditLine wrapper
Connection id: 17190053
Current database: gkbb
Current user: root@10.9.165.246
SSL: Not in use
Current pager: less
Using outfile: ''
Using delimiter: ;
Server version: 5.5.5-10.1.26-MariaDB MariaDB Server
Protocol version: 10
Connection: 10.9.108.125 via TCP/IP
Server characterset: utf8
Db characterset: utf8
Client characterset: utf8
Conn. characterset: utf8
TCP port: 3306
Uptime: 13 days 21 hours 14 min 38 sec
Threads: 276 Questions: 31378648 Slow queries: 212 Opens: 2977 Flush tables: 1 Open tables: 2761 Queries per second avg: 26.155
--------------
mysql> show global variables like "innodb_version";
+----------------+-------------+
| Variable_name | Value |
+----------------+-------------+
| innodb_version | 5.6.36-82.1 |
+----------------+-------------+
1 row in set (0.06 sec)
PS: 查看 status
还有一个快捷方式 \s
。
编辑测试库表结构(添加字段),卡住,任何操作都不行了,等一个多小时,还是不行。。
还一度怀疑是不是表结构设计问题,字段、数据是不是太多了。
过程
偶尔想起看看会话情况:
SELECT * FROM information_schema.processlist WHERE db = 'mydb';
或命令:
mysqladmin -uroot -p123456 processlist
mysql -uroot -p123456 -e 'SHOW PROCESSLIST'
看到里面好几个会话的状态都是 wait for table metadata lock
,这就有点奇怪了,之前没有见过。
网上的资料显示:
为了在并发环境下维护表元数据的数据一致性,在表上有活动事务(显式或隐式)的时候,不可以对元数据进行写入操作。因此 MySQL 引入了 metadata lock ,来保护表的元数据信息。
因此在对表进行上述操作时,如果表上有活动事务(未提交或回滚),请求写入的会话会等待在 Metadata lock wait 。
如果资料没错,那么就是说,如果有事务没有结束,DDL 操作请求 MDL(metadata lock)时会卡住这张表。
我想起我们的服务中确实存在会话没有关闭的情况。
- 用了 SQLAlchemy 做 ORM
- 每次查询都使用一个会话,包括 SELECT
- 增删改操作都立即 commit 了,SELECT 却没有(记得是有个什么原因特意如此)
合理怀疑:这个查询 SESSION 没有关闭,导致 ALTER 语句进入 MDL 等待状态,然后导致了表无法进行任何操作(包括查询,至于为什么这样,我不知道)。
本地复现
- 开两个终端,分别建立 MySQL 连接。
- 其中一个终端(A):
SET SESSION auto_commit = 0;
SELECT * FROM test.test LIMIT 1;
- 另一个终端(B)只需要:
TRUNCATE test.test;
,然后发现:卡住了。
PS:
- DDL 需要 metadata 锁。
TRUNCATE
属于 DDL,可能因为其非事务性(不支持提交和回滚)。参考:https://dba.stackexchange.com/questions/36607/why-is-truncate-ddl
现在,回到终端 A:
mysql> select * from information_schema.processlist where db = 'test';
+----+------+-----------+------+---------+------+---------------------------------+----------------------------------------------------------------+
| ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO |
+----+------+-----------+------+---------+------+---------------------------------+----------------------------------------------------------------+
| 3 | root | localhost | test | Query | 0 | executing | select * from information_schema.processlist where db = 'test' |
| 5 | root | localhost | test | Query | 6111 | Waiting for table metadata lock | truncate test |
+----+------+-----------+------+---------+------+---------------------------------+----------------------------------------------------------------+
2 rows in set (0.00 sec)
mysql> select * from information_schema.innodb_trx\G
*************************** 1. row ***************************
trx_id: 421232684444408
trx_state: RUNNING
trx_started: 2019-03-29 16:06:14
trx_requested_lock_id: NULL
trx_wait_started: NULL
trx_weight: 0
trx_mysql_thread_id: 3
trx_query: select * from information_schema.innodb_trx
trx_operation_state: NULL
trx_tables_in_use: 0
trx_tables_locked: 0
trx_lock_structs: 0
trx_lock_memory_bytes: 1136
trx_rows_locked: 0
trx_rows_modified: 0
trx_concurrency_tickets: 0
trx_isolation_level: REPEATABLE READ
trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_adaptive_hash_latched: 0
trx_adaptive_hash_timeout: 0
trx_is_read_only: 0
trx_autocommit_non_locking: 0
1 row in set (0.00 sec)
mysql> show engine innodb status\G
*************************** 1. row ***************************
Type: InnoDB
Name:
Status:
=====================================
2019-03-29 19:04:40 0x7f1bcc1d6700 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 3 seconds
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 7 srv_active, 0 srv_shutdown, 11228 srv_idle
srv_master_thread log flush and writes: 11234
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 16
OS WAIT ARRAY INFO: signal count 10
RW-shared spins 0, rounds 27, OS waits 12
RW-excl spins 0, rounds 32, OS waits 0
RW-sx spins 0, rounds 0, OS waits 0
Spin rounds per wait: 27.00 RW-shared, 32.00 RW-excl, 0.00 RW-sx
------------
TRANSACTIONS
------------
Trx id counter 54542
Purge done for trx's n:o < 54542 undo n:o < 0 state: running but idle
History list length 53
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 421232684445328, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 421232684443488, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
--------
FILE I/O
--------
I/O thread 0 state: waiting for completed aio requests (insert buffer thread)
I/O thread 1 state: waiting for completed aio requests (log thread)
I/O thread 2 state: waiting for completed aio requests (read thread)
I/O thread 3 state: waiting for completed aio requests (read thread)
I/O thread 4 state: waiting for completed aio requests (read thread)
I/O thread 5 state: waiting for completed aio requests (read thread)
I/O thread 6 state: waiting for completed aio requests (write thread)
I/O thread 7 state: waiting for completed aio requests (write thread)
I/O thread 8 state: waiting for completed aio requests (write thread)
I/O thread 9 state: waiting for completed aio requests (write thread)
Pending normal aio reads: [0, 0, 0, 0] , aio writes: [0, 0, 0, 0] ,
ibuf aio reads:, log i/o's:, sync i/o's:
Pending flushes (fsync) log: 0; buffer pool: 0
639 OS file reads, 99 OS file writes, 21 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 4 merges
merged operations:
insert 0, delete mark 0, delete 0
discarded operations:
insert 0, delete mark 0, delete 0
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
0.00 hash searches/s, 0.00 non-hash searches/s
---
LOG
---
Log sequence number 26417867
Log flushed up to 26417867
Pages flushed up to 26417867
Last checkpoint at 26417858
0 pending log flushes, 0 pending chkp writes
17 log i/o's done, 0.00 log i/o's/second
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 137428992
Dictionary memory allocated 133441
Buffer pool size 8192
Free buffers 7710
Database pages 482
Old database pages 0
Modified db pages 0
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 446, created 41, written 72
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool page gets since the last printout
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 482, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
--------------
ROW OPERATIONS
--------------
0 queries inside InnoDB, 0 queries in queue
1 read views open inside InnoDB
Process ID=4492, Main thread ID=139757271107328, state: sleeping
Number of rows inserted 6, updated 0, deleted 0, read 20
0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s
----------------------------
END OF INNODB MONITOR OUTPUT
============================
1 row in set (0.00 sec)
表明:事务存在,TRUNCATE 锁等待。
如果,kill 3
干掉这个没有 commit 的查询 SESSION,TRUNCATE
就会正常执行下去。
结论
- 不管怎样,应该保持事务的短小精干,快速执行和退出。
PS:业务代码中 SELECT
之前为什么不提交的问题需要进一步检查。
- DDL 需要 MDL,而没有结束的事务会阻止 MDL。
更多细节,需要更多深入了解。
开发工具 Linux 终端 tmux
2019-03-21
从今天开始,打开 TeamViewer 就这样了。
商业用途
检测为商业用途
该软件似乎适用于商业环境。请注意:免费版仅供个人使用。
您的会话将在5分钟后终止。请登录我们的网站以获得更多信息。
商业用途
超时后连接将被阻断。
您的许可证对您与伙伴的最大会话时间有所限制,立即重新连接时将被阻断。请稍后再试或升级您的许可证。
与该伙伴的连接在07:33之前都将保持阻断。
我不喜欢下那些破解版软件,对原开发者来说,就是偷东西,总觉得有亏于人。
另一方面也不放心其安全性。
但是,这价格真心用不起。
新方案
需求
远程访问公司的工作机器
备选方案
不管什么方案,从两个内网机器想要实现通信,只能有一个双方都能连接的外网主机进行中转。
我对自己家的公网 IP 很久以前就绝望了,我打电话给电信要求分配公网 IP,之后他们说给我开了,然后我要求进入光猫最高权限,进去设置端口转发规则,不行。。。那要公网 IP 有捷豹用啊!
所以:
- 要么别个给免费的全套远程桌面访问解决方案(一般有些限制),比如行云管家
- 要么给免费的数据转发(一般也有些带宽之类的限制),或许附带专用软件。
只要能流畅使用终端,都可以接受。
在研究方案的过程中,发现了另一个好的选择:tmate.io。
tmate.io
这是 tmux 的分支。
tmux 我用过好一阵子,也很容易上手。
使用方法:
# 创建远程连接
tmate -S /tmp/tmate.sock new-session -d
# 显示 SSH 连接命令
tmate -S /tmp/tmate.sock display -p '#{tmate_ssh}'
思路
创建定时任务,定时检查并建立 tmate 连接,然后将 ssh 命令输出到文件里面。
文件位于我的坚果云文件同步目录 $HOME/Documents/Mine/
,这样我在任何地方都能通过 SSH 访问公司的电脑。
/etc/cron.d/tmate
SHELL=/usr/bin/zsh
* * * * * markjour [ -f $HOME/Documents/Mine/tmate.now ] && $HOME/Documents/Mine/tmate.sh && rm $HOME/Documents/Mine/tmate.now
~/Documents/Mine/tmate.sh
#!/usr/bin/zsh
tmate -S /tmp/tmate.sock kill-session
tmate -S /tmp/tmate.sock new-session -d
sleep 3
tmate -S /tmp/tmate.sock display -p '#{tmate_ssh}' > ~/Documents/Mine/tmate.conn
我在家只需要在同步目录下创建一个名为 tmate.now 的文件,一会儿就能用上 ssh 了。