DuetG Blog

Keep It Simple, Stupid

  • 使用NTFS-3G在macOS上免费读写NTFS驱动器

    使用NTFS-3G在macOS上免费读写NTFS驱动器

    这是个救穷不救急的方法,如果着急用,建议还是花139块(或19.95刀)去买个Paragon NTFS for Mac。

    出于个人原因,突然需要从一台老iMac里拷贝出大量的文件,这让我本来就捉襟见肘的储存空间更加的雪上加霜。万般无奈下从京东买了块致态的500GB固态硬盘,把以前笔记本里的1TB机械硬盘换了出来。由于硬盘上本就还有数据,不能格式化,所以就只能在NTFS的文件系统下连接iMac了。

    众所周知macOS对NTFS是只读的,在“因为是个一次性的小需求所以不想花钱买软件”的指导思想下,我只得选择安装商业软件,并在试用期内把问题搞定。然而因为拖延症以及我对“数据读写也要耗时”这个事情从没有像这次一样直观的体验,令我在这台iMac上陆续装了三款免费试用的NTFS装载软件,并逐一都过了期。

    然而我的活儿却还没干完。

    思前想后,决定找一个完全免费的解决方案,通过搜索找到了NTFS-3G这样一款开源跨平台的NTFS驱动。不过想要在macOS上使用,还需要借助macFUSE才可以。下面写的基本上来自于macFUSE官方Wiki上有关NTFS-3G的指导。如果英语不错的话,也可以直接去看原文。

    首先由于需要编译,所以你需要在Mac上安装Xcode,确保Command Line Tools安装到系统。如果没有的话可以在终端里使用这条命令:

    sudo xcode-select --install

    接下来需要安装Homebrew来在终端里实现软件包的安装和管理。

    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

    较低版本的macOS是无法通过官网的 .pkg 包完成安装的,会验证你的系统版本,所以用命令行安装是比较稳妥的方式,虽然也会提示版本低,但不会终止安装。

    接下来安装macFUSE,这个直接到官网下载最新的安装包就可以了,目前最新的是macFUSE 4.5.0,注意安装完成后请务必重启系统。

    以上准备工作完成后,就可以照着官网Wiki上写的按步骤操作了。其间会有下载和编译的过程,终端窗口不会有任何进度提示,还请耐心等候。

    首先是从Homebrew安装NTFS-3G

    brew tap gromgit/homebrew-fuse
    brew install ntfs-3g-mac

    完成之后插上你的NTFS移动硬盘,macOS识别后在终端使用以下命令查找硬盘分区的名称(如/dev/disk1s1)

    diskutil list

    确定之后就可以手动挂载NFTFS分区了,注意把下面命令中的/dev/disk1s1更换成你硬盘实际分区的名称

    # 还没弹出移动硬盘的话要先把分区卸载掉
    sudo diskutil unmount /dev/disk1s1
    # 再用 ntfs-3g 挂载硬盘
    sudo mkdir /Volumes/NTFS
    sudo /usr/local/bin/ntfs-3g /dev/disk1s1 /Volumes/NTFS -o local -o allow_other -o auto_xattr -o auto_cache
    # 或者上条命令也可以换成下面这条
    sudo /usr/local/sbin/mount_ntfs /dev/disk1s1 /Volumes/NTFS

    代码输入之后,桌面上应该就会显示出来新挂载的NTFS硬盘了,名字会变成NTFS-3G相关的名字,但内容是没错的。打开之后就可以写入数据了。不用的时候点右键推出就好,再用的时候再用命令来挂载。

    至于自动挂载,官方Wiki也给了方法。但由于大多数情况用的还是移动硬盘来回拷贝文件,而不是台式机内多挂了一个硬盘,所以在这里就不再详述了,有需求的直接去Wiki查阅就好。

  • 数据考古其乐无穷

    数据考古其乐无穷

    一直以来都觉得自己记忆力非常不错。刚开始写Blog那会儿,总是喜欢隔段时间写一篇“谈谈这个Blog”之类的文章,讲讲建站之辛苦,无法访问之无奈。后来这些个烦恼竟也渐渐忘记了,就不再倒苦水了。

    这个Blog从最初在Blogger上利用第三方服务器发布绕过对blogspot的封锁开始,到最终落回到了家里服务器自托管Wordpress为止。其间经历了512j.com(我要安家)、Sitesled.com、Dreamhost.com合租(那会儿还没有“拼车”这个用法)、Linode.com、Oracle Cloud,最后是家里的VMware ESXi等诸多托管。

    当然上面说的这些要不是因为最近的数据考古,我其实也都忘个差不多了。与其美其名曰数据“考古”,不如说是翻数据垃圾。这么些年,我每当要重装系统或者是对C盘有什么大动作,总要把C盘重要的文件复制到后面的盘符里,再建一个名叫“C”的文件夹存好。有时候顾不上改名,就干脆保持着“新建文件夹”的名字存上就好。再后来又有了“新建文件夹 (2)”、“新建文件夹 (3)”、“新建文件夹 (4)”……这方面我目前的记录是“新建文件夹 (14)”。然后当我打开“新建文件夹 (6)”的时候,发现里面还有另一套7、8、9、10。八成是因为我嫌太多了,所以压缩了一下,把目录从并列变成嵌套了:眼不见为净。

    忘了96、97年刚用电脑那会儿是谁说的:不要在根目录放过多的零碎文件。我一直讲这句话当作圣经,但凡看到有零碎文件在根目录上,总想新建一个文件夹把它们放进去。于是这也成了文件夹变多的理由之一。

    最近一个机缘巧合,让我不得已要把硬盘上的数据转移出去。借着这个机会,我决定好好检视一下这些文件夹里到底有什么有价值的文件。不过几乎都是垃圾文件,可谓是沙里淘金了。

    先是用搜索把png、jpg搜了一通,果不其然,竟然在很古早的QQ聊天记录文件夹里找到了一些本没有任何存档的、仅在聊天时候传递和接收过的照片。里面有本地Buzzer第一次聚会的一些照片,实在是太难得了。算算已经有十几年了,那次聚会我还没去成。

    除了照片,更有价值的是我曾经拖过早期在Blogger上做的Blog的全站文档。里面有那个Blog主题所需要的图片文件。这些图片原本我是直接引用Gmail上的,后来Gmail界面升级,这些图片作为没有用的缓存还在服务器上留了一阵子,我没在意,等想起来的时候Google已经把这些图片删掉了。于是Blogspot上的这个Blog主题基本崩坏了很多年,直到这次我找到了这份珍贵的全站数据,甚至还有05年我最早的两篇文章。由于Blog来回搬家,最初的数据都删除了,所以一直为之前失去的Blog数据感到惋惜。不过这次我终于有了从05年开始写Blog的证据,也算是对自己的起点有了一个准确的交待。

    找到的照片用手机备份到了Google相册,找到的主题图片也专门做了个Nginx服务补回到了主题里。又把主题重新整理了一下,把失效的连接(主要是Live Spaces)都注释掉,把页面也调宽了些。毕竟05年那会儿大家都还1024×768,800的页宽就刚刚好了。

    于是乎Blogger上的Duet G. Blog就重生了,曾经时髦的Gmail风格主题,现在居然变成了复古的代表,还真是有意思了。用IFTTT把Wordpress和Blogger连在一起,以后这两个同步更新。之前的文章全都撤回了,算是一个新的开始吧。

  • 使用WebP Server Go优化网站图片

    使用WebP Server Go优化网站图片

    之前介绍了使用WebP Cloud Services的公共服务做代理让Gravatar的头像能在大陆正常访问的方法。

    设置好之后就决定想尝试一下他们的图片服务。但是官方制作的Wordpress插件着实用起来不顺手:只能将正文里本地图片的地址替换成代理地址,但特色图片却不能替换。要知道像2023这种官方主题,如果文章里不怎么插入图片的话,特色图片反而是页面加载数据量的大头。自行修改插件失败之后,我决定寻找替代的方案。

    按照官方插件作者的Blog我找到了WebP Cloud Services后端使用的开源程序WebP Server Go。开源代码和付费服务其实是一个作者。研究了一下GitHub上的README.md以及官网的文档,用Docker很快就部署完成了。简单修改了一下Nginx的配置文件,Blog页面的加载速度果然快了不少。特色图片用的大分辨率的图果然影响了不少速度啊。

    简单说一下部署流程和注意事项,默认你要加速的也是Wordpress,并且服务器里已经装好了Docker。

    首先建立一个工作目录,并且在里面创建一个 docker-compose.yml

    version: '3'
    
    services:
      webp:
        image: webpsh/webp-server-go
        # image: ghcr.io/webp-sh/webp_server_go
        restart: always
        environment:
          - MALLOC_ARENA_MAX=1
        volumes:
          - ./path/to/pics:/opt/pics  #./path/to/pics 改成你的Wordpress目录
          - ./exhaust:/opt/exhaust
          - ./metadata:/opt/metadata
        ports:
          -  127.0.0.1:3333:3333
        deploy:
          resources:
            limits:
              memory: 400M
        memswap_limit: 400M

    假设你的图片和网站路径有着这样的对应模式:

    图片路径

    /var/www/duetg.com/path/demo.jpg

    网站路径

    https://duetg.com/path/demo.jpg

    那么docker-compose.yml里的 ./path/to/pics 就应该改成 /var/www/duetg.com

    exhaust 和 metadata 会自动在工作文件夹中生成,exhaust 文件夹中包含已经转换完毕的图片缓存,以备下次请求的时候直接使用。这两个文件夹也可以自行定义位置。

    Docker Compose文件写好保存退出后,就可以拉取镜像创建容器了

    docker compose up -d

    接下来我们修改Nginx配置文件。原理很简单,在 server 块里新建一个 location,运用反向代理把和图片相关的请求直接转到Docker容器映射的3333端口就好。location 有两种写法,一种是直接指定到Wordpress的图片附件文件夹

    location ^~ /wp-content/uploads/ {
        proxy_pass http://127.0.0.1:3333;
    }

    还有一种是在整个目录里用正则表达式过滤和图片相关的文件扩展名

    location ~* \.(?:jpg|jpeg|gif|png)$ {
        proxy_pass http://127.0.0.1:3333;
    }

    如果你还使用了Cloudflare之类的CDN加速,你需要让CDN服务器知道这些图片不缓存,所以还要在 location 块里再加上下面这行

    location ~* \.(?:jpg|jpeg|gif|png)$ {
        add_header Cache-Control 'private';
        proxy_pass http://127.0.0.1:3333;
    }

    由于WebP Server Go会自动拒绝原本已经是WebP图片的转换请求,导致返回是空值,如果你的网站已经有一部分WebP图片了,建议还是用按扩展名过滤的方法来向服务请求图片转换更好。

    使用自托管的WebP转换服务和使用云服务相比,优点除了有免费且不限量外,其实更重要还在于网页里的图片引用地址不会被更改,这点也是我所看中的。

    完

  • 使用Cloudflare Tunnel通过标准http(s)端口访问内网服务器

    使用Cloudflare Tunnel通过标准http(s)端口访问内网服务器

    其实访问内网服务器本身就是隧道的功能之一,这并没有什么可多说的。但Cloudflare Tunnel的优势在于,不但能够内网穿透,还可以为原本不具备使用标准http(s)端口的服务(如国内的家庭宽带)增加标准端口访问。当然还有Cloudflare提供的其他付费免费的安全功能和加速功能就不细说了。

    大多数人用家宽架设服务器的时候都会选择在路由器上用一个非标准的端口映射到内网的机器上。也许你内网的机器是标准的80或者443端口,但映射的时候只能给他随便挑个吉利(冷僻)的端口。再用DDNS把wan口获得的公网IP同步到DNS服务上。然后在浏览器的地址栏里敲上你的域名外加冒号和端口号,就能看到内网开的服务了。

    但是假如电信公司没给你公网IP呢?

    这时候用Cloudflare Tunnel就会非常方便了(其实有公网IP也可以用)。借官网的图来解释一下:

    通过加密隧道,你的内网资源与Cloudflare建立了访问通道,而Cloudflare又把资源映射到你托管在它上面的域名上,无视你是否有公网IP(因为资源是通过隧道访问的),也不管你是否是标准端口(因为域名在Cloudflare上托管,不管实际是什么端口,它只管从标准端口转发过去就好)。这样我们就实现了使用标准端口访问内网资源的目的。

    使用之前要弄明白一点:你的内网只要有一台机器和Cloudflare建立的Tunnel连接,且内网设备间互相访问是没有障碍的。那么你内网的所有机器都可以在Cloudflare上映射一个标准端口的域名,哪怕是一台空调或者一个冰箱。这个功能类似于Tailscale的路由功能。

    先选择一台机器作为与Cloudflare建立Tunnel的客户端。这里有几点建议。尽量不要选需要频繁切换代理的机器,因为Tunnel连接在切换代理的时候会断掉,而是否能够重新连上是不一定的,重启客户端是比较可靠的方法。但有时不一定能物理接触到那台机器,然而Tunnel又断了,很有可能就没办法处理了。其次尽量选择能够一直开机的服务器来部署,因为如果关机了整个内网都会无法访问。最后是把客户端安在路由器里是个不错的选择,但可能没有在某台机器上方便管理和调整。

    具体的安装可以部分参照少数派的《CloudFlare Tunnel 免费内网穿透的简明教程》

    由于我的域名目前已经在SNI/HOST黑名单,所以才会出现http协议映射后跳转https连接失败的情况。如果你的域名没问题,按照少数派的教程映射http是可以的。但如果你想用自己申请的证书,可以参考后面没有划线的文字。虽然少数派的教程算是详尽,但最后在“5. 配置域名和转发URL”环节是有一些表述上的问题的。如果是以http协议映射,即域名使用默认80端口访问,内网服务也是http协议,大多数情况是没有问题的,但请不要在域名SSL/TLS设置部分开启“始终使用 HTTPS”,否则会强行自动跳转https。可如果像少数派的教程所讲用https协议映射内网http端口的话,虽然Cloudflare能够给你一个免费的证书,但通过我的测试,在大陆网络环境下这种方式是无法访问到服务的,具体情况是浏览器会报无法获取证书的错。所以如果想要使用https,建议还是在本地服务器上配置证书,再用Nginx开启ssl监听端口(比如443),最后再以https协议在Cloudflare Tunnel中映射内网服务器的该端口,并且务必开启下方“Additional application settings”中“TLS”里的“No TLS Verify”开关,否则Cloudflare Tunnel会拒绝访问,返回502错误。

    至于如何在没有公网IP以及80端口的情况下为主机申请免费证书,建议使用acme.sh的DNS API功能。

    完

  • 使用WebP Cloud Services将Gravatar头像替换为WebP格式

    使用WebP Cloud Services将Gravatar头像替换为WebP格式

    WebP Cloud Services是一个创业服务型公司,提供付费API将图片转换成WebP格式供用户使用。除了收费服务外,他们也有免费账户可供选择体验,并且还提供免费的公共服务:将Gravatar以及GitHub头像转换成WebP格式。

    将头像替换成WebP格式除了能够加快图片加载的速度外,更重要的还是WebP Cloud Services的服务器在大陆范围能够被访问。这样一来就不会再出现直连无法显示头像的问题,加载网站的浏览器进度条也能够立即结束。

    根据官方文档给出的指南,可以在Wordpress主题的 functions.php 最下方添加钩子函数,实现在加载网站的时候将Gravatar的 https://www.gravatar.com/avatar/:hash 转换成他们自己的 https://gravatar.webp.se/avatar/:hash

    代码如下

    function use_webp_public_service($avatar) {
    	$avatar = str_replace(array("www.gravatar.com", "0.gravatar.com", "1.gravatar.com", "2.gravatar.com"), "secure.gravatar.com", $avatar);
        $avatar = str_replace("https://secure.gravatar.com", "https://gravatar.webp.se", $avatar);
    	return $avatar;
    }
    add_filter('get_avatar', 'use_webp_public_service');

    由于给主题开了自动更新,所以一开始我选择了使用子主题来增加这个函数,这样就不担心主题更新的时候把修改的内容覆盖掉了。但缺点是假如想换其他的主题,就还要再做一个对应的子主题,这样实在是太麻烦了。

    当然现在Wordpress有允许你执行代码片段的插件(如Code Snippets),但倘若只是为了这一个功能安装如此重量级的插件又觉得有些得不偿失了。于是还是把这个功能做成一个简单的插件来的更方便一些。本身代码也不多,更不需要更新什么,所以也就不选择发布到Wordpress.org了,需要的话可以在下方下载自行安装。

    考虑回头要不注册个免费账户,把Blog的图片也接入WebP Cloud Services吧。

    更新:已经在Blog上启用了。用起来也很简单,GitHub账号登录就可完成注册。官方为Wordpress提供了插件,并且在插件的页面上有详细的使用说明,按图索骥便可完成。如果是想通过Nginx来实现的话,也可以在 server 块中添加用来替换图片地址的代码

    #把yyets.dmesg.app替换为你的原网址,vz4w427.webp.ee替换为webp.se提供给你的代理地址
    location / {
        sub_filter_once off;
        sub_filter_types text/html;
        sub_filter  '<img src="https://yyets.dmesg.app/' '<img src="https://vz4w427.webp.ee/';
        sub_filter  '<img src=https://yyets.dmesg.app/' '<img src=https://vz4w427.webp.ee/';
    
        sub_filter  '<img src="/' '<img src="https://vz4w427.webp.ee/';
    }

    再更新:鉴于官方的Wordpress插件不能加速文章的特色图片(外加自行修改无果),于是找到了WebP Cloud Services后端的开源代码WebP Server Go,自行在服务器上部署,这样一来所有图片就都自动变成WebP了。