TimothyQiu's Blog

keep it simple stupid

荫穴源码阅读小记

2 Comments

阅读一下某源代码,学习一些 Python 的基本知识 = =

注意:以下内容均为 Python 基础知识笔记,几乎都可以通过上述途径获得。

阅读剩余部分...

C++11 Variadic Template

No Comments

听说这个特性是很久以前了,总是读作「维拉迪克·坦普雷特」,一直没反应过来中文到底该叫什么,因为 C 时代的 Variadic Macro 我一直是很象形地读作「点点点」的 = =||

OK,扯远了。Variadic Template 对应中文应该是「可变参数模板」。

阅读剩余部分...

各式乱码

2 Comments

烫烫烫与屯屯屯

这两个乱码应该是不少 C/C++ 程序员的必经之路吧。

微软 Visual C++ 的 Debug 模式下,会为未初始化的内存填充一些初始值,以便调试。其中,栈上的内存都用 0xCC 初始化、堆上的内存都用 0xCD 初始化。

而如果把 0xCCCC 作为字符输出,在简体中文的 Windows 系统下,就会根据其使用的 GBK 编码将其解释为「烫」字;0xCDCD 则为「屯」。

变巨

如果你用过南极星,说明你已经老了。

在那个万码奔腾的年代,由于早年的《曹操传》和《三国志》等游戏使用的都是 Big5 编码的文本数据,而简体中文 Windows 系统使用的编码不同于 Big5。用「前朝的剑斩本朝的官」就产生了乱码。

「变巨」的 GBK 编码为 B1E4 BEDE(GB2312 亦然),而在 Big5 编码中这四个字节对应的汉字为「曹操」。

俸俸伲购美病

这是《英雄传说VI 空之轨迹SC》简体中文版中的一句对白,也是最初被玩家讽刺得最惨的地方。

打上官方修正补丁后可以发现原文为「嘿嘿嘿,还好啦。」之所以会产生这样的乱码是因为 GBK 编码:

BA D9 BA D9 BA D9 A3 AC BB B9 BA C3 C0 B2 A1 A3 // 嘿嘿嘿,还好啦。
   D9 BA D9 BA D9 A3 AC BB B9 BA C3 C0 B2 A1    // 俸俸伲购美病

缺了第一个字节……

锟斤拷

相对前面几个乱码的直白,这个乱码是很纠结的存在。

Unicode 中定义了一个特殊字符「�」即 U+FFFD,称作 Replacement Character。用来表示无法显示的字符或是无法解析的数据。

如果一段数据本身是使用 GBK 编码的,那么其中可能有很多部分不符合 UTF-8 编码规则。一个处理 UTF-8 数据的程序得到这段数据后,可以选择将数据中检测到不合 UTF-8 编码规则的部分替换为 UTF-8 编码的 U+FFFDEFBFBD,这样,就在自动消除编码问题的同时对用户给出了数据编码错误的提示。

经过上面这步处理后,数据中就产生了很多 EFBFBD 的序列,此时如果试图以 GBK 将其解码,那么两个这样的序列就成了「锟斤拷」,即 EFBF BDEF BFBD

自动备份

No Comments

我已经忘了上次备份服务器是什么时候的事了,只记得前不久因为「以为备份过」做错事然后手忙脚乱了。更考虑到自己邮箱那么多空间浪费着也是浪费着,于是就决定抽空写个脚本定期备份一下。

说是「自动」备份,其实一句话解释就是通过 cron 定期执行脚本,对需要备份的目录使用 tar 打包,然后 sendmail 发到邮箱。

这里的操作系统是 CentOS,其它系统应该也是大同小异。以下便是本次行动的流水帐 :)

Sendmail 相关

因为系统里原生没有安装 sendmail,于是

yum install sendmail   # 安装
service sendmail start # 启动服务
chkconfig sendmail on  # 开启自动启动

因为只想使用发信功能,所以也不用花时间改配置(收信功能的默认配置是只接受本地邮件)。确定防火墙允许 25 端口后,就可以使用下面的命令直接发送邮件了。

# 使用交互模式(使用只包含一个句点的行结束正文并发送)
mail <收件人>
# 命令行直接发送
echo <正文> | mail -s <主题> <发件人>

使用这种方法发出的邮件显示发件人地址为「<用户名>@<主机名称>」。因为 sendmail 只支持纯文本,所以需要借助 uuencode 来编码附件,于是:

# 只包含附件
uuencode <文件路径> <文件显示名称> | mail -s <主题> <收件人>
# 正文和附件
(echo <正文>; uuencode <文件路径> <文件显示名称>) | mail -s <主题> <收件人>

备份脚本

编写 Shell 脚本实现对 Web 目录的备份和发送工作,因为博客使用的是 SQLite 数据库,直接打包即可,不需要先用 mysqldump 导出。(新手上路,表示快被引号什么的弄疯了,于是大多数情况下都为变量加上了引号。另外邮件正文纯属无聊,完全可以不加 = =)

#!/bin/sh

# 备份文件存放目录
BACKUP_DIR="/path/to/backup/directory"

# 备份文件邮件接收地址
BACKUP_MAIL_RECEIVER="example@example.com"

# =====================================

# 保证目录存在
[ ! -d "$BACKUP_DIR" ] &&  mkdir -p "$BACKUP_DIR"

# 需要备份的路径
WEB_DIR="/path/to/web/root"

BACKUP_DATE="`date +%Y-%m-%d`"

BACKUP_FILE_NAME="$BACKUP_DATE.tar.gz"
BACKUP_FILE_FULLNAME="$BACKUP_DIR/$BACKUP_FILE_NAME"

cd $WEB_DIR
    tar czpf "$BACKUP_FILE_FULLNAME" *

BACKUP_MAIL_SUBJECT="VPS Backup: $BACKUP_DATE"
BACKUP_MAIL_MESSAGE=$(
    echo "Sir,";
    echo "";
    echo "Backup file $BACKUP_FILE_FULLNAME created.";
)

(echo "$BACKUP_MAIL_MESSAGE"; uuencode "$BACKUP_FILE_FULLNAME" "$BACKUP_FILE_NAME") \
    | mail -s "$BACKUP_MAIL_SUBJECT" "$BACKUP_MAIL_RECEIVER"

保存后给脚本加上执行权限,就可以直接运行试一下,应该会有邮件发到邮箱了。

chmod u+x <脚本名>

定时执行

定时执行肯定就是 cron 了,这个不用多说,直接 crontab -e 然后添加一行:

0 0 * * 2 /path/to/script

就大功告成鸟~从此,每周二午夜就会有一封谜之信件安静地躺到你的邮箱里……

Lua 学习笔记:协程

3 Comments

协程(coroutine)并不是 Lua 独有的概念,如果让我用一句话概括,那么大概就是:一种能够在运行途中主动中断,并且能够从中断处恢复运行的特殊函数。(嗯,其实不是函数。)

举个最原始的栗子

下面给出一个最简单的 Lua 中 coroutine 的用法演示:

function greet()
    print "hello world"
end

co = coroutine.create(greet) -- 创建 coroutine

print(coroutine.status(co))  -- 输出 suspended
print(coroutine.resume(co))  -- 输出 hello world
                             -- 输出 true (resume 的返回值)
print(coroutine.status(co))  -- 输出 dead
print(coroutine.resume(co))  -- 输出 false    cannot resume dead coroutine (resume 的返回值)
print(type(co))              -- 输出 thread

协程在创建时,需要把协程体函数传递给创建函数 create()。新创建的协程处于 suspended 状态,可以使用 resume 让其运行,全部执行完成后协程处于 dead 状态。如果尝试 resume 一个 dead 状态的,则可以从 resume 返回值上看出执行失败。另外你还可以注意到 Lua 中协程(coroutine)的变量类型其实叫做「thread」Orz...

乍一看可能感觉和线程没什么两样,但需要注意的是 resume() 只有在 greet() 以某种形式「返回」后才会返回(所以说协程像函数)。

函数执行的中断与再开

单从上面这个例子,我们似乎可以得出结论:协程果然就是某种坑爹的函数调用方式啊。然而,协程的真正魅力来自于 resumeyield 这对好基友之间的羁绊。

阅读剩余部分...