为废弃的openssl-1.0.2填坑 (.a转.so)

先吐个槽:话说php7已经大行其道,php8也开测了,某擎微平台却还运行在已经停止支持的php5上,而php5更是依赖了已废弃的openssl-1.0.x

帮小伙伴编译php5环境的时候,发现工具链已经无法很好的编译出openssl的lib库。编译出来的libcrypto.so竟然是0字节,其他文件均正常。调整各项参数,重新编译均无法解决。只好拿libcrypto.a开刀,反向编译出正确的.so文件。

ar -x libcrypto.a
gcc -shared *.o -o libcrypto.so
rm *.o

工作原理: .so文件是动态库文件,.a是有一系列.o 文件通过ar程序打包在一起的静态库,要把它转成动态库只需先解开,生成一堆.o文件,再通过编译器(gcc 或 ifort)编成动态库即可。

Gitlab 保存设置项目时提示500错误

将gitlab转为docker后,发现管理后台保存配置时提示500错误,查看日志/var/log/gitlab/gitlab-rails/production.log对应的错误信息为OpenSSL::Cipher::CipherError

查阅官方资料,得知是没有导入原来的加密信息/etc/gitlab/gitlab-secrets.json导致,重置下即可。

  • 进入控制台docker exec -it docker bash
  • 输入gitlab-rails console,等待进入rails控制台
  • 输入ApplicationSetting.current.reset_runners_registration_token!,显示结果为true
  • 再次尝试保存操作,已正常

如果项目设置也不正常,需进入DB控制台清理更多的Token设置,请参阅官方文献:
https://docs.gitlab.com/ee/raketasks/backup_restore.html#when-the-secrets-file-is-lost

快速创建TLS证书并部署到Docker服务

将下方代码保存为certbot.sh,修改头部变量后,上传到装有openssl组件的linux服务器上运行即可。

#!/bin/sh
#

export PASSWORD="密码"

export COUNTRY="CN"
export STATE="省"
export CITY="市"
export ORGANIZATION="公司名称"
export ORGANIZATIONAL_UNIT="Dev"
export COMMON_NAME="域名"
export EMAIL="电子邮件地址"

export HOST_NAME="$COMMON_NAME"
export IP=`ping $HOST_NAME -c 1 | sed '1{s/[^(]*(//;s/).*//;q}'`

export DIR="cert-$HOST_NAME"

# Workspace

[ -d $DIR ] || mkdir -p $DIR

echo "PASSWORD: $PASSWORD" > $DIR/!nfo.txt
echo "HOST_NAME: $HOST_NAME" >> $DIR/!nfo.txt
echo "HOST_IP: $IP" >> $DIR/!nfo.txt

# Generate CA

openssl genrsa -aes256 -passout "pass:$PASSWORD" -out "$DIR/ca-key.pem" 4096

openssl req -new -x509 -days 3650 -key "$DIR/ca-key.pem" -sha256 -out "$DIR/ca.pem" -passin "pass:$PASSWORD" -subj "/C=$COUNTRY/ST=$STATE/L=$CITY/O=$ORGANIZATION/OU=$ORGANIZATIONAL_UNIT/CN=$COMMON_NAME/emailAddress=$EMAIL"

# Generate Server Certs

openssl genrsa -out "$DIR/server-key.pem" 4096

openssl req -subj "/CN=$HOST_NAME" -sha256 -new -key "$DIR/server-key.pem" -out $DIR/server.csr

echo "subjectAltName = DNS:$HOST_NAME,IP:$IP,IP:127.0.0.1" > $DIR/server.cnf
echo "extendedKeyUsage = serverAuth" >> $DIR/server.cnf

openssl x509 -req -days 3650 -sha256 -in $DIR/server.csr -passin "pass:$PASSWORD" -CA "$DIR/ca.pem" -CAkey "$DIR/ca-key.pem" -CAcreateserial -out "$DIR/server-cert.pem" -extfile $DIR/server.cnf

# Generate Client Certs

openssl genrsa -out "$DIR/client-key.pem" 4096

openssl req -subj '/CN=client' -new -key "$DIR/client-key.pem" -out $DIR/client.csr

echo "extendedKeyUsage = clientAuth" > $DIR/client.cnf

openssl x509 -req -days 3650 -sha256 -in $DIR/client.csr -passin "pass:$PASSWORD" -CA "$DIR/ca.pem" -CAkey "$DIR/ca-key.pem" -CAcreateserial -out "$DIR/client-cert.pem" -extfile $DIR/client.cnf

# Modify Certs Permission

chmod 0400 $DIR/*-key.pem
chmod 0444 $DIR/ca.pem $DIR/*-cert.pem

# Remove Temporary Files

rm -f $DIR/*.csr $DIR/*.cnf

如果需要部署到Docker服务,请继续

# Install To Docker Daemon

mkdir -p /etc/docker/certs.d
cp $DIR/ca.pem /etc/docker/certs.d/
cp $DIR/server-*.pem /etc/docker/certs.d/

cat <<EOF >/etc/docker/daemon.json
{
    "tlsverify": true,
    "tlscacert": "/etc/docker/certs.d/ca.pem",
    "tlscert": "/etc/docker/certs.d/server-cert.pem",
    "tlskey": "/etc/docker/certs.d/server-key.pem",
    "hosts": ["tcp://0.0.0.0:2376", "unix:///var/run/docker.sock"]
}
EOF

# Modify Systemd Service

if [ -f /lib/systemd/system/docker.service ]; then
    sed -i 's#\["tcp:#\["fd://", "tcp:#' /etc/docker/daemon.json
    sed -i 's# -H fd://##' /lib/systemd/system/docker.service
    systemctl daemon-reload && systemctl restart docker
fi

特别注意

在systemd系统上-H已设置,因此无法使用hosts键来添加侦听地址,请参阅 https://docs.docker.com/install/linux/linux-postinstall/#configuring-remote-access-with-systemd-unit-file

修复PowerShell和服务器管理器

今天手残,把家里服务器的PowerShell给卸载了,结果悲催的发现服务器管理器也跟着消失了。查阅微软文档,得知如下修复方式,特此记录:

@echo off

:: .Net Framework 4.x
Dism /online /enable-feature /all/ featurename:Netfx4

:: PowerShell & PowerShellISE
Dism /online /enable-feature /all /featurename:MicrosoftWindowsPowerShell
Dism /online /enable-feature /all /featurename:MicrosoftWindowsPowerShellISE

Debian9/10 启用 Google BBR 加速

一、加载BBR内核模块

lsmod | grep bbr

如果回显tcp_bbr 20480 14则表示已加载,否则请使用如下命令加载BBR内核模块

modprobe tcp_bbr
echo "tcp_bbr" | tee -a /etc/modules-load.d/modules.conf

二、启用BBR网络优化

sysctl net.ipv4.tcp_available_congestion_control

如果回显net.ipv4.tcp_available_congestion_control = bbr cubic reno则表示已启用优化,否则请使用如下命令启用BBR网络优化

echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
sysctl -p

PHP版百度云加速API/SDK封装

<?php

/**
 * Author: anrip <https://www.arnip.com>
 * Update: 2020-1-8
 */

class Yunjiasu
{
    private $api_base = 'https://api.su.baidu.com/';

    private $access_key = '123456';
    private $secret_key = 'abcdef';

    public function zones($data)
    {
        $path = 'v31/yjs/zones';
        return $this->api_call('GET', $path, $data);
    }

    public function purge_cache($id, $data)
    {
        $path = 'v31/yjs/zones/' . $id . '/purge_cache';
        return $this->api_call('DELETE', $path, $data);
    }

    private function api_call($method, $path, $data = NULL)
    {
        $url = $this->api_base . $path;
        $header = $this->api_header($path, $data);
        $result = $this->http_repuest($method, $url, $header, $data);

        if (!empty($result['errors'])) {
            $error = array_pop($result['errors']);
            $error['error'] = 1;
            return $error;
        }

        if (!empty($result['result'])) {
            return $result['result'];
        }

        if (!empty($result['success'])) {
            return ['success' => 1];
        }

        return $result;
    }

    private function api_header($path, $data = NULL)
    {
        $params = [
            'X-Auth-Access-Key' => $this->access_key,
            'X-Auth-Nonce' => uniqid(),
            'X-Auth-Path-Info' => $path,
            'X-Auth-Signature-Method' => 'HMAC-SHA1',
            'X-Auth-Timestamp' => time(),
        ];

        if (is_array($data)) {
            ksort($data);
            $params = array_merge($params, $data);
        }

        $header = $signls = [];

        foreach ($params as $k => $v) {
            if (is_bool($v)) {
                $v = $v ? 'true' : 'false';
            }
            if (is_array($v)) {
                $v = str_replace('","', '", "', json_encode($v, JSON_UNESCAPED_SLASHES));
            }
            if (strpos($k, 'X-Auth') === 0) {
                $header[] = $k . ':' . $v;
            }
            if ($v !== '') {
                $signls[] = $k . '=' . $v;
            }
        }

        $header[] = 'X-Auth-Sign:' . base64_encode(
            hash_hmac('sha1', implode('&', $signls), $this->secret_key, true)
        );

        return $header;
    }

    private function http_repuest($method, $url, $header = NULL, $body = NULL)
    {
        $ch = curl_init();

        if ($method == 'GET' && $body) {
            $url .= '?' . http_build_query($body);
            $body = NULL;
        }

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);

        if ($header) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        }

        if ($body) {
            if (is_array($body)) {
                $body = json_encode($body);
            }
            curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
        }

        $result = curl_exec($ch);
        $errno = curl_errno($ch);
        $error = curl_error($ch);

        curl_close($ch);

        if ($errno) {
            return ['error' => $errno, 'message' => $error];
        }

        return json_decode($result, true);
    }
}

#######################################################################

$su = new Yunjiasu();

$rs_zones = $su->zones(array(
    'name' => 'anrip.com'
));

if (isset($rs_zones['error'])) {
    exit(json_encode($rs_zones));
}

print_r($su->purge_cache($rs_zones['id'], array(
    'files' => array('https://www.anrip.com/test.jpg')
)));

rsync多进程并发执行同步数据

原始命令

rsync -aPv --delete rsync://1.2.3.4/dp1/ /mnt/backup

多线程模式

#!/bin/sh
#

src='rsync://1.2.3.4/dp1' #源路径,结尾不带斜线
dst='/mnt/backup' #目标路径,结尾不带斜线

opt="-aPv --delete" #同步选项

num=16 #并发进程数
depth='5 4 3 2 1' #归递目录深度

task=/tmp/`echo $src$ | md5sum | head -c 16`
[ -f $task-next ] && cp $task-next $task-skip
[ -f $task-skip ] || touch $task-skip

# 创建目标目录结构
rsync $opt --include "*/" --exclude "*" $src/ $dst

# 从深到浅同步目录
for l in $depth ;do
    # 启动rsync进程
    for i in `find $dst -maxdepth $l -mindepth $l -type d`; do
        i=`echo $i | sed "s#$dst/##"`
        if `grep -q "$i$" $task-skip`; then
            echo "skip $i"
            continue
        fi
        while true; do
            now_num=`ps axw | grep rsync | grep $dst | grep -v '\-\-daemon' | wc -l`
            if [ $now_num -lt $num ]; then
                echo "rsync $opt $src/$i/ $dst/$i" >>$task-log
                rsync $opt $src/$i/ $dst/$i &
                echo $i >>$task-next
                sleep 1
                break
            else
                sleep 5
            fi
        done
    done
done

# 最终单进程验证
while true; do
    sleep 5
    now_num=`ps axw | grep rsync | grep $dst | grep -v '\-\-daemon' | wc -l`
    if [ $now_num -lt 1 ]; then
        echo "rsync $opt $src/ $dst" >>$task-log
        rsync $opt $src/ $dst
        break
    fi
done

制作MacOS启动U盘

真是好记性不如烂笔头啊,以前经常用的命令,一时竟然没想起来

sudo /Applications/Install\ macOS\ Mojave.app/Contents/Resources/createinstallmedia --volume /Volumes/your-disk-name /Applications/Install\ macOS\ Mojave.app —nointeraction

PostgreSQL 更改库及所有表的所有者(OWNER)

  • database, public,schema1 为你需要修改的库名
  • username 为更改后的所有者用户名
\c database;

DO $$
DECLARE
    r record;
    i int;
    v_schema text[] := '{public,schema1}';
    v_new_owner varchar := 'username';
BEGIN
    FOR r IN
        SELECT 'ALTER TABLE "' || table_schema || '"."' || table_name || '" OWNER TO ' || v_new_owner || ';' AS a FROM information_schema.tables WHERE table_schema = ANY (v_schema)
        UNION ALL
        SELECT 'ALTER TABLE "' || sequence_schema || '"."' || sequence_name || '" OWNER TO ' || v_new_owner || ';' AS a FROM information_schema.sequences WHERE sequence_schema = ANY (v_schema)
        UNION ALL
        SELECT 'ALTER TABLE "' || table_schema || '"."' || table_name || '" OWNER TO ' || v_new_owner || ';' AS a FROM information_schema.views WHERE table_schema = ANY (v_schema)
        UNION ALL
        SELECT 'ALTER FUNCTION "' || nsp.nspname || '"."' || p.proname || '"(' || pg_get_function_identity_arguments(p.oid) || ') OWNER TO ' || v_new_owner || ';' AS a FROM pg_proc p JOIN pg_namespace nsp ON p.pronamespace = nsp.oid WHERE nsp.nspname = ANY (v_schema)
        UNION ALL
        SELECT 'ALTER DATABASE "' || current_database() || '" OWNER TO ' || v_new_owner
    LOOP
        EXECUTE r.a;
    END LOOP;
    FOR i IN array_lower(v_schema, 1)..array_upper(v_schema, 1)
    LOOP
        EXECUTE 'ALTER SCHEMA "' || v_schema[i] || '" OWNER TO ' || v_new_owner;
    END LOOP;
END
$$;