跳转至

Recent Blog

database acronyms

常常被几个缩写搞晕,今天有空好好查了下。

CRUD 增删改查

web后端代名词,CREATE READ UPDATE DELETE

ACID 事物操作的四个特性

Atomic 原子性,一次事物包含多个操作,这些操作要么都成功,要么都失败。 Consistency 一致性 Isolation 隔离性,多个事物之间按优先级并发,互不影响 Durability 持久性,数据储持久化,存储在磁盘上而非内存中

CAP 分布式系统的不可能三角的定理

Consistency 一致性,保证所有节点的数据状态都一致 Availbility 可用性,保证能对外服务 Partition tolerance 分区容忍性,可以接受系统出现分区,俗称脑裂。

CAP是被证明的定理,不可能三角表示同时最多只能保证两个,而不能保证三个。三种情况解释如下: 1. 多节点的系统不能保证没有故障,就需要系统能接受系统出现分区(脑裂)。当出现分区时,需要从C一致性和A可用性中二选一,当选择一致性时,就放弃可用性。因为网络有分区无法保证查询信息是一致的,所以请求将返回失败。 2. 当选择可用性时,系统将每次都尝试返回最新的结果,即使由于分区导致数据不一定是最新的。 3. 而当没有出现分区时,可以同时保证一致性和可用性。

简而言之1保证了C+P,2保证了A+P,3保证了C+A

udp 查看统计的方法

  • /proc/net/snmp
  • /proc/net/udp

除此之外,还有通常使用netstat/ss 来查看发送队列和接收队列的缓冲区占用。

/proc/net/snmp

cat /proc/net/snmp | grep Udp\:
输出格式 Udp: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors

  • InDatagrams recvmsg调用时,值会增加。
  • NoPorts 发送到没有监听的端口,值会增加
  • InErrors 没有内存,或者checksum失败
  • OutDatagrams 成功发送到IP层,注意这不代表包成功发送出去了,因为在IP层可能有错误,比如路由错误,会导致IP层的OutNoRoutes值增加

/proc/net/udp

cat /proc/net/udp
输出格式 sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops

  • sl hash slot for the socket
  • local_address 16进制的ip.端口
  • st socket state
  • tx_queue 发送队列的内存大小
  • rx_queue 接收队列的内存大小
  • inode socket对应的inode,可以判断哪个进程打开了这个socket
  • drops 只记录了接收方向被丢掉的包,不包括发送方向丢掉的包。

参考

https://blog.packagecloud.io/monitoring-tuning-linux-networking-stack-sending-data/#monitoring-udp-protocol-layer-statistics

Linux创建热点

iptables 用来配置转发数据包规则的工具,Linux的防火墙配置就是利用的iptables。普通的路由器也是使用的iptables来实现NAT地址转换。

使用iptables转发流量

路由器使用的局域网ip,例如可使用的局域网有3类 * A类地址:10.0.0.0 - 10.255.255.255 ==> 10.0.0.0/8 * B类地址:172.16.0.0 - 172.31.255.255 ==> * C类地址:192.168.0.0 -192.168.255.255 ==> 192.168.0.0/16

公网访问路由LAN,常见防火墙后的服务器

假设公网客户(8.8.8.8)访问路由器下的服务(192.168.0.2)。请求先到达路由的公网地址假设1.1.1.1, 此时的ip层源地址和目的地址分别为(8.8.8.8/1.1.1.1), 然后路由器需要将目的地址改写为192.168.0.2,此时ip包的地址为(8.8.8.8/192.168.0.2),这需要的iptable规则为

iptables -t nat -A PREROUTING -d 1.1.1.1 -j DNAT --to-destination 192.168.0.2
ip包就能正常到达192.168.0.2,处理完成之后,ip包变成(192.168.0.2/8.8.8.8),这是可能有几种情况: * 没有路由规则能匹配8.8.8.8,则会被丢弃。 * 一般会发送到默认网关,然后由网关发送正确发送到8.8.8.8,但8.8.8.8客户不认识源地址192.168.0.2,所以包会被丢弃 * 直接在第一个路由上被丢弃,因为192.168.0.2是一个私有地址,不能被转发。

所以需要另外一条iptables规则,将192.168.0.2发出的ip包改成(1.1.1.1/8.8.8.8)

iptables -t nat -A POSTROUTING -s 192.168.0.2 -j SNAT --to-source 1.1.1.1

Reference

https://serverfault.com/questions/627608/redirect-all-incoming-traffic-from-a-secondary-public-ip-to-an-internal-ip-addre

随身wifi工具刷机

本文记录了淘宝卖的随身wifi刷机成Debian,还能收发短信。还有救砖的艰辛过程,不过结局美满。

依赖

  • edl备份恢复工具,https://github.com/bkerler/edl, 下载源代码后执行git submodule update --init --recursivepip install -r requirements.txt
  • openstick编译好的debian https://github.com/OpenStick/OpenStick。 在release页面下载 base.zip, debian.zip, firmware-ufi001c.zip,boot-ufi001c.img
  • apt 安装 adb fastboot

切卡

刚接触时看网上的都是在后台页面切卡,但是刷机了没有后台页面如何切卡呢? 为了切卡又重刷安卓,导致变砖了。参考网上资料发现,Debian下可以直接切。

debian默认卡槽位1:

echo 1 > /sys/class/leds/sim:sel/brightness
echo 0 > /sys/class/leds/sim:en/brightness
echo 0 > /sys/class/leds/sim:sel2/brightness
echo 0 > /sys/class/leds/sim:en2/brightnessR
modprobe -r qcom-q6v5-mss
modprobe qcom-q6v5-mss
systemctl restart rmtfs
systemctl restart dbus-org.freedesktop.ModemManager1.service

esim槽位3:

echo 0 > /sys/class/leds/sim:sel/brightness
echo 0 > /sys/class/leds/sim:en/brightness
echo 1 > /sys/class/leds/sim:sel2/brightness
echo 0 > /sys/class/leds/sim:en2/brightness
modprobe -r qcom-q6v5-mss
modprobe qcom-q6v5-mss
systemctl restart rmtfs
systemctl restart dbus-org.freedesktop.ModemManager1.service

其他两个槽位

槽位2:

echo 0 > /sys/class/leds/sim:sel/brightness
echo 1 > /sys/class/leds/sim:en/brightness
echo 0 > /sys/class/leds/sim:sel2/brightness
echo 0 > /sys/class/leds/sim:en2/brightness
modprobe -r qcom-q6v5-mss
modprobe qcom-q6v5-mss
systemctl restart rmtfs
systemctl restart dbus-org.freedesktop.ModemManager1.service

槽位4:
echo 0 > /sys/class/leds/sim:sel/brightness
echo 0 > /sys/class/leds/sim:en/brightness
echo 0 > /sys/class/leds/sim:sel2/brightness
echo 1 > /sys/class/leds/sim:en2/brightness
modprobe -r qcom-q6v5-mss
modprobe qcom-q6v5-mss
systemctl restart rmtfs
systemctl restart dbus-org.freedesktop.ModemManager1.service

有些棒子esim槽位不一样槽位3不行自行试试槽位2 4
https://github.com/OpenStick/OpenStick/issues/49#issuecomment-1568202001

刷机

先使用edl全量备份,方法在最下面。先刷base包,解压base.zip后执行里面的flash.sh。然后刷debian包,解压debian.zip后执行里面的flash.sh。这时进入系统发现可能出现问题(我也没明显感觉到问题),因为他们是ufi001b的。 所以再刷适配ufi001c的包,解压firmware-ufi001c.zip。

cd firmware-ufi001c
adb push ./* /lib/firmware
adb reboot bootloader
fastboot flash boot boot-ufi001c.img
fastboot reboot
但是在刷ufi001c的包之前我能找到modem网络,刷完就没了,所以有了下面基带恢复的步骤。

基带

基带文件在随身wifi的modem分区,先用edl备份modem分区。当然下面介绍了edl全量备份,跳过了userdata,估计是root和home目录。

恢复基带文件

我在安装debian系统时,发现移动网络不可用,于是参考网上说的,将原始基带恢复后正常。 基带文件名为"modem.bin", edl全量备份后在dumps目录下。直接mount该文件,然后将modem.*和mba.mbn取出来,当发现刷机后发现移动网络不能使用时,重新拷回去就能用了。

sudo mount modem.bin /mnt
复制到firmware-ufi001c目录,覆盖之前的文件。
cp /mnt/modem.* .
cp /mnt/mba.mbn .

再次拷贝到wifi棒子的/lib/firmware目录, 配合再刷一次适配001C的boot文件。

adb push ./* /lib/firmware
adb reboot bootloader
fastboot flash boot boot-ufi001c.img
fastboot reboot #重启

然后就能找到modem网卡了。

重启modem

有时重刷了firmware,还是出现没有modem网卡的情况,也就是mmcli -m 0提示找不到modem设备的时候,需要执行下面的命令。或者直接等一会重启ModemManager

systemctl stop ModemManager
qmicli -d /dev/wwan0qmi0 --uim-sim-power-off=1 && qmicli -d /dev/wwan0qmi0 --uim-sim-power-on=1
systemctl start ModemManager

短信收发和转发邮件

下载两个python文件,地址 https://gitee.com/jiu-xiao/ufi-message。配置smtp.py中的邮箱信息,我使用的QQ邮箱登录,然后转发到另一个邮箱。开始发送不成功,修改后能发送了,内容如下。

#!python3

my_sender='@qq.com'
my_user='@hotmail.com'
server_address='smtp.qq.com'
server_port=465
server_passwd='' #填写qq邮箱授权码


import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
import datetime
import time

def mail(text):
    msg=MIMEText(text,'plain','utf-8')
    msg['From']=formataddr(["随身Wifi",my_sender])
    msg['To']=formataddr([my_user,my_user])
    msg['Subject']="转发 "+time.strftime("%H:%%M:%S %m/%d")

    server=smtplib.SMTP_SSL(server_address,server_port)

    server.login(my_sender,server_passwd)
    server.auth_plain()
    server.sendmail(my_sender,[my_user,],msg.as_string())
    server.quit()

然后就能写进crontab自动跑了。

救砖

edl使用

github上的开源工具,可以替代Windows那些高通工具,Miko,星海啥的。是我这Linux用户的福音,并且简单,windows常常失败。 使用edl工具之前要先重启到edl也就是9008模式,使用命令adb reboot edl,不需要按RST键。

备份:推荐第一种方式,第二种方式生成的一个文件刷到另一个设备失败,但是可以刷MiKo导出的单文件。

edl rl dumps --skip=userdata --genxml
or
edl rf flash.bin #单文件

恢复:

edl qfil rawprogram0.xml patch0.xml .

恢复分区

刷了debian后,分区会变,这样导致有些分区不存在所以无法刷回去。这里介绍下恢复分区的方法。不过上面的edl恢复应该不需要这个操作。

备份分区

./edl gpt . --genxml
备份后有两个文件,恢复时只用gpt_main0.bin文件,恢复分区命令
./edl w gpt gpt_main0.bin
打印分区来验证下

./edl printgpt

参考

https://forum.openwrt.org/t/uf896-qualcomm-msm8916-lte-router-384mib-ram-2-4gib-flash-android-openwrt/131712/160 https://www.kancloud.cn/handsomehacker/openstick/2636505

pve入门

lxc 配置

pve使用lxc来运行容器而不是docker。 docker对应的“镜像”概念在pve里叫模板(template),默认的pve容器模板是从官网下载,非常慢,可以替换成清华源。另外在模板列表里面的模板都是比较新的,老版本可以上清华源上找,例如centos7,然后通过url来上传,怎样都非常方便。

容器网络问题

有的容器模板没有安装红帽的NetworkManger,这导致创建容器时选择的DHCP网卡配置不会生效,即使给网卡设置静态ip也不行。有个解决办法是启动后再加一个静态ip的网卡,这样容器就有网络访问权限了,然后赶紧安装NetworkManger吧。

低版本容器启动不能进入console的问题

如果systemd的版本低于232,启动容器时pve提示:WARN: old systemd (< v232) detected, container won't run in a pure cgroupv2 environment!
也打不开控制台,只能通过在宿主机上执行 pct enter id来进入容器。网上有帖子说在容器里面执行软件更新后,可以恢复,也许是systemd版本更新了,但是这个方法不适用于centos7。最后只能通过修改宿主机的grub,修改启动参数:

#/etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="systemd.unified_cgroup_hierarchy=0 quiet"
再执行update-grub命令,最后重启宿主机后问题解决。

低版本容器问题

pve的容器ENTERPOINT都是/sbin/init,跟我现在公司的管理docker方式相同。 会启动systemd,包括sshd等,对于远程访问非常方便。但是版本低的容器启动时不仅无法进入控制台,而且不会启动systemd。手动使用systemctl启动sshd时会失败,因为dbus没有启动,而启动dbus也失败。总之新版本容器就不会有这个问题,总之要配置启动参数。

对于通过/sbin/init来启动sshd的方式值得讨论,因为通过在Dockerfile中设置ENTRYPOINT service ssh restart && bash也可以有相同的效果。而公司的大量容器都启动systemd时,会启动udev服务,这时硬件故障,直接导致宿主机卡死。

map directory to lxc container

pct set 110 -mp0 /srv/music,mp=/srv/music

虚拟机配置声音

我安装过一个win7的虚拟机作为测试环境用,而且需要使用音频,在添加音频网卡时,使用了SPICE驱动,会导致虚拟机无法启动,必须将显示器的驱动也改成SPICE。然而我使用remmina来远程访问这个虚拟机,听不到声音。 最后将音频驱动改为None,然后remmina的advance标签卡的Auido output mode设置Local就能听到声音了,虽然声音质量不佳,不过勉强能用!

参考

  • https://forum.proxmox.com/threads/solved-warn-old-systemd-v232-detected-container-wont-run-in-a-pure-cgroupv2-environment.114736/
  • https://stackoverflow.com/questions/25135897/how-to-automatically-start-a-service-when-running-a-docker-container/32179054#32179054

ibus-setup

这里记录下ibus的配置记录,重新安装了系统,默认安装的ibus。之前用的fcitx5还不错,不过都尝试下。遇到两个问题:

firefox里面单击选中的文字触发删除

之前安装的ibus-pinyin, 重新安装ibus-libpinyin后解决。参考

配置默认输入法

作为一名程序员,默认英文输入是基本素质,在fcitx5中强制的英文输入法是默认输入法。但ibus中不是,但可以通过dbus来修改。打开dconf-editor,依次找到dconf-editor -> desktop -> ibus -> general,直接修改preload-engines的用户定义顺序,engines-order会跟随变化。将ibus:us:en提到ibus-pinyin数组前面就可以了。参考

ibus 体验

ibus中的好像输入表情要容易些。

gnome 配置ibus

最近切换到gnome-wayland, 配置ibus花了挺多时间。问题跟网上说的什么locale无关,gnome中的locale文件是修改配置时自动更新的。最终无头无脑卸载了fcitx相关的东西,并且重装了ibus和ibus-libpinyin,然后可能是重启后成功。

libavcodec使用

记录ffmpeg的学习系列,这是关于AVCodecContext的部分。

sample_fmt

解码器avctx中的sample_fmt,是解码后的原始音频(PCM)采样格式,几乎所有的音频格式(amr,mp3)解码后都是PCM。但是采样格式可能不同,这个是由解码器来设定的。 具体在打开解码器的时候avcodec_open2, 需要传入解码解码avctx, 这个函数会调用解码器的init函数,从而将解码器的设定同步到avctx中。 对于编码器而言,这个值由是用户自己设置。如注释所说:

    /**
     * audio sample format
     * - encoding: Set by user.
     * - decoding: Set by libavcodec.
     */
    enum AVSampleFormat sample_fmt;  ///< sample format

所有的采样格式。因为工作需要解码amr, 先是自己基于opencore开发的,解码后是S16(即AV_SAMPLE_FMT_S16), 而用ffmpeg解码后是AV_SAMPLE_FMT_FLTP, 这样的话重采样一次,效率低。后来发现ffmpeg有两套amr解码实现,选择opencore版本就是S16了。

enum AVSampleFormat {
    AV_SAMPLE_FMT_NONE = -1,
    AV_SAMPLE_FMT_U8,          ///< unsigned 8 bits
    AV_SAMPLE_FMT_S16,         ///< signed 16 bits
    AV_SAMPLE_FMT_S32,         ///< signed 32 bits
    AV_SAMPLE_FMT_FLT,         ///< float
    AV_SAMPLE_FMT_DBL,         ///< double

    AV_SAMPLE_FMT_U8P,         ///< unsigned 8 bits, planar
    AV_SAMPLE_FMT_S16P,        ///< signed 16 bits, planar
    AV_SAMPLE_FMT_S32P,        ///< signed 32 bits, planar
    AV_SAMPLE_FMT_FLTP,        ///< float, planar
    AV_SAMPLE_FMT_DBLP,        ///< double, planar
    AV_SAMPLE_FMT_S64,         ///< signed 64 bits
    AV_SAMPLE_FMT_S64P,        ///< signed 64 bits, planar

    AV_SAMPLE_FMT_NB           ///< Number of sample formats. DO NOT USE if linking dynamically
};

docker network

记录一次docker的网络问题,以及学到的知识。

背景

公司用docker容器替代虚拟机来隔离,用来ssh登录以及运行不同的服务。容器连接了双网络,一个用来访问同宿主机上的容器,另一个用来从其他主机访问。

问题

宿主机重启之后,容器无法访问。需要手动改路由。

解决办法

每次修改路由麻烦,后面发现两个网络都是macvlan时,存在无法没有网络。

创建桥接物理网卡

这是需要指定parent为物理网卡,既然是桥接物理网卡,就能从其他宿主机访问了。

docker network create -d bridge   --subnet=10.9.3.0/24   --gateway=10.9.3.1   -o parent=ens39f0 public_net_bridge

docker network create -d macvlan  --subnet=10.9.3.0/24   --gateway=10.9.3.1   -o parent=ens39f0 public_net_macvlan
这两个由于使用的同一个网段/网卡,所以不可能同时存在。也许可以通过指定不同的ip-range来实现吗?

创建桥接虚拟网卡

这种网络就不能从非宿主机的其他主机访问,只能在同宿机下的容器之间访问。我称之为私有网络

docker network create -d bridge   private_net_bridge

docker network create -d macvlan  private_net_macvlan
这里没有指定网络地址

iperf测速

发现无论桥接物理网卡还是虚拟网卡,macvlan都要比bridge快

  • 私有网络 bridge 模式分别测得: 20.4 Gbits/sec 22.6 Gbits/sec 23.0 Gbits/sec macvlan 模式分别测得: 26.1 Gbits/sec 24.4 Gbits/sec 26.7 Gbits/sec

  • 桥接物理网卡 macvlan: 25.7 Gbits/sec 25.5 Gbits/sec 27.3 Gbits/sec bridge: 20.2 Gbits/sec 20.4 Gbits/sec 23.2 Gbits/sec

顺便说下容器连接多网络的方法

容器启动的时候,只能指定一个网络, 然后启动之后,可以通过命令来连接多网络,可以在启动时设置--restart=alway,这样重启主机后自动连接双网络

docker network connect private_net_bridge test_container

杂项

网络配置挺复杂,macvlan 下面还分 * Bridge mode, 就是常见的模式,走宿主机的网卡 * 802.1q trunk bridge mode, 先在物理网卡上创建子网卡

IPvlan

除了bridge macvlan之外,还有IPvlan, 这种模式下,所有的容器都使用相同的mac地址,所以如果容器使用dhcp来获取ip地址,则可能有问题。 访问其他容器时,可以配置来使用macvlan模式。

overlay

docker network driver 除了上面的三种模式之外,还有overlay, 用于连接不同主机的网络,可以跨宿主机访问容器。

宿主机网络类型

我通常会创建bridge并将物理网卡设为从卡,然后创建虚拟网桥,用于访问虚拟机。而除了bridge, 还有bond,另外还有team。总而言之,bridge可以使不同的虚拟机(client)使用网卡的虚拟化功能,而bond可以将不同的网卡绑定,实现负载均衡。如果两个网卡分别有1M带宽,那么bond后的网卡则有2M带宽。下面的链接先bonding,然后在bonding网卡上创建bridge网卡。参考

Linux下的邮件配置

这里记录Linux(debian)下如何使用Mutt查看邮件,用fetchmail接收邮件,用msmtp发送邮件以及使用maildrop来筛选邮件。与其他邮件客户端相比,如thunderbird,他们使用的在线登陆方式,没有下载邮件来离线访问。而mutt支持离线访问本地的邮件,也可以配置为访问邮件服务器,查看服务器上的邮件。 在线方式除了离线不可用的缺点之外,每次打开mutt需要登陆,非常慢。 我这里的配置是比较简陋,适合公司少量邮件的场景。又因为目前使用的Byobu-terminal终端,其邮件提醒是基于/var/mail/spool/$USER文件。邮件比较多或者附件比较大的话,相较于用文件夹来存储邮件,这种方式会比较慢。

软件安装

需要安装 fetchmail, maildrop, mutt

接收配置

在家目录下创建文件.fetchmailrc

poll imap.exmail.qq.com
  protocol IMAP
  user "example@example.com"
  password "password"
  keep
  #fetchall
  ssl

mimedecode
mda "/usr/bin/maildrop"
keep 方式不会删除服务器上的邮件。然后启动定时任务,自动检查新邮件
systemctl --user enable --now fetchmail.service

service 内容

# /usr/lib/systemd/user/fetchmail.service
# or any other location per man:systemd.unit(5)
[Unit]
Description=Fetchmail Daemon
Documentation=man:fetchmail(1)

[Service]
ExecStart=fetchmail --nodetach --daemon 300
ExecStop=fetchmail --quit
Restart=always

[Install]
WantedBy=default.target

发送配置

在家目录创建文件.msmtproc,填入发送的验证信息

defaults
auth           on
tls            on
tls_starttls off
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile        ~/.msmtp.log

# exmail
account        office
host           smtp.exmail.qq.com
port           465
from           example@example.com
user           example@example.com
password       password

mutt配置

由于我不想删除/var/mail/里面的邮件,这样才能在byobu-terminal中提醒,所以没有配置maildrop。最后需要配置mutt读取/var/mail/$USER。在家目录或者xdg配置目录(~/.config/mutt)创建文件.muttrc/muttrc

set spoolfile=/var/spool/mail/jimery
set header_cache=~/.cache/mutt
set send_charset="utf-8"

这样就能查看邮件了。 在mutt里面手动管理邮件,存档或者删除。

mutt使用

其实不用mutt, 直接用mail也可以,这个默认访问/var/mail/$USER,是Linux默认的邮件工具。 mutt能很方便调用msmtproc来发送邮件。

maildrop in Arch

又换回Arch了,发现maildrop在AUR里,而且还依赖好几个AUR, 而自己编译只依赖courier-unicode库。

  1. 下载courier-unicode源码
  2. ./configure --prefix=$HOME/.local --enable-shared=no --with-pic # 静态编译,指定安装到用户根目录
  3. make && make install # 必须安装否则编译maildrop的时候找不到这个库,即使指定路径也不行。
  4. 下载maildrop源码
  5. ./configure --prefix=/home/hst/.local --enable-shared=no # 静态编译,指定安装到用户根目录
  6. make
  7. 验证是静态链接的courier-unicode,确认ldd ./libs/maildrop/maildrop 里面没有'courier-unicode'

Arch里面创建用户时默认没有对应的邮箱文件,直接手动创建sudo touch "/var/spool/mail/$(whoami)", 还有chmod

neomutt

mutt 中浏览pdf等非text的附件时,mutt应该保存文件到指定目录,然后使用第三方软件打开的。但浏览器提示文件不存在。 用neomutt就能解决。

foxmail适配

Foxmail邮件subject的字符编码默认是GBK, 除非在设置里修改。 邮箱协议最初协议默认是ASCII收发subject。现代的大部分邮箱普遍使用UTF-8收发。 收和发不一致的问题,本应该像html那样,用content-type来显式表明发邮件一方使用的字符编码。
可是邮箱协议并没有为subject定义content-type字段, 只有MIME有方法设置content-type和charset。不过可以通过下面的方式为subject设置charset

Subject: =?charset?encoding?encoded-text?=

但是foxmail没有这么做,而是之间将GBK编码塞到了subject位置,所以乱码。

Date: Tue, 3 Feb 2026 10:24:34 +0800
From:
To:
Cc: 
Subject: »Ø¸´: Èý·½Í¨»°²âÊÔÎÊÌâ-ÈýÐÇÖÕ¶ËͬÑù²¦²â³¡¾°Ò»´ÎÕý³££¬Ò»´ÎÈý·½¶¼Ã»ÓÐÉùÒô
References:
X-Priority: 3
X-GUID: 9BF12FA7-4B7A-4CC5-B07D-1B3C61294575
X-Has-Attach: no
X-Mailer: Foxmail 7.2.9.156[cn]
Mime-Version: 1.0
Message-ID:
Content-Type: multipart/related;
------=_002_NextPart574464278560_=----
Content-Type: text/plain;
        charset="GB2312"
Content-Transfer-Encoding: base64

解决办法:要么要求发件人修改foxmail配置,要么该收件人配置,在neomutt的配置增加set assumed_charset="gbk:utf-8"就能解决这个问题

安装wordpress记录

本文记录在debian上安装配置wordpress的补助,并配置了ftp功能,支持自更新wordpress。

安装wordpress

下载最新的包,解压到/var/www/html

安装配置数据库

安装mariadb, 创建数据库和用户

mysql -u root
CREATE DATABASE wordpressdb; 
CREATE USER wordpressuser@localhost IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON wordpressdb.* TO wordpressuser@localhost;

安装配置nginx php

安装nginx和php-7.4,还有php一些组件 nginx 配置

server { 
  listen 80 default_server; 
  listen [::]:80 default_server;
  server_name your_domain.com;

  root /var/www/html;
  index index.php index.html index.htm;

  location / {
    # try_files $uri $uri/ =404;
    try_files $uri $uri/ /index.php?q=$uri&$args;
  }

  location ~ \.php$ {
      include snippets/fastcgi-php.conf;
      fastcgi_split_path_info ^(.+\.php)(/.+)$;
      fastcgi_pass unix:/run/php/php-fpm.sock;
  }
}

安装配置vsftpd

安装后,修改配置文件/etc/vsftpd.conf

local_enable=YES
write_enable=YES
chroot_local_user=YES
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd.chroot_list
allow_writeable_chroot=YES
pm_service_name=ftp

添加用户,并限制权限

useradd [user_name]
passwd [user_name]
usermod -d /var/www/html/wordpress user_name -s /sbin/nologin

setfacl -m u:ftpsecure:r-x /var/www/html/

setfacl -R -m u:ftpsecure:rwx /var/www/html/wordpress
setfacl -R -d -m u:ftpsecure:rwx /var/www/html/wordpress
如果提示没有setfacl命令,则执行安装acl命令 apt install acl

ftp遇到问题和解决办法

  • 登陆提示"500 OOPS: could not read chroot() list file:/etc/vsftpd.chroot_list",需要创建文件/etc/vsftpd.chroot_list

  • 登陆ftp报530验证失败的问题,修改配置如下

    pm_service_name=ftp
    

  • 登陆提示"500 OOPS: vsftpd: refusing to run with writable root inside chroot()
allow_writeable_chroot=YES
  • 登陆提示 500 OOPS: vsftpd: refusing to run with writable root ,意思是登陆者具备对目录的写权限,这是由于目录设定权限为777,所以要是重新设定为755
    chmod 755 /srv/ftp
    

配置wordpress

修改wordpress/wp-config.php 文件, 添加如下内容

define('FTP_HOST', 'localhost');
define('FTP_USER', 'ftp');
define('FTP_PASS', '');
通过wordpress的api可以生成随机token,将输出替换到wordpress/wp-config.php

$curl -s https://api.wordpress.org/secret-key/1.1/salt/

define('AUTH_KEY',         'uOeyPW$K[P}23x^0l##N+qP#xzUlIBV[ZQlATs!7J?+5^!w0*bgEw|V6)k:YU0en');
define('SECURE_AUTH_KEY',  'Ad*-`eK|U4Z*7g}7CdX<q0^EuGqT1Tt}CaDRgF%NX-|fmk(:BACtws+^_0Pb8ZRA');
define('LOGGED_IN_KEY',    ':Z$}=h~z-[]8W}wZ(|/;]ZY;U{>u3K>P|u6/d:6}&h*);0ewhrcGm8$/tPii#{,%');
define('NONCE_KEY',        'd}Ue8.+KPDGdH^%2t~fTljDj8e{q{raR!Q0piqM(gcQP&7-$L3u0u|!Bn(-gh/?B');
define('AUTH_SALT',        'UQh.k>4UBTK6IecZe~lL6|J/w^KFROIeCdZw^g=(x?(L+j(-|%C FCt =V*XVz+k');
define('SECURE_AUTH_SALT', 'hHr&dDCApb14yz@ks+;}mk,s<-[]KUj*UAhl0+<pqT*!j;wxc+[mU[czh =><#em');
define('LOGGED_IN_SALT',   'WO,U^A||&:E@2A2_|MS W1l`fguj-7E{Fz6QkC+OM96Ho49<agM?O=G2FloxuF?6');
define('NONCE_SALT',       'uDN.1::MJ>~9Yp+e39y%o?r >:+OcUSqg5_g<Jt:Sr!um?U:U|MJ2q2qKiLDfmr@');

更新数据库配置到wp-config.php

更新url

开始使用http访问,后面切换到https后一直提示错误说跳转太多次。后来发现原因是套了cloudflare,cloudflare设置的是前端https后端http, 后端以http访问真实服务器后又跳转到https。所以请求一直在cf<->wordpress之间无限跳转。所以首先要设置cloudflare的代理模式为严格安全,strict full safe,也就是前端和后端都用证书。然后修改wordpress的url方法有很多,之前通过直接修改数据库,这次发现wordpress有个wp的命令行工具,一键修改。

vsftpd 配置默认目录

为local user配置默认目录,例如所有用户登录后进入/home目录, 添加配置local_root=/home,为匿名用户配置默认目录为tmp目录,则添加配置anon_root=/tmp

参考

https://serverfault.com/questions/544850/create-new-vsftpd-user-and-lock-to-specify-home-login-directory https://shiftedbits.org/2012/01/29/enable-wordpress-automatic-updates-on-a-debian-server/