jwj 发布的文章

在 Excel 中,stdevp 是计算样本总体标准偏差的函数,它反映了相对于平均值的离散程度。但在 PHP 里是没有该函数的,要计算标准偏差时,只能自己进行写算法,十分不便。于是查询相关资料和公式,总结出了以下代码。

- 阅读剩余部分 -

为了方便给多台服务器提供文件访问能力和CDN加速能力,我选择了使用COS来储存文件。但官方提供的开机自动挂载方案感觉不大稳定,自己研究cosfs工具的使用,并配合systemctl来实现开机自动挂载。

相比官方提供的/etc/fstab挂载方案,使用systemctl来管理cosfs进程个人感觉会更稳定,因为systemctl提供了自动重启功能,即cosfs进程挂了会自动启动。

使用/etc/fstab挂载方案,如果文件修改过于频繁,挂载会掉。
两者的性能没具体测试过,但应该不会相差太大。

安装 cosfs

这里我用的是 Ubuntu 20.04,如果你的是其它系统,可以参考官方文档进行安装。

下载包

wget https://github.com/tencentyun/cosfs/releases/download/v1.0.19/cosfs_1.0.19-ubuntu20.04_amd64.deb

安装包

sudo dpkg -i cosfs_1.0.19-ubuntu20.04_amd64.deb

编辑密钥文件

sudo nano /etc/passwd-cosfs

密钥文件内容

<BucketName-APPID>:<SecretId>:<SecretKey>
<BucketName-APPID>为存储桶名称格式。
<SecretId><SecretKey> 为密钥信息,您可前往访问管理控制台的 云 API 密钥管理 中查看和创建。

修改密钥文件权限

sudo chmod 640 /etc/passwd-cosfs
sudo chown www:www /etc/passwd-cosfs
因为我挂载 cos 是给网站使用的,所以我都是用 www 用户来挂载。后面的 chown 都是这个用途

创建挂载目录

因为挂载cos时,需要被挂载的目录存在,所以我们先提前创建

sudo mkdir -p /mnt/cosfs
sudo chown www:www /mnt/cosfs

创建缓存目录

sudo mkdir -p /var/cache/cosfs
sudo chown www:www /var/cache/cosfs

编辑fuse.conf

编辑fuse配置,以允许其它用户访问挂载的文件

sudo nano /etc/fuse.conf

找到user_allow_other,如果被注释则取消注释,如果没有该配置,则新增一行配置。

user_allow_other
不设置的话,其它用户会访问不了挂载的目录
fusermount: option allow_other only allowed if 'user_allow_other' is set in /etc/fuse.conf

设置systemctl服务

编辑服务文件

sudo nano /etc/systemd/system/cosfs.service
[Unit]
Description=cosfs Service
After=network.target

[Service]
Type=simple
User=www
Group=www
Restart=on-failure
RestartSec=5s
ExecStart=cosfs -f cos-1251274180 /mnt/cosfs -ourl=http://cos.ap-guangzhou.myqcloud.com -odbglevel=info -oallow_other -ouse_cache=/var/cache/cosfs

[Install]
WantedBy=multi-user.target
cos-1251274180 为储存桶名称
/mnt/cosfs 为本地挂载目录
-ourl 为访问域名。请参见 地域和访问域名
-ogid 用户组ID
-ouid 用户ID
-ouse_cache 缓存目录

常用挂载选项

-omultipart_size=[size]
用来指定分块上传时单个分块的大小(单位: MB),默认是10MB。 由于分块上传对单个文件块的数目有最大限制(10000块),所以对于超出100GB(10MB * 10000)大小的文件,需要根据具体情况调整该参数。

-oallow_other
如果要允许其他用户访问挂载文件夹,可以在运行 COSFS 的时候指定该参数。

-odel_cache
默认情况下,COSFS 工具为了优化性能,在 umount 后,不会清除本地的缓存数据。 如果需要在 COSFS 退出时,自动清除缓存,可以在挂载时加入该选项。

-onoxattr
禁用 getattr/setxattr 功能,在1.0.9之前版本的 COSFS 不支持设置和获取扩展属性,如果在挂载时使用了 use_xattr 选项,可能会导致 mv 文件到 Bucket 失败。

-opasswd_file=[path]
该选项可以指定 COSFS 密钥文件的所在路径,该选项设定的密钥文件需要设置权限为600。

-odbglevel=[dbg|info|warn|err|crit]
设置 COSFS 日志记录级别,可选 info、dbg、warn、err 和 crit。生产环境中建议设置为 info,调试时可以设置为 dbg。如果您的系统日志,未定期清理且由于访问量很大,生成大量日志,您可以设置为 err 或者 crit。

-oumask=[perm]
该选项可以去除给定类型用户,对挂载目录内文件的操作权限。例如,-oumask=755,对应挂载目录的权限变为022。

-ouid=[uid]
该选项允许用户 id 为 [uid] 的用户不受挂载目录中文件权限位的限制,可以访问挂载目录中的所有文件。
获取用户 uid 可以使用 id 命令,格式id -u username。例如执行id -u user_00,可获取到用户 user_00 的 uid。

-oensure_diskfree=[size]
COSFS 工具为提升性能,默认使用系统盘存放上传、下载的临时缓存,文件关闭后会释放空间。在并发打开的文件数较多或者读写大文件的时候,COSFS 工具会尽量多的使用硬盘来提高性能,默认只保留 100MB 硬盘可用空间给其他程序使用,可以通过选项 oensure_diskfree=[size] 设置 COSFS 工具保留可用硬盘空间的大小,单位为 MB。例如-oensure_diskfree=1024,COSFS 工具会保留1024MB剩余空间。

启动和安装服务

此时,我们尝试下启动服务

sudo systemctl start cosfs

然后查看服务状态

sudo systemctl status cosfs

如果Active的状态是 active (running) ,则代表服务运行正常。
参考运行状态:

cosfs.service - cosfs Service
     Loaded: loaded (/etc/systemd/system/cosfs.service; disabled; vendor preset: enabled)
     Active: active (running) since Thu 2022-02-17 17:36:59 CST; 20s ago
   Main PID: 9689 (cosfs)
      Tasks: 3 (limit: 2328)
     Memory: 2.8M
     CGroup: /system.slice/cosfs.service
             └─9689 /usr/local/bin/cosfs -f cos-1251274180 /mnt/cosfs -ourl=http://cos.ap-guangzhou.myqcloud.com -odbglevel=info -ogid=1002 -ouid=1002 -ouse_cache=/tmp/cosfs

Feb 17 17:36:59 VM-8-16-ubuntu systemd[1]: cosfs.service: Scheduled restart job, restart counter is at 37.
Feb 17 17:36:59 VM-8-16-ubuntu systemd[1]: Stopped cosfs Service.
Feb 17 17:36:59 VM-8-16-ubuntu systemd[1]: Started cosfs Service.
Feb 17 17:36:59 VM-8-16-ubuntu s3fs[9689]: [tid:9689]s3fs.cpp:main(5001): init v1.0.19(commit:unknown) with OpenSSL

那我们就可以直接启用服务了,那么服务就会开机时自动启动。

sudo systemctl enable cosfs

如果状态不正常,请看后面的调试服务

链接文件

需要挂载cos中的某个文件或目录到网站中的话,我们可以使用软链接来进行。
如:挂载cos中的files目录到网站目录中/www/wwwroot/default,则可以使用以下命令

sudo ln -s /mnt/cosfs/files /www/wwwroot/default/files
sudo chown -h www:www /www/wwwroot/default/files

调试服务

如果服务不能正常运行,可以使用命令查看服务运行日志,再根据日志信息去调整配置和服务。

journalctl -f -u cosfs.service

如果修改了服务,需要重新加载服务然后重启服务才会生效

sudo systemctl daemon-reload
sudo systemctl restart cosfs

cosfs 工具帮助

cosfs -h
用法: cosfs BUCKET:[PATH] MOUNTPOINT [OPTION]...

挂载腾讯云 COS 储存桶作为文件系统.

   cosfs 和 FUSE/mount 的常规选项:
      -o opt[,opt...]
      -o opt [-o opt] ...

cosfs 选项:

   大多数 cosfs 选项以"opt"的形式给出:

             <option_name>=<option_value>

   default_acl (默认="public-read")
     - 应用所有写入cos对象时的默认acl

   retries (默认="2")
      -  cos 事务失败时的重试次数

   use_cache (默认="" 即禁用缓存)
      - 用于本地文件缓存的本地文件夹

   del_cache (删除本地文件缓存)
      - cosfs启动和退出时删除本地文件缓存

   storage_class (默认="standard")
      - 使用指定的存储类存储对象.  可能的值:
        standard, standard_ia, 和 reduced_redundancy.

   public_bucket (默认="" 即禁用)
      - 设置为 1 时,匿名挂载公共存储桶

   passwd_file (默认="")
      - 指定要使用的 cosfs 密码文件

   connect_timeout (默认="300" 秒)
      - 连接等待超时时间

   readwrite_timeout (默认="60" 秒)
      - 读写等待超时时间

   max_stat_cache_size (默认="1000" 个 (约 4MB))
      - 文件元数据的缓存空间可缓存多少个文件的元数据

   stat_cache_expire (默认不过期)
      - 指定文件元数据缓存的过期时间(秒)

   enable_noobj_cache (默认禁用)
      - enable cache entries for the object which does not exist.
      cosfs always has to check whether file(or sub directory) exists 
      under object(path) when cosfs does some command, since cosfs has 
      recognized a directory which does not exist and has files or 
      sub directories under itself. It increases ListBucket request 
      and makes performance bad.
      You can specify this option for performance, cosfs memorizes 
      in stat cache that the object(file or directory) does not exist.

   no_check_certificate
      - server certificate won't be checked against the available 
      certificate authorities.

   nodnscache (禁用DNS缓存)
      - cosfs is always using dns cache, this option make dns cache disable.

   nosscache (禁用SSL会话缓存)
      - cosfs is always using ssl session cache, this option make ssl 
      session cache disable.

   multireq_max (默认="20")
      - maximum number of parallel request for listing objects.

   parallel_count (默认="5")
      - number of parallel request for uploading big objects.
      cosfs uploads large object(over 20MB) by multipart post request, 
      and sends parallel requests.
      This option limits parallel request count which cosfs requests 
      at once. It is necessary to set this value depending on a CPU 
      and a network band.

   multipart_size (默认="10")
      - part size, in MB, for each multipart request.

   ensure_diskfree (默认与 multipart_size 的值相同)
      - sets MB to ensure disk free space. cosfs makes file for
        downloading, uploading and caching files. If the disk free
        space is smaller than this value, cosfs do not use diskspace
        as possible in exchange for the performance.

   singlepart_copy_limit (默认="5120")
      - maximum size, in MB, of a single-part copy before trying 
      multipart copy.

   url (默认="")
      - sets the url to use to access tencentyun cos

   default_permission (默认=777)
      - when the file do not have permission meta, cosfs will use this 
      defalut value.

   endpoint (默认="")
      - sets the endpoint to use on signature version 4
      If the cosfs could not connect to the region specified
      by this option, cosfs could not run. But if you do not specify this
      option, and if you can not connect with the default region, cosfs
      will retry to automatically connect to the other region. So cosfs
      can know the correct region name, because cosfs can find it in an
      error from the COS server.

   mp_umask (默认为 "0000")
      - sets umask for the mount point directory.
      If allow_other option is not set, cosfs allows access to the mount
      point only to the owner. In the opposite case cosfs allows access
      to all users as the default. But if you set the allow_other with
      this option, you can control the permissions of the
      mount point by this option like umask.

   nomultipart (禁用分段上传)

   enable_content_md5 (默认禁用)
      - ensure data integrity during writes with MD5 hash.


   nocopyapi (for other incomplete compatibility object storage)
        For a distributed object storage which is compatibility COS
        API without PUT(copy api).
        If you set this option, cosfs do not use PUT with 
        "x-cos-copy-source"(copy api). Because traffic is increased
        2-3 times by this option, we do not recommend this.

   norenameapi (for other incomplete compatibility object storage)
        For a distributed object storage which is compatibility COS
        API without PUT(copy api).
        This option is a subset of nocopyapi option. The nocopyapi
        option does not use copy-api for all command(ex. chmod, chown,
        touch, mv, etc), but this option does not use copy-api for
        only rename command(ex. mv). If this option is specified with
        nocopyapi, then cosfs ignores it.

   use_path_request_style (use legacy API calling style)
        Enble compatibility with OSS-like APIs which do not support
        the virtual-host request style, by using the older path request
        style.

   dbglevel (默认="crit")
        Set the debug message level. set value as crit(critical), err
        (error), warn(warning), info(information) to debug level.
        default debug level is critical. If cosfs run with "-d" option,
        the debug level is set information. When cosfs catch the signal
        SIGUSR2, the debug level is bumpup.

   curldbg - put curl debug message
        Put the debug message from libcurl when this option is specified.

FUSE/mount 选项:

   Most of the generic mount options described in 'man mount' are
   supported (ro, rw, suid, nosuid, dev, nodev, exec, noexec, atime,
   noatime, sync async, dirsync).  Filesystems are mounted with
   '-onodev,nosuid' by default, which can only be overridden by a
   privileged user.
   
   There are many FUSE specific mount options that can be specified.
   e.g. allow_other  See the FUSE's README for the full set.

其它选项:

 -h, --help        输出帮助信息.
     --version     输出版本信息.
 -d  --debug       开启系统日志的调试消息。 指定 -d 两次会启用 FUSE 调试消息到 STDOUT。
 -f                FUSE 前台选项 - 不要作为守护程序运行
 -s                FUSE 单线程选项(禁用多线程操作)

参考链接

申请软著或知识产权用的。主要统计代码行数和合并所有代码文件到一个文件,打印前后各30页这个需要自己打开合并后的文件去打印。

<?php

$output = 'print.txt';
$dir = 'app';

$list = scanFiles('app');
$info = mergeFiles($output, $list);
echo '文件总数:' . count($list) . '个' . PHP_EOL;
echo '代码总量:' . $info['content length'] . '字' . PHP_EOL;
echo '代码行数:' . $info['line total'] . '行' . PHP_EOL;

/**
 * 扫描指定目录下的所有文件
 * @param string $path 要扫描的目录
 * @param string $regex 文件名规则(正则)
 * @return array
 */
function scanFiles($path, $regex = '\.(php|html)$')
{
    $list = [];
    foreach (scandir($path) as $item) {
        if ('.' === $item || '..' === $item) continue;
        if (is_dir($path . '/' . $item)) {
            $list = array_merge($list, scanFiles($path . '/' . $item));
        } elseif (is_file($path . '/' . $item)) {
            if (!preg_match('@' . $regex . '@', $item)) continue;
            $list[] = $path . '/' . $item;
        }
    }

    return $list;
}

/**
 * 合并数组中的所有文件
 * @param string $output 合并后的内容的输出路径
 * @param array $list 要合并的文件列表
 * @return array
 */
function mergeFiles($output, $list)
{
    $file = fopen($output, 'w+');
    $length = 0;
    $line = 0;
    foreach ($list as $item) {
        $itemRes = fopen($item, 'r');
        $findEnd = false;
        while(!feof($itemRes))
        {
            $itemLine = fgets($itemRes);
            if ($findEnd) {
                if (false !== strpos($itemLine, '*/')) {
                    $findEnd = false;
                }
                continue;
            }

            if (preg_match('@^\s*//@', $itemLine)) {
                continue;
            } elseif (preg_match('@^\s*$@', $itemLine)) {
                continue;
            } elseif (preg_match('@\s*/\*.*\*/\s*@', $itemLine)) {
                continue;
            } elseif (false !== strpos($itemLine, '/*')) {
                $findEnd = true;
                continue;
            } else {
                $line++;
                $length += fwrite($file, $itemLine);
            }
        }
        fclose($itemRes);
    }
    fclose($file);
    return ['content length' => $length, 'line total' => $line];
}

执行效果

# php print.php
文件总数:317个
代码总量:1808293字
代码行数:41856行

近日有安全提示:OpenSSH XMSS Key 解析整数溢出漏洞。

XMSS中使用的签名方案是有状态的,这意味着密钥随时间而变化,此过程需要考虑以前保存的“状态”(如果有)。负责处理XMSS保存的“状态”的函数会由于整数溢出漏洞而导致内存破坏。任何可以解析私有XMSS密钥的OpenSSH函数都容易受到攻击。

披露时间:2019-10-09 00:00:00 CVE编号:CVE-2019-16905

修复方案

升级OpenSSH至8.1及以上版本

需确认机器已安装的软件包中不存在低版本openssh组件,如可通过执行命令:rpm -qa | grep openssh查看组件版本。

准备工作

安装编译所需依赖软件包:

yum install -y wget gcc pam-devel libselinux-devel zlib-devel openssl-devel

下载 OpenSSH 安装包上传至服务器或 wget 直接下载

cd /usr/local/src
wget -O openssh.tar.gz https://mirrors.aliyun.com/pub/OpenBSD/OpenSSH/portable/openssh-9.3p1.tar.gz

备份配置文件 一般卸载的时候都会把配置文件以sshd_config.rpmsave的方式另存一份,但是/etc/pam.d/sshd这个配置文件并没有另存,所以建议都备份一下。

cp /etc/ssh/sshd_config sshd_config.backup
cp /etc/pam.d/sshd sshd.backup

删除低版本OpenSSH的的rpm包

rpm -e --nodeps `rpm -qa | grep openssh`

安装openssh

解压

tar -zxvf openssh.tar.gz
cd openssh-9.3p1

编译配置

./configure --prefix=/usr --sysconfdir=/etc/ssh --with-md5-passwords --with-pam --with-zlib --with-tcp-wrappers --with-ssl-dir=/usr/local/ssl --without-hardening

编译安装

make && make install

配置

调整文件权限

chmod 600 /etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_ecdsa_key /etc/ssh/ssh_host_ed25519_key

复制配置文件

cp -a contrib/redhat/sshd.init /etc/init.d/sshd
chmod u+x /etc/init.d/sshd

还原配置文件

mv ../sshd.backup /etc/pam.d/sshd
mv ../sshd_config.backup /etc/ssh/sshd_config

添加添加自启服务ssh到开机启动项

chkconfig --add sshd
chkconfig sshd on

重启服务

systemctl restart sshd

验证结果

查看下安装结果:

ssh -V

运行结果

OpenSSH_9.3p1, OpenSSL 1.1.1k  FIPS 25 Mar 2021

到此,升级基本完成。安全起见不要关闭SSH窗口,新增一个SSH连接,看看能否正常登录。如果不能登录,可以根据 sshd 的日志进行配置调整。

清理源代码

rm -rf /usr/local/src/openssh*

参考链接:https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/INSTALL
本文基于《CentOS 8 升级 OpenSSH 8.4》进行修改后发布,感谢原作者的分享。

使用wget下载文件时,报了一个错误,浏览器打开检查证书,发现证书没过期。联想起前段时间Let's Encrypt更换了根证书,那应该就是这个问题了。

报错信息:

# wget https://dl.ll00.cn/v2ray-linux-64.zip
--2021-11-03 11:55:26--  https://dl.ll00.cn/v2ray-linux-64.zip
Resolving dl.ll00.cn (dl.ll00.cn)... 59.83.218.168, 116.178.66.14, 59.80.39.21, ...
Connecting to dl.ll00.cn (dl.ll00.cn)|59.83.218.168|:443... connected.
ERROR: cannot verify dl.ll00.cn's certificate, issued by ‘/C=US/O=Let's Encrypt/CN=R3’:
  Issued certificate has expired.
To connect to dl.ll00.cn insecurely, use `--no-check-certificate'.

解决办法:
Linux上更新或安装下的根证书就行

yum install -y ca-certificates