最近经常用 IRC,发送大段文本和图片就成了刚性需求,然而现有的公共 Pastebin 和图床在管理上不太方便:

  1. 我希望删除得越早越好,这些资料本身就是临时的,根本不必要长期存储。
  2. 我不希望被其他人看到。网上现有的服务通常有一个 Recent,很容易读到别人发的消息。

出于这两点考虑,我打算自制一个支持代码和文本的 Pastebin。这也是本文标题的由来,「ownPaste」意味着这是属于我一人的 pastebin,我对其有充分的控制权。

思路

一开始我打算自己写一个 pastebin 服务器和客户端,并制定了详细的协议,但在写代码过程中,我发现很多功能其实对非公开使用场景是没用的,于是边写边砍,最后发现使用 scp 即可出色完成任务。现在的 Pastebin 由以下部分组成:

  1. 一个网站空间:存放文件
  2. GNU SourceHighlight:代码高亮
  3. scp:把文件传到服务器上

实现

定时删除

组合使用 crontabfind 即可。

在服务器上运行 contab -e,在打开的编辑器中输入:

0       *       *       *       *       /bin/sh /path/to/clean_pastes.sh

这意味着每小时 0 分执行一次 clean_pastes.sh。如果需要更细粒度的控制,可以把 0 也改成 *,这样每分钟都会检查一次。

运行 crontab -l 说明已经成功加入规则。运行 systemctl start crond 启动定时任务服务。

/path/to/clean_pastes.sh 中输入:

find /LOCAL/PASTE/ROOT/ -mtime +0 -type f >> deleted_pastes
find /LOCAL/PASTE/ROOT/ -mtime +0 -type f -delete

find 命令的 -mtime +0 参数用于找到 24 小时前修改的文件。第一行命令用来记录删除了哪些文件。

实际上还能用 -atime 参数找出多长时间没被访问过的文件,可以用来确保一段时间内访客不会遇到文件不存在的问题。

上传

要想方便地上传文件,首先应该启用 SSH 密钥登录(ssh-copy-id),避免每次上传都输入密码。

我使用 Fish shell,写了以下自定义命令,方便添加 paste:

function pastef --description "copy a file unmodified"
  scp $argv[1] vps:/LOCAL/PASTE/ROOT/
  echo "https://WEBSITE/PASTE_ROOT/"(basename $argv[1])
end

function pastesf --description "pastesf file lang"
  set fname (basename $argv[1])
  source-highlight -s $argv[2] -i $argv[1] -o /tmp/$fname.html
  pastef $argv[1]
  pastef /tmp/$fname.html
  unlink /tmp/$fname.html
end

function pastes --description "pastes lang"
  set fname (mktemp)
  cat >> $fname
  echo END OF INPUT
  pastesf $fname $argv[1]
  unlink $fname
end

function paste --description "paste plain text"
  pastes txt
end

后记

这次更深刻地体会到了不能着急动手,应该好好想想使用场景,免得做出来没用的东西,或者把简单东西复杂化。

不过想想「在另一个场景下怎么办」还是挺好的。比如说,我想给团队建立内部 pastebin,可能会出现如下需求:

  1. 不需要定时删除,而是在一定阶段后归档,因为这些资料要留下来,也许以后有用。
  2. 允许多人同时使用同一个 pastebin。
  3. 权限控制。允许部分人上传,允许部分人读取,并支持用户权限的调整。

这看上去与 ownPaste 有点矛盾,但还是可以作一些调整的(好吧,其实相当于推倒重来),比如归档功能可以写一个脚本,权限控制全部委托给 SSH 就行了,总之我们并不必要考虑太多,只要考虑当前使用场景即可。

当然更好的方法是搭建已有的开源 Pastebin 平台,这里就不再赘述了。