最近在使用Golang集成虹软Linux SDK时,发现不能单纯的设置CGO_ENABLED=0,这样会导致C/C++库调用出错,无法完成正常的编译,因为你需要引入C/C++库的时候,不能禁用CGO。

而且虹软Linux SDK只能在Linux平台编译,macOS上缺少必须的glibc库,所以使用Docker是最好的方案,好在Docker社区的强大,几乎你需要的所有环境都有对应的官方镜像,这里推荐golang:alpine作为基础镜像,这个镜像包含了基础的Golang运行环境和可供编译C/C++的Linux环境,如果有缺少的参数可以自行添加。

为了减少最终镜像体积,可以分阶段构建,大概的Dockerfile如下:

# 使用基础镜像构建
FROM golang:1.15-alpine AS build
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN apk add libc6-compat libgcc libstdc++
ENV GO111MODULE=on \
    GOPROXY=https://goproxy.cn,direct \
    GOOS=linux \
    GOARCH=amd64
WORKDIR /build
COPY lib /usr/
COPY go.mod .
COPY go.sum .
RUN go mod download
COPY . .
RUN go build -o face
# 使用轻量化镜像运行减少体积
FROM scratch as final
ENV TZ=Asia/Shanghai
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=build /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=build /build/face /
COPY --from=build /build/.env /face.env
ENTRYPOINT ["/face"]

最近一个项目使用Docker来部署的,但每次手动部署都需要先把代码拉取到本地,然后在执行命令删除原来的容器和镜像,最后再部署,非常繁琐,所以直接把这些命令放在一个Shell脚本内,实现一键部署,代码如下:

# 指定代码目录
codePath="/root/";
# 接收输入,形如:  xxx.sh projectName
project=$1;
if [ ! -n "$1" ] ;then
  projectName="projectName";
fi
cd $codePath$projectName
echo "git pull start" ;
# 拉取最新代码
git pull origin master
echo "git pull finish" ;

echo "Docker build start" ;
# 停止容器、删除容器、删除镜像
docker stop app
docker rm app
docker image rm app
docker build . -t app
echo "Docker build finish" ;

echo "Docker deploy start" ;
# 开始部署
docker run -d --name app --network host --restart=always -v ~/app.env:/app.env app
echo "Docker deploy finish" ;

自此一个半自动部署脚本完成,后续有时间再把脚本和Jenkins集成到一起,就可以实现定时或者提交后自动部署了。

最近在使用Golang开发数据库操作过程中,涉及到PostgreSQL的主键自增长,一般在MySQL中可以使用AUTO_INCREMENT字段来实现主键自增长,语句如下:

CREATE TABLE IF NOT EXISTS `table_name`(
   `id` INT UNSIGNED AUTO_INCREMENT,
   `title` VARCHAR(100) NOT NULL,
   `author` VARCHAR(40) NOT NULL,
   `sub_date` DATE,
   PRIMARY KEY ( `id` )
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

但在PostgreSQL中无法使用AUTO_INCREMENT,经过查询得知PostgreSQL需要使用序列来标识字段的自增长,语句如下:

#先创建序列
CREATE SEQUENCE upms_id_seq START 1;

#主键赋默认值
CREATE TABLE "table_name" (
  "id" int4 NOT NULL DEFAULT nextval('upms_id_seq'),
  "title" varchar(100) NOT NULL,
  "author" varchar(40) NOT NULL,
  "sub_date" timestamptz,
  PRIMARY KEY ("id")
);

最近给服务器拷贝文件,由于文件较大,网络传输较慢,所以想到拿U盘拷贝,由于macOS、Windows、Linux系统之间文件格式互不兼容,所以搜了下哪种格式最适合,于是让我找到了UDF格式,具体的格式内容可以参考维基百科 - Universal Disk Format

由于各种Windows和macOS格式化会存在兼容问题,所以推荐在macOS或Linux环境下使用开源工具进行格式化
https://github.com/JElchison/format-udf
查看挂载硬盘,找到你那个U盘,形如/dev/sdb、/dev/disk2这样的,然后再执行格式化。

fdisk -l  #我电脑显示/dev/disk2,以disk2为例
./format-udf.sh /dev/disk2 "My UDF External Drive"

格式化以后,插入macOS和Windows会自动识别U盘,插入Linux系统需要新建个目录并执行挂载命令。

mkdir /mnt/usb
mount -t udf /dev/sdb /mnt/usb

使用完以后,macOS和Windows需要弹出U盘,Linux执行卸载命令才可以拔掉,否则会造成数据丢失。

umount /dev/sdb

背景

目前由于国内备案不支持 .im 域名,导致只能通过海外服务器中转+CDN加速的方式来达成访问,这样的情况下不管是CDN加速还是frp内网穿透,都会导致服务端无法直接获取到真实的IP地址。

思路

通过学习Typecho源码发现,在/var/Typecho/Request.php的 660 行左右,找到了setIp方法,这个方法主要是switch循环,先尝试从$this->getServer(__TYPECHO_IP_SOURCE__)中获取 IP,然后再尝试从$this->getServer('REMOTE_ADDR')中获取IP,而查看getServer相关的代码,发现基本功能就是获取$_SERVER内的相关变量。

解决

通过代码逻辑可以知道,这是官方提前预留出的获取IP地址的方式,显然也是最正确的做法,只要在配置文件提前定义好常量__TYPECHO_IP_SOURCE__的值,那么程序就会优先从这个对应$_SERVER的成员中获取值。
在配置文件/config.inc.php中添加:

/** 定义 IP 来源 */
define('__TYPECHO_IP_SOURCE__', 'HTTP_ALI_CDN_REAL_IP');

这时候后端就能获取到真是的IP地址了,统计工具插件也就可以工作了。

推荐一款Typecho类似于百度统计的本地统计插件Access,还是很好用的。