所有由Yanlongli发布的文章

给网站签发一个ssl证书,用于开发调试

有时候在开发时,想临时弄个自签证书用于开发调试,或者是开发公司网站时领导不给正式环境的ssl证书,就需要自己签发证书了。这是我再网上搜到的一个脚本。我是在Ubuntu环境下运行可以的。

https://gitee.com/yanlong-li/codes/roewbhnyd6laqm9cx80i431

#!/bin/bash -e

# * 为必改项
# * 更换为你自己的域名
CN='daohang.dev' # 例如: demo.rancher.com

# 扩展信任IP或域名
## 一般ssl证书只信任域名的访问请求,有时候需要使用ip去访问server,那么需要给ssl证书添加扩展IP,
## 多个IP用逗号隔开。如果想多个域名访问,则添加扩展域名(SSL_DNS),多个SSL_DNS用逗号隔开
SSL_IP='' # 例如: 1.2.3.4
SSL_DNS='*.daohang.dev,*.non0.com' # 例如: demo.rancher.com











# 国家名(2个字母的代号)
C=CN

# 证书加密位数
SSL_SIZE=2048

# 证书有效期
DATE=${DATE:-3650}

# 配置文件
SSL_CONFIG='openssl.cnf'

if [[ -z $SILENT ]]; then
echo "----------------------------"
echo "| SSL Cert Generator |"
echo "----------------------------"
echo
fi

export CA_KEY=${CA_KEY-"cakey.pem"}
export CA_CERT=${CA_CERT-"cacerts.pem"}
export CA_SUBJECT=ca-$CN
export CA_EXPIRE=${DATE}

export SSL_CONFIG=${SSL_CONFIG}
export SSL_KEY=$CN.key
export SSL_CSR=$CN.csr
export SSL_CERT=$CN.crt
export SSL_EXPIRE=${DATE}

export SSL_SUBJECT=${CN}
export SSL_DNS=${SSL_DNS}
export SSL_IP=${SSL_IP}

export K8S_SECRET_COMBINE_CA=${K8S_SECRET_COMBINE_CA:-'true'}

[[ -z $SILENT ]] && echo "--> Certificate Authority"

if [[ -e ./${CA_KEY} ]]; then
    [[ -z $SILENT ]] && echo "====> Using existing CA Key ${CA_KEY}"
else
    [[ -z $SILENT ]] && echo "====> Generating new CA key ${CA_KEY}"
    openssl genrsa -out ${CA_KEY} ${SSL_SIZE} > /dev/null
fi

if [[ -e ./${CA_CERT} ]]; then
    [[ -z $SILENT ]] && echo "====> Using existing CA Certificate ${CA_CERT}"
else
    [[ -z $SILENT ]] && echo "====> Generating new CA Certificate ${CA_CERT}"
    openssl req -x509 -sha256 -new -nodes -key ${CA_KEY} \
    -days ${CA_EXPIRE} -out ${CA_CERT} -subj "/CN=${CA_SUBJECT}" > /dev/null || exit 1
fi

echo "====> Generating new config file ${SSL_CONFIG}"
cat > ${SSL_CONFIG} <<EOM
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, serverAuth
EOM

if [[ -n ${SSL_DNS} || -n ${SSL_IP} ]]; then
    cat >> ${SSL_CONFIG} <<EOM
subjectAltName = @alt_names
[alt_names]
EOM
    IFS=","
    dns=(${SSL_DNS})
    dns+=(${SSL_SUBJECT})
    for i in "${!dns[@]}"; do
      echo DNS.$((i+1)) = ${dns[$i]} >> ${SSL_CONFIG}
    done

    if [[ -n ${SSL_IP} ]]; then
        ip=(${SSL_IP})
        for i in "${!ip[@]}"; do
          echo IP.$((i+1)) = ${ip[$i]} >> ${SSL_CONFIG}
        done
    fi
fi

[[ -z $SILENT ]] && echo "====> Generating new SSL KEY ${SSL_KEY}"
openssl genrsa -out ${SSL_KEY} ${SSL_SIZE} > /dev/null || exit 1

[[ -z $SILENT ]] && echo "====> Generating new SSL CSR ${SSL_CSR}"
openssl req -sha256 -new -key ${SSL_KEY} -out ${SSL_CSR} \
-subj "/CN=${SSL_SUBJECT}" -config ${SSL_CONFIG} > /dev/null || exit 1

[[ -z $SILENT ]] && echo "====> Generating new SSL CERT ${SSL_CERT}"
openssl x509 -sha256 -req -in ${SSL_CSR} -CA ${CA_CERT} \
    -CAkey ${CA_KEY} -CAcreateserial -out ${SSL_CERT} \
    -days ${SSL_EXPIRE} -extensions v3_req \
    -extfile ${SSL_CONFIG} > /dev/null || exit 1

if [[ -z $SILENT ]]; then
echo "====> Complete"
echo "keys can be found in volume mapped to $(pwd)"
echo
echo "====> Output results as YAML"
echo "---"
echo "ca_key: |"
cat $CA_KEY | sed 's/^/  /'
echo
echo "ca_cert: |"
cat $CA_CERT | sed 's/^/  /'
echo
echo "ssl_key: |"
cat $SSL_KEY | sed 's/^/  /'
echo
echo "ssl_csr: |"
cat $SSL_CSR | sed 's/^/  /'
echo
echo "ssl_cert: |"
cat $SSL_CERT | sed 's/^/  /'
echo
fi

if [[ -n $K8S_SECRET_NAME ]]; then

  if [[ -n $K8S_SECRET_COMBINE_CA ]]; then
    [[ -z $SILENT ]] && echo "====> Adding CA to Cert file"
    cat ${CA_CERT} >> ${SSL_CERT}
  fi

  [[ -z $SILENT ]] && echo "====> Creating Kubernetes secret: $K8S_SECRET_NAME"
  kubectl delete secret $K8S_SECRET_NAME --ignore-not-found

  if [[ -n $K8S_SECRET_SEPARATE_CA ]]; then
    kubectl create secret generic \
    $K8S_SECRET_NAME \
    --from-file="tls.crt=${SSL_CERT}" \
    --from-file="tls.key=${SSL_KEY}" \
    --from-file="ca.crt=${CA_CERT}"
  else
    kubectl create secret tls \
    $K8S_SECRET_NAME \
    --cert=${SSL_CERT} \
    --key=${SSL_KEY}
  fi

  if [[ -n $K8S_SECRET_LABELS ]]; then
    [[ -z $SILENT ]] && echo "====> Labeling Kubernetes secret"
    IFS=$' \n\t' # We have to reset IFS or label secret will misbehave on some systems
    kubectl label secret \
      $K8S_SECRET_NAME \
      $K8S_SECRET_LABELS
  fi
fi

echo "4. 重命名服务证书"
mv ${CN}.key tls.key
mv ${CN}.crt tls.crt

Ckeditor5 图片媒体库浏览插件

找了一圈,网上的各种资源都是针对图片上传的,没有针对已有的图片进行浏览添加。顾参考插件教程写了一个支持图片浏览的插件。

首先是说明,这个只提供了接口,具体的图片窗口展示样式需要自己做。

源码参考地址: https://gitee.com/yanlong-li/ckeditor5-build-classic/tree/stable/src/plugins/ImageBrowsing

提供两个api:

open 负责点击菜单时,回调自定义函数来开启图片浏览窗口

init 负责在插件初始化时,给一个匿名函数,用于图片浏览后给定一个图片地址进行插入

下面是 插件,放置在 /src/plugins 目录下的,可自定义,imageIcon 也是自定义一个图标
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import imageIcon from './icon.svg';
import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
// 导出插件   ImageBrowsing  可自定义
export default class ImageBrowsing extends Plugin {
   init() {
     //插件的名字  imageBrowsing  可自定义
      const config = this.editor.config.get('imageBrowsing');

      const editor = this.editor;

      // 调用 init 函数 将 匿名函数传递进去  方便在外围调用
      config.init((imageUrl) => {
         if (!imageUrl) {
            return;
         }
         editor.model.change(writer => {
            const imageElement = writer.createElement('image', {
               src: imageUrl
            });

            // Insert the image in the current selection location.
            editor.model.insertContent(imageElement, editor.model.document.selection);
         });
      })

      editor.ui.componentFactory.add('ImageBrowsing', locale => {
         const view = new ButtonView(locale);

         view.set({
            label: '媒体库',
            icon: imageIcon,
            tooltip: true
         });

         // Callback executed once the image is clicked.
         view.on('execute', () => {
            if (!config.open) {
               return;
            }
            config.open()
         });

         return view;
      });

   }
}
引用时的配置:
imageBrowsing: {
   call: null,
   init: (call) => {
      // 接收一个匿名形参,并保存起来,存在哪里都行;
      this.call = call
      // 当选择图片时调用
      //  call("图片url地址") 
   },
   open: () => {
      console.log('哈哈哈');
   }
},

使用GPG签名进行GIT提交的几个问题

先贴出我的配置文件

[user]
     name = Yanlong-li
     email = ahlyl94@gmail.com
     signingkey = 68EFDB840679A70E
 [winUpdater]
     recentlySeenVersion = 2.24.0.windows.2
 [commit]
     gpgSign = true
 [gpg]
     program = D:/phper/tools/GnuPG/bin/gpg.exe

commit.gpgSign = true 用于每次commit都自动使用gpg 进行签名
user.signingkey = XXXXXX 用于配置gpg签名的密钥指定,根据实际修改

gpg.program=xxx 这个要根据实际情况修改,因为我用的是 Kleopatra 进行管理,如果用git自带的gpg代理程序会提示  gpg: DBG: locking for 'xxx/.gnupg/gnupg_spawn_agent_sentinel.lock'  这个文件被锁定导致报错

如果你用了Kleopatra 进行证书的管理,但又不想使用Kleopatra的gpg签名,需要执行下列步骤:

去除program参数,并且创建指向密钥目录的软链接

mklink /d %USERPROFILE%\.gnupg %USERPROFILE%\AppData\Roaming\gnupg

删除 %USERPROFILE%/.gnupg/gnupg_spawn_agent_sentinel.lock 文件

关于GPG密钥的创建应该就不用我说了,Windows推荐使用Kleopatra进行图形化的管理。

PHP7.4 发布 来说一下改进和新功能

空合并运算符 ??=

PHP新增一个 空合并运算符 ??= ,如下demo

<?php
$a??=1; // $a = isset($a)?$a:1;
echo $a; // 1

当前置变量 没有 赋值或为null 时,将后置变量赋值给前置变量,相当于 $a = $a??1;
$a = $a??1; 相当于 $a = isset($a)?$a:1; 注意 ?? 需要一个变量来接收,
而 ??= 是自动用前置变量来接收。
所以最终 $a??=1 相当于 $a = isset($a)?$a:1;

属性类型

意思呢就是 类的属性支持强类型了,这个功能我可是期待很久的。奈何 7.4 之前的版本并不支持。这样就能更严格的控制变量类型了。

对此说明一点,就目前来讲 强类型 并不会提高太多性能,只是让开发人员更清晰控制变量类型,都说 强类型 是编译性语言的特性,因为强类型有利于编译执行。当PHP有了强类型后,相信不久的将来 编译执行 特性也会来临,比如 p++。

箭头函数

这个箭头函数在JS等语言可能经常出现,其实就是 ()=>{} 常用于写匿名函数或操作数很精简的函数。

<?php
$factor = 10;
$nums = array_map(fn($n) => $n * $factor, [1, 2, 3, 4]);
// $nums = array(10, 20, 30, 40);

这是一个官方的 demo ,如果不知道 array_map 函数的意思可以查一下手册。

<?php

$fn = fn($a, $b, $c = 1) => $a + $b + $c;
echo $fn(1, 1); // 3

这个例子可能更简单,其实就是一个更简单一些
fn 是 function 的简写,函数内可以接收多个参数包括可选参数,箭头函数体内不能包括在 大括号 {} 内,仅允许一个表达式,并自动 return 返回,如果要更复杂的操作还是 常规的匿名函数来的方便。

数组展开 Unpacking inside arrays

这个特性也非常舒适,当你需要将两个数组合并时往往是用过 []+[] 或 array_merge 去合并数组,但当你新建立一个数组需要包含已有数组时往往只能 先创建再和合并数组,此时我们可以使用 …[] 来嵌套并展开已有数组。

<?php

$a = [1,2,3,4,5]; //已有数组

$b = [7,8,9,…$a];

var_dump($b); // [7,8,9,1,2,3,4,5];

数值分隔符

这个简单了解一下就好,就是数值中间穿插下划线 _ 会自动忽略,不会对数值产生影响。不知道这个特性有什么好处,毕竟一般分割是逗号 1,000 但是逗号在编程中又有特殊意义。

更多的参考官方文档吧

https://www.php.net/manual/en/migration74.new-features.php#migration74.new-features.core.unpack-inside-array

使用宝塔面板进行项目的自动部署WebHook

首先你要知道什么是WebHook,如果你真的不想知道那也没关系。总之就是在你push到git仓库时会从git仓库触发一个http请求。关于http的地址根据你不同的git仓库有不同的方式去配置。

首先配置宝塔面板,你需要安装宝塔插件中的 WebHook

随便起一个名字然后保存

这时你会在列表中看到新增加的名称,点击查看密钥 获取密钥并配置到git仓库中,如下gitee.com仓库

注意ip和端口号之间有一个冒号 :

关于使用git ssh 需要你配置ssh密钥,可以使用

ssh-keygen -t rsa -C “name@mail.com”

如果没有才执行这个命令并将公钥设置为部署公钥
查看命令是 cat ~/.ssh/id_rsa.pub

如下代码点击编辑后输入并保存

需要替换gitPath的项目储存路径和 gitSSH 为你的项目的gitSSH地址信息

#!/bin/bash
#输出空白行 隔断
echo ""
#输出当前时间
date  +"%Y-%m-%d %H:%M.%S"
echo "Start"
#判断宝塔WebHook参数是否存在
#if [ ! -n "$1" ];
#then
#          echo "param参数错误"
#          echo "End"
#          exit
#fi
#git项目路径
gitPath="/www/wwwroot/www.daohang.dev"
#git 网址 这里要修改成你的仓库地址
gitSSH="git@gitee.com:yanlong-li/daohang.dev.git"
# 定义自定义脚本的文件名称
buildScript="buildScript.sh"
echo "Web站点路径:$gitPath"

#判断项目路径是否存在
if [ -d "$gitPath" ]; then
        cd $gitPath
        #判断是否存在git目录
        if [ ! -d ".git" ]; then
                echo "在该目录下克隆 git"
                git clone $gitSSH gittemp
                mv gittemp/* gittemp/.[^.]* .
				rm -rf gittemp
        fi
        #拉取最新的项目文件
        #git reset --hard origin/master
		echo "正在拉取远程代码"
        git pull
        #设置目录权限
        #chown -R www:www $gitPath
        echo "拉取结束"
else
        echo "该项目路径不存在"
        echo "End"
        exit
fi
# 下面是自定义的一个脚本,用于自定义的执行动作 如果不需要可以删除
if [ -f "$buildScript" ]; then
  chmod +x $buildScript
  ./$buildScript
else
  echo '不存在执行脚本';
fi
echo "脚本执行结束"

下面是我用来编译 Vue的一个脚本,也一起放上来

前提你要安装了 mp2管理器 或者手动安装了 node+npm


# 编译脚本 buildScript.sh

logUpdatePath="log/update"
logBuildPath="log/build"
# 更新依赖
logDate=$(date  +"%Y-%m-%d-%H-%M")
if [ ! -d "$logUpdatePath" ]; then
    mkdir -p $logUpdatePath
fi
if [ ! -d "$logBuildPath" ]; then
    mkdir -p $logBuildPath
fi
echo "更新依赖"
npm install
echo "编译项目"
npm run build
echo "设置权限"
chown -R www:www dist/[^.]*
echo "运行结束"
注意 有时候可能在Webhook中无法识别到node和npm,重装WebHook即可
使用图中的方法进行新建一个,然后提交后点击测试,然后查看日志,如果是空白则需要重装WebHook

如何 Git 上使用 GPG 进行验证提交教程

首先你可以可以参阅 Gitee(码云) 和github发布的各自平台的添加教程

https://gitee.com/help/articles/4248#article-header0

https://help.github.com/en/github/authenticating-to-github/managing-commit-signature-verification

以下来自码云

如何在码云上使用 GPG

GPG

GPG Key 生成与导出

Windows

  1. 下载 https://gpg4win.org/
  2. 生成 GPG Key
输入图片说明

输入用户名和邮箱,注意邮箱必须与 Gitee 提交邮箱一致

输入图片说明
  1. 导出
输入图片说明

另外在Windows平台请注意

请仔细确认你的GPG 主目录是在哪个位置,如下图:

比如我的就是
C:/Users/Yanlongli/AppData/Roaming/gnupg/pubring.kbx
而 Git默认寻找位置是
C:\Users\Yanlongli\.gnupg
这会产生如下问题

gpg: directory ‘/c/Users/Yanlongli/.gnupg’ created
gpg: keybox ‘/c/Users/Yanlongli/.gnupg/pubring.kbx’ created

gpg: skipped “68EFDB840679A70E”: No secret key
gpg: signing failed: No secret key
error: gpg failed to sign the data
fatal: failed to write commit object

这就是目录不对
我们可以通过软连接的方式链接到该目录 — 注意需要管理员权限
mklink /d C:\Users\Yanlongli\.gnupg C:\Users\Yanlongli\AppData\Roaming\gnupg

如果出现如下错误,直接删除 所有 .gnupg 目录下 .lock结尾的文件即可

gpg: invalid size of lockfile ‘/c/Users/Yanlongli/.gnupg/gnupg_spawn_agent_sentinel.lock’
gpg: cannot read lockfile
gpg: can’t connect to the agent: Invalid argument
gpg: keydb_search failed: No agent running
gpg: skipped “68EFDB840679A70E”: No agent running
gpg: signing failed: No agent running
error: gpg failed to sign the data
fatal: failed to write commit object

[转载]Webstorm/Phpstorm中将ES6文件转为es5的js文件

https://www.liangzl.com/get-article-detail-11958.html

前言:

       我写此篇文章是为了在比较老旧的项目中书写es6代码,例如fis项目、非webpack架构的JQuery项目等等,如果你是vue + webpack项目,请无视这篇文章:)

用web/phpstrom写老旧项目用es6的步骤:

1.打开phpstorm的命令行,运行命令:

npm install -g babel-cli

2. 在当前项目中安装

npm install --save-dev babel-preset-es2015

3.在File-settings-Tools-File Watcher中:

 点击+号

File Type:配置该监听器监听的文件类型,可以在Preferences > Editor > File types中配置
Scope:配置该监听器的监听范围,可自定义新的范围,也可以使用Preferences > Appearance & Behavior > Scopes
Program:babel的安装位置
Arguments:命令执行参数,参见Babel CLI
Working directory:babel命令执行的位置,默认为文件所在目录

我在此处是将后缀为.es6的文件进行编译,设置–out-dir ./ 设置输出目录为在当前.es6相同的目录中,然后在html中引入的是.js后缀的es5文件就可以愉快的写es6了

4.  .babelrc文件

   我们可以通过在根目录设置.babelrc文件去配置babel编译的结果

参考: https://blog.csdn.net/zhoubo5692/article/details/78414713


 转载至链接:https://my.oschina.net/jamesview/blog/1924356。

MySql修复表

前公司服务器到期,自行手动备份恢复了数据到另一台服务器上,造成MySql服务无法启动。php-fpm无法启动等问题。

经检查为系统权限问题,将MySql的data目录设置为对应的启动用户所有权即可。也会表提示为标记为修复,可以使用下面的方法解决。

针对test_db库修复所有表

myisamchk -r -q ……../data/test_db/*.MYI

针对test_db库修复某个特定表

myisamchk -r -q ……../data/test_db/user.MYI

下面的没有经过测试,可以参考:

自动修复全部数据库及表

mysqlcheck --auto-repair -A -o -uroot -p

针对某一个特定库

mysqlcheck –auto-repair –databases test -o -uroot -p

开启关闭Windows10文件系统区分大小写

关闭使用

fsutil.exe file SetCaseSensitiveInfo D:\workspace disable

开启使用

fsutil.exe file SetCaseSensitiveInfo D:\workspace enable

需要注意点,Windows下的文件区分大小写并不好用。推荐不要开启,默认为关闭状态。

更改文件启用区分大小写时,出现错误:不支持该请求。

解决方案:勾选适用于Linux的Windows子系统,需要重启。