services->setting->platform->get('system.backend_url'), 8); $api_url = substr(Yii::$app->services->setting->platform->get('system.api_url'), 8); $h5_url = substr(Yii::$app->services->setting->platform->get('system.h5_url'), 8); $static_url = substr(Yii::$app->services->setting->platform->get('system.static_url'), 8); $salary_h5_url = parse_url(Yii::$app->services->setting->platform->get('system.cat_h5_url') ?: '')['host'] ?? ''; if (!empty($config['certificate']['ssl_path'])) { $is_docker_deploy = Yii::$app->params['is_docker_deploy']; //获取配置 $path = $config['certificate']['ssl_path']; $pwd = Yii::$app->params['oskad']; $is_docker_deploy = Yii::$app->params['is_docker_deploy']; $host = Yii::$app->params['host']; $replaces = [ '{SSL_PATH}' => $path, '{PWD}' => $pwd, '{FILE_NAME}' => static::FILE_NAME, ]; if ($is_docker_deploy) { //是否为docker搭建系统 $file_path = '/www/wwwroot/qimall/'; $file_content = static::shDockerTemplate(); //获取sh模板 } else { //prod $file_path = '/data/wwwroot/qimall/'; $file_content = static::shTemplate(); } //组装sh脚本 $content = str_replace(array_keys($replaces), array_values($replaces), $file_content); file_put_contents($file_path . static::FILE_NAME, $content); //执行脚本 if ($is_docker_deploy) { // exec('sshpass -p "'. $pwd.'" ssh root@'. $host .' "sh '. $file_path . static::FILE_NAME.'"'); exec("sshpass -p '".$pwd."' ssh -o StrictHostKeyChecking=no root@". $host." 'sh ". $file_path . static::FILE_NAME . "'"); } else { exec('sh '. $file_path . static::FILE_NAME); } } $url_arr = [ 'admin_expire_date' => $admin_url, 'h5_expire_date' => $h5_url, 'api_expire_date' => $api_url, 'static_expire_date' => $static_url, ]; // 有发薪猫插件才获取过期日期 if ($this->isInstallSalary($salary_h5_url)) { $url_arr['salary_h5_expire_date'] = $salary_h5_url; } //通过域名获取ssl证书过期日期 foreach ($url_arr as $key => $value) { $info = $this->getCertificateExpireTime($value); if ($info['code'] == 0) $config['certificate'][$key] = date('Y-m-d', $info['cert_info']['validTo_time_t']); } //保存配置 Yii::$app->services->setting->platform->set([static::KEY => $config]); return true; } /** * 获取配置 * * @param string $key * @return mixed */ public function getConfig(string $key = '') { $config = Yii::$app->services->setting->platform->get(static::KEY); foreach ($config as &$item) { $item = json_decode($item, true); } $info = $key ? ($config[$key] ?? '') : $config; if (!empty($info['certificate'])) $info['certificate']['ssl_path'] = ''; return $info; } /** * 计算证书到期提醒 * * @return array */ public function certificateNotice() { // 全部证书 $cers = ['admin', 'api', 'h5', 'static']; if ($this->isInstallSalary()) { $cers[] = 'salary_h5'; } $notices = []; foreach ($cers as $key) { $this->keyShowNotice('certificate', sprintf('%s_expire_date', $key)) && ($notices[] = $key); } return $notices; } /** * 计算服务器到期提醒 * * @return boolean */ public function serverNotice() { return $this->keyShowNotice('server'); } /** * 是否即将到期显示提示 * * @param string $key * @return boolean */ protected function keyShowNotice(string $key, string $expire_key = 'expire_date') { $config = $this->getConfig($key); if (!(isset($config['open_notice']) && $config['open_notice'])) return false; // 到期时间 $expire_date = $config[$expire_key]; return bcsub(strtotime($expire_date), time()) < bcmul(static::LIMIT, 86400); } //通过域名获取ssl证书过期时间 public function getCertificateExpireTime($url) { if (!extension_loaded('openssl') || !is_callable('openssl_x509_parse')){ return ['code' => -1, 'msg' => '请开启openssl扩展']; } //不规范入参处理 $parse = parse_url($url); if (!empty($parse['host'])) { $domain = $parse['host']; } elseif (empty($parse['path'])) { return ['code' => -1, 'msg' => $url . '请输入合法的域名']; } else { //abc.top/x/xx $arr = explode('/', $parse['path']); $domain = $arr[0]; } $context = stream_context_create([ 'ssl' => [ 'capture_peer_cert' => true, 'capture_peer_cert_chain' => true, ], ]); $client = @stream_socket_client("ssl://" . $domain . ":443", $errno, $errstr, 10, STREAM_CLIENT_CONNECT, $context); if ($client == false) { return ['code' => -1, 'msg' => $domain . '未查到可靠信息','err'=>[ 'errno'=>$errno, 'errstr'=>iconv('gbk', 'utf-8', $errstr), ]]; } $params = stream_context_get_params($client); if (empty($params['options']['ssl']['peer_certificate'])) { return ['code' => -1, 'msg' => $domain . '获取信息失败,请确保可以正常访问']; } $cert = $params['options']['ssl']['peer_certificate']; $cert_info = @openssl_x509_parse($cert); return ['code' => 0, 'cert_info' => $cert_info]; } /** * prod部署-sh模板 * * @return string */ protected static function shTemplate() { return <<<'EOC' #!/bin/bash # 检查是否有sudo权限 if [ "$(id -u)" != "0" ]; then # 设置root密码,这里是示例密码,请替换为您的实际密码 root_password='{PWD}' # 使用echo和管道将密码传递给su命令 echo $root_password | su -c "sh /data/wwwroot/qimall/{FILE_NAME}" fi # 检查是否有sudo权限 if [ "$(id -u)" == "0" ]; then # 证书 # 证书路径 ssl_path='{SSL_PATH}' # 移动证书到目录 dir=/application/nginx/conf/ssl # 证书目录 ssl=/data/wwwroot/qimall/${ssl_path} # 复制 cp ${ssl} ${dir}/ssl.zip cd ${dir} # 解压 unzip -o ssl.zip # 重启nginx # systemctl restart nginx /application/nginx/sbin/nginx -s reload # 重启消费者cd # systemctl restart swoole_consume_run fi EOC; } /** * docker部署-sh模板 * * @return string */ protected static function shDockerTemplate() { return <<<'EOC' #!/bin/bash # 检查是否有sudo权限 if [ "$(id -u)" != "0" ]; then # 设置root密码,这里是示例密码,请替换为您的实际密码 root_password='{PWD}' # 使用echo和管道将密码传递给su命令 echo $root_password | su -c "sh /www/wwwroot/qimall/{FILE_NAME}" fi # 检查是否有sudo权限 if [ "$(id -u)" == "0" ]; then # 证书 # 证书路径 ssl_path='{SSL_PATH}' # 移动证书到目录 dir=/data/confs/nginx/ssl # 证书目录 ssl=/www/wwwroot/qimall/${ssl_path} # 复制 cp ${ssl} ${dir}/ssl.zip cd ${dir} # 解压 unzip -o ssl.zip # 重启nginx # systemctl restart nginx sudo docker restart nginx # 重启消费者cd # systemctl restart swoole_consume_run fi EOC; } /** * 是否安装发薪猫插件 * * @param null $url * * @return bool */ public function isInstallSalary($url = null): bool { if (is_null($url)) { $url = Yii::$app->services->setting->platform->get('system.cat_h5_url'); } return Addons::isInstall('Salary') && $url; } }