王新阳

wangxinyang

linux中启动mysql

1. 使用systemctl启动MySQL(推荐)
如果系统使用Systemd,并且MySQL已安装为系统服务,可以使用以下命令:

# 启动MySQL
sudo systemctl start mysql

# 或者,有些系统上服务名可能是mysqld
sudo systemctl start mysqld

# 设置开机自启
sudo systemctl enable mysql

# 查看状态
sudo systemctl status mysql

# 停止MySQL
sudo systemctl stop mysql

# 重启MySQL
sudo systemctl restart mysql

2. 使用service命令(SysVinit系统)对于使用SysVinit的系统,可以使用service命令:

# 启动MySQL
sudo service mysql start

# 或者,有些系统上服务名可能是mysqld
sudo service mysqld start

# 查看状态
sudo service mysql status

# 停止MySQL
sudo service mysql stop

# 重启MySQL
sudo service mysql restart

3. 使用mysqld_safe启动
mysqld_safe是一个脚本,用于启动MySQL服务器,并在发生错误时自动重启。通常,它位于MySQL安装目录的bin目录下。

# 进入MySQL安装目录,假设在/usr/local/mysql
cd /usr/local/mysql

# 使用mysqld_safe启动,并指定配置文件(如果需要)
sudo bin/mysqld_safe --defaults-file=/etc/my.cnf &

# 或者,如果已经将MySQL的bin目录添加到PATH,可以直接运行
sudo mysqld_safe &

注意:使用mysqld_safe启动时,可能需要指定--user选项来指定运行MySQL的用户,通常为mysql。

4. 手动启动MySQL服务器
你也可以直接调用mysqld来启动,但这通常不推荐,因为它不会提供自动重启等保护。

# 指定配置文件启动
sudo /usr/sbin/mysqld --defaults-file=/etc/mysql/my.cnf &

# 或者,如果知道MySQL的数据目录和socket文件等位置,可以指定选项
sudo /usr/sbin/mysqld --datadir=/var/lib/mysql --socket=/var/lib/mysql/mysql.sock --user=mysql &

5. 使用MySQL安装包中的启动脚本
如果你使用二进制包或源码编译安装,可能提供了启动脚本。例如,在源码编译安装后,可以使用support-files/mysql.server脚本。

# 假设在MySQL安装目录下
sudo support-files/mysql.server start

6. 检查MySQL是否启动
无论使用哪种方式启动,都可以通过以下方法检查MySQL是否正在运行:

# 检查进程
ps aux | grep mysqld

# 检查端口(默认3306)
netstat -tlnp | grep 3306
ss -tlnp | grep 3306

# 尝试连接
mysql -u root -p -e "SHOW DATABASES;"

1. systemctl 启动(Systemd 系统,推荐)

# 1.1 启动 MySQL
sudo systemctl start mysql
# 或(某些发行版使用 mysqld)
sudo systemctl start mysqld

# 1.2 停止 MySQL
sudo systemctl stop mysql
sudo systemctl stop mysqld

# 1.3 重启 MySQL
sudo systemctl restart mysql
sudo systemctl restart mysqld

# 1.4 查看状态
sudo systemctl status mysql
sudo systemctl status mysqld

# 1.5 设置开机自启
sudo systemctl enable mysql
sudo systemctl enable mysqld

# 1.6 禁用开机自启
sudo systemctl disable mysql
sudo systemctl disable mysqld

# 1.7 重新加载配置文件
sudo systemctl reload mysql
sudo systemctl reload mysqld

# 1.8 查看日志
sudo journalctl -u mysql
sudo journalctl -u mysqld
sudo journalctl -u mysql -f  # 实时监控日志

2. service 启动(SysVinit 系统)

# 2.1 启动 MySQL
sudo service mysql start
sudo service mysqld start

# 2.2 停止 MySQL
sudo service mysql stop
sudo service mysqld stop

# 2.3 重启 MySQL
sudo service mysql restart
sudo service mysqld restart

# 2.4 查看状态
sudo service mysql status
sudo service mysqld status

# 2.5 设置开机自启
sudo chkconfig mysql on       # RHEL/CentOS 6
sudo update-rc.d mysql defaults # Debian/Ubuntu

# 2.6 禁用开机自启
sudo chkconfig mysql off
sudo update-rc.d mysql remove

3. 直接启动 MySQL 守护进程

# 3.1 使用 mysqld_safe(推荐)
sudo mysqld_safe --defaults-file=/etc/my.cnf &

# 3.2 直接启动 mysqld
sudo /usr/sbin/mysqld --defaults-file=/etc/my.cnf --user=mysql &

# 3.3 使用 MySQL 启动脚本
sudo /etc/init.d/mysql start
sudo /etc/init.d/mysqld start

# 3.4 使用 mysql.server(MacOS/部分Linux)
sudo /usr/local/mysql/support-files/mysql.server start

检查系统中安装的 MySQL

# 查看 MySQL 版本
mysql --version
mysql -V

# 查看 MySQL 安装位置
which mysql
whereis mysql

# 查看 MySQL 服务状态
systemctl list-units | grep -i mysql
systemctl list-units | grep -i mariadb

# 查看 MySQL 进程
ps aux | grep mysql
ps aux | grep mysqld

# 查看 MySQL 端口
sudo netstat -tlnp | grep mysql
sudo ss -tlnp | grep mysql
sudo lsof -i :3306

配置文件位置

# 常见配置文件位置
/etc/my.cnf
/etc/mysql/my.cnf
/usr/local/mysql/my.cnf
~/.my.cnf

# MariaDB 配置文件
/etc/my.cnf
/etc/my.cnf.d/
/etc/mysql/my.cnf
/etc/mysql/mariadb.conf.d/

video 视频标签的属性

一、核心 HTML5 属性

<video
  src="video.mp4"
  controls
  preload="metadata"
  poster="thumbnail.jpg"
  width="800"
  height="450"
  muted
  loop
  autoplay
  playsinline
  crossorigin="anonymous"
  class="video-player"
>
  <!-- 备用内容 -->
  <p>您的浏览器不支持 HTML5 视频</p>
</video>

二、针对 iOS/Safari 的关键属性

<video
  playsinline
  webkit-playsinline
  x5-playsinline
  t7-video-player-type="inline"
>

解释:
playsinline - 标准属性,防止 iOS 自动全屏
webkit-playsinline - WebKit 前缀版本(iOS 9-10 需要)
x5-playsinline - 腾讯 X5 内核(微信浏览器)
t7-video-player-type="inline" - 部分安卓浏览器

三、自动播放策略(iOS 限制)

<!-- iOS 允许自动播放的条件 -->
<video autoplay playsinline muted>
  <!-- 必须同时有:autoplay + playsinline + muted -->
</video>

<!-- 或使用 JavaScript 控制 -->
<video id="myVideo" playsinline controls>

// iOS 需要用户交互才能播放声音
document.addEventListener('touchstart', function() {
  const video = document.getElementById('myVideo');
  video.play().catch(e => console.log(e));
}, { once: true });

四、推荐的最佳实践配置

<video
  controls
  playsinline
  webkit-playsinline
  preload="metadata"
  poster="poster.jpg"
  width="100%"
  height="auto"
  style="object-fit: contain; background-color: #000;"
  crossorigin="anonymous"
  aria-label="视频描述"
>
  <!-- 多格式支持 -->
  <source src="video.mp4" type="video/mp4">
  <source src="video.webm" type="video/webm">
  <!-- 备用内容 -->
  <p>您的浏览器不支持 HTML5 视频</p>
</video>

五、重要 CSS 补充

video {
  /* 防止 iOS 默认控件 */
  -webkit-appearance: none;
  
  /* 移除 iOS 的蓝色高光 */
  -webkit-tap-highlight-color: transparent;
  
  /* 禁用文本选择 */
  user-select: none;
  -webkit-user-select: none;
  
  /* 响应式 */
  max-width: 100%;
  height: auto;
  display: block;
}

六、微信浏览器特殊处理

<video
  x5-video-player-type="h5"
  x5-video-player-fullscreen="true"
  x5-video-orientation="portrait"
>


php遍历获取当前目录及子目录下所有文件

/**
 * SELF_FIRST 目录从浅到深返回
 * CHILD_FIRST 先处理子节点,目录从深到浅返回
 */
function getAllFilesWithSize() {
        $files = [];
        $iterator = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($this->cacheBaseDir, FilesystemIterator::SKIP_DOTS),
            RecursiveIteratorIterator::CHILD_FIRST
        );
        foreach ($iterator as $SplFileInfo) {
            if ($SplFileInfo->isFile()) {
                $files[] = [
			'getRealPath' => $SplFileInfo->getRealPath(),
			'getPathname' => $SplFileInfo->getPathname(),
			'getExtension' => $SplFileInfo->getExtension(),
			'getFilename' => $SplFileInfo->getFilename(),
			'getSize' => $SplFileInfo->getSize(),
			'getType' => $SplFileInfo->getType(),
                ];
            }
        }
        
        return $files;
    }

参考:
PHP标准库 https://www.php.net/manual/zh/book.spl.php
递归目录迭代器 https://www.php.net/manual/zh/class.recursivedirectoryiterator.php

阻止事件冒泡的几种方法

如下代码,双击图片区域时,也会触发 alert(0) 事件,要阻止双击图片的冒泡

<body>
<img src="a.JPG" width="50%">
<script>
document.addEventListener('dblclick', function(e) {
    e.preventDefault(); // 阻止默认行为
    alert(0);
});
</script>
</body>

方法1:阻止图片的默认双击行为

<body>
<img src="a.JPG" width="50%" ondblclick="event.preventDefault();">
<script>
document.addEventListener('dblclick', function(){
    alert(0);
});
</script>
</body>

方法2:直接在图片上添加事件监听器(推荐)

<body>
<img src="a.JPG" width="50%" id="myImage">
<script>
document.getElementById('myImage').addEventListener('dblclick', function(event){
    event.preventDefault(); // 阻止默认行为
    alert(0);
}, false);
</script>
</body>

方法3:使用事件捕获阶段

<body>
<img src="a.JPG" width="50%">
<script>
document.addEventListener('dblclick', function(){
    alert(0);
}, true); // 使用捕获阶段而非冒泡阶段
</script>
</body>

方法4:完全阻止图片的所有默认行为

<body>
<img src="a.JPG" width="50%" style="pointer-events: none;">
<script>
document.addEventListener('dblclick', function(){
    alert(0);
});
</script>
</body>

方法5:使用更具体的事件处理(推荐)

<body>
<img src="a.JPG" width="50%">
<script>
// 捕获图片的双击事件
document.querySelector('img').addEventListener('dblclick', function(e){
    e.stopPropagation(); // 阻止冒泡到document
    alert('双击了图片!');
});

// 其他地方的双击事件
document.addEventListener('dblclick', function(e){
    if(e.target.tagName !== 'IMG') {
        alert('双击了非图片区域!');
    }
});
</script>
</body>

浏览器全屏切换、不允许选中示例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>浏览器全屏切换示例</title>
<style>
.no-select{-webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none;}
</style>
</head>
<body>
<button id="fullscreenBtn">进入全屏模式</button>
<div class="no-select" style="margin:2em 0;">使用css控制,双击这里时,文字<span style="color:red">不会</span>被选中</div>
<div style="margin:2em 0;">双击这里时,文字<span style="color:red">会</span>被选中</div>

<strong>css控制不选中</strong>
<pre style="padding:10px;border:1px solid #ccc;background-color:#f3f3f3">
.no-select{
	-webkit-user-select:none;
	-moz-user-select:none;
	-ms-user-select:none;
	user-select:none;
}
</pre>
<strong>js控制不选中</strong>
<pre style="padding:10px;border:1px solid #ccc;background-color:#f3f3f3">
	const selection = window.getSelection();
	if(selection)selection.removeAllRanges();
</pre>

<script>
function toggleFullscreen() {
	// 获取全屏API的兼容性写法
	const requestFullscreen = document.documentElement.requestFullscreen || 
		document.documentElement.mozRequestFullScreen ||
		document.documentElement.webkitRequestFullscreen ||
		document.documentElement.msRequestFullscreen;

	const exitFullscreen = document.exitFullscreen ||
		document.mozCancelFullScreen ||
		document.webkitExitFullscreen ||
		document.msExitFullscreen;
	if (!document.fullscreenElement &&
		!document.mozFullScreenElement &&
		!document.webkitFullscreenElement &&
		!document.msFullscreenElement) {
		// 进入全屏
		requestFullscreen.call(document.documentElement);
	} else {
		// 退出全屏
		exitFullscreen.call(document);
	}
}

document.getElementById('fullscreenBtn').addEventListener('click', toggleFullscreen);
document.addEventListener('dblclick', toggleFullscreen);
</script>
</body>
</html>

JSON 网络令牌JWT(JSON Web Token)

参考:https://zhuanlan.zhihu.com/p/12876076909

1、什么是JWT?
JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在各方之间以 JSON 格式安全地传输信息。它通常用于身份验证和授权流程中,特别是在无状态的 RESTful API 和现代 Web 应用中。

2、什么时候应该使用 JSON Web Token?
以下是 JSON Web Token (JWT) 的一些适用场景:

授权(Authorization): 这是 JWT 最常见的用途。用户登录后,后续的每个请求都会携带 JWT,从而允许用户访问该令牌所授权的路由、服务和资源。单点登录(Single Sign On)是当前广泛使用 JWT 的一个功能,因为它具有较小的开销,并且可以轻松跨不同域名使用。
信息交换(Information Exchange): JWT 是在各方之间安全传输信息的一种好方式。由于 JWT 可以签名(例如,使用公钥/私钥对),你可以确认发送者的身份。此外,由于签名是基于头部(header)和负载(payload)计算得出的,你还可以验证内容是否被篡改。

3、JSON Web Token 的结构是什么?
在紧凑形式中,JSON Web Token(JWT)由三部分组成,各部分之间通过点号(.)分隔:

头部(Header)
负载(Payload)
签名(Signature)

JWT有效期可以在 $payload 中设置(建议),也可以通过在 $secretKey 原有秘钥后加日期,动态改变秘钥来实现

PHP生成和验证jwt

//生成JWT令牌
function jwt_create($payload, $secretKey){
	function base64url_encode($data){return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');}
	// 定义 Header、Payload 和密钥
	$header = array('alg' => 'HS256');

	// 编码 Header 和 Payload
	$headerEncoded = base64url_encode(json_encode($header));
	$payloadEncoded = base64url_encode(json_encode($payload));

	// 生成签名(HMAC-SHA256)
	$signatureInput = "$headerEncoded.$payloadEncoded";
	$signature = hash_hmac('sha256', $signatureInput, $secretKey, true);
	$signatureEncoded = base64url_encode($signature);

	// 组合完整 JWT
	$jwt = "$headerEncoded.$payloadEncoded.$signatureEncoded";
	return $jwt;
}
//验证JWT令牌并获取数据
function jwt_verify($jwt,$secretKey){
	function base64url_encode($data){return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');}
	function base64url_decode($data) {$padding = strlen($data) % 4; if($padding > 0){$data .= str_repeat('=', 4 - $padding);} return base64_decode(strtr($data, '-_', '+/'));}
	// 提取已生成的 JWT 各部分
	list($header, $payload, $signature) = explode('.', $jwt);

	// 重新计算签名
	$recomputedSignature = base64url_encode(
		hash_hmac('sha256', "$header.$payload", $secretKey, true)
	);

	// 比较签名
	if($signature === $recomputedSignature){
		$res=json_decode(base64url_decode($payload),true);
		if(is_array($res) && isset($res['userid']))return $res['userid'];
	}
	return false;
}

html跨平台在线预览pdf

PDFObject.js

官网:https://pdfobject.com/

相关博客:

https://blog.csdn.net/i_dont_know_a/article/details/80707963

https://blog.csdn.net/qappleh/article/details/80250492

https://www.jq22.com/yanshi649


pdf.js

官网:https://mozilla.github.io/pdf.js/getting_started/

相关博客:

https://blog.csdn.net/weixin_42400643/article/details/152602790

https://blog.csdn.net/weixin_31800911/article/details/148820919

https://www.jb51.net/javascript/338851frl.htm

移动端h5常用的几款插件

1、拖拽排序插件——Sortable.js
演示地址:https://www.jq22.com/yanshi10850


2、日期选择插件——rolldate.js
演示地址:https://weijhfly.github.io/rolldate-index.html
下载地址:https://www.jq22.com/jquery-info19834


3、图片裁剪插件——cropper.js
下载地址:https://github.com/fengyuanchen/cropperjs


4、底部滑动选择插件——mobileSelect.js
下载地址:https://www.jq22.com/jquery-info14679
演示地址:https://www.jq22.com/yanshi14679

php获取指定目录的所有子孙目录

方法一:scandir + 递归

function getAllSubdirectories($path) {
    $subdirs = [];
    
    $items = scandir($path);
    foreach ($items as $item) {
        if ($item === '.' || $item === '..') continue;
        
        $fullPath = $path . DIRECTORY_SEPARATOR . $item;
        if (is_dir($fullPath)) {
            // 添加当前目录
            $subdirs[] = $fullPath;
            // 递归获取子目录的子目录
            $subdirs = array_merge($subdirs, getAllSubdirectories($fullPath));
        }
    }
    
    return $subdirs;
}

// 使用示例
$allSubdirs = getAllSubdirectories('/path/to/directory');
print_r($allSubdirs);

方法二:使用 RecursiveDirectoryIterator(推荐)

function getAllSubdirectoriesIterator($path) {
    $subdirs = [];
    
    $iterator = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS),
        RecursiveIteratorIterator::SELF_FIRST
    );
    
    foreach ($iterator as $fileinfo) {
        if ($fileinfo->isDir()) {
            $subdirs[] = $fileinfo->getPathname();
        }
    }
    
    return $subdirs;
}

// 使用示例
$allSubdirs = getAllSubdirectoriesIterator('/path/to/directory');
print_r($allSubdirs);

layui.prompt 监听回车键来触发确认操作

layer.prompt({
	title: '请输入密码:',
	formType: 1,
	success: function(layero, index){
		$(layero).find('.layui-layer-input').prop('autocomplete','new-password').on('keydown',function(e){
			if(e.which === 13){
				$(layero).find('.layui-layer-btn0').trigger('click');
			}
		});
	},
	yes: function(index, layero){
		let elem=$(layero).find('.layui-layer-input'), value=elem.val();
		if(value==='123456'){
			layer.close(index);
			layer.msg('密码正确');
		}else{
			elem.focus();
			layer.tips(value===''?'请输入':'密码错误',elem,{tips:1,time:2e3});
		}
	}
});

传统prompt方法无法监听输入

layer.prompt({
	title: '请输入密码:',
	formType: 1,
},function(value, index, elem){
	console.log(value);
	layer.close(index);
});
2026-02-21 星期六 农历正月初五