MySQL 相关命令

database MySQL MySQL 相关命令 数据库连接 mysql -u username -p password:***** mysql> 数据库操作 创建数据库: create database dbname charsetutf-8; 删除数据库: drop database dbname; 切换数据库: use dbname; 查看当前选择的数据库: select database(); 展示所有数据库: show databases; 表操作 查看所有表: show tables; 创建表: create table tbname( 列及类型约束 ); # 例如: create table students( id int auto_increment primary key, sname varcahr(10) not null ); 修改表: alter table tbname add|change|drop 列名 类型; # 例如: alter table students add birthday datetime; 删除表: drop table tbname; 查看表结构: desc tbname; 更改表名称: rename table old-tbname to new-tbname; 查看表的创建语句: show create table tbname; 数据操作 查询: select * from tbname; 增加: ...

MySQL 连接 Python

database MySQL Python MySQL 连接 Python 0.安装引入模块 使用接口Python DB API 安装mysql模块 pip install mysql-connector-python # python2.7,使用 Python-MySQL connector pip install pymysql # python3.4,安装 pymysql 模块 引入模块 import pymsql #python3.x import mysql.connector #py2.x 1.connection 对象 用于建立与数据库的连接 创建方法: # host:连接的 mysql 主机,本机填为 ‘localhost’ # port:连接的 mysql 主机的端口,默认为 3306 # user:连接的用户名 # passwd:连接的用户的密码 # db:连接的数据库名 conn = pymysql.Connect(host,port,user,passwd,db) # Python 3.x connection 对象的方法 close():关闭连接 commit():提交修改 rollback():回滚事务 cursor():返回 cursor 对象 2.cursor对象 用于执行语句 创建方法: cursor = conn.cursor() 方法 execute(op,[args]) # 执行一个数据库查询和命令 fetchone() # 取得结果集的下一行 fetchmany(size) # 取得结果集的下几行 fetchall() # 取得结果集的剩下的所有行 rowcount # 最近一次execute返回数据的行数或影响行数 close() # 关闭游标对象 属性 rowcount 只读属性,表示最近一次 execute() 执行后受影响的行数 connection 获得当前连接对象 3.查询的一般流程 select查询数据操作过程: 开始 创建connection 创建cursor 使用cursor.excute()执行select语句 使用cursor.fetch*()获取并处理数据 关闭cursor 关闭connection 结束 4.常见查询语句 # 增加 import pymysql try: conn = pymysql.Connect(host,port,user,passwd,db) cs1=conn.cursor() count=cs1.execute("insert into students(sname) values('张良')") print(count) conn.commit() cs1.close() conn.close() except Exception,e: print e.message # 删除 # -*- coding: utf-8 -*- import pymysql try: conn = pymysql.Connect(host,port,user,passwd,db) cs1=conn.cursor() count=cs1.execute("delete from students where id=6") print(count) conn.commit() cs1.close() conn.close() except Exception,e: print e.message # 查询一行数据 #-*- coding: utf-8 -*- import pymysql try: conn = pymysql.Connect(host,port,user,passwd,db) cur=conn.cursor() cur.execute('select * from students where id=7') result=cur.fetchone() print() cur.close() conn.close() except Exception,e: print e.message # 查询多行数据 #-*- coding: utf-8 -*- import pymysql try: conn = pymysql.Connect(host,port,user,passwd,db) cur=conn.cursor() cur.execute('select * from students') result=cur.fetchall() print(result) cur.close() conn.close() except Exception,e: print e.message 5.SQL 语句参数化 以参数传递的方式执行 sql 脚本,为之后的封装打基础 例如: #-*- coding: utf-8 -*- import pymysql try: conn = pymysql.Connect(host,port,user,passwd,db) cs1=conn.cursor() sname=raw_input("请输入学生姓名:") #参数 params=[sname] #参数封装成列表 count=cs1.execute('insert into students(sname) values(%s)',params) #%传参 print(count) conn.commit() cs1.close() conn.close() except Exception,e: print e.message 6.封装 将常见的语句封装成方法,以传参的方式执行语句,防注入 例如: #-*- coding: utf-8 -*- import pymysql class MysqlHelper(): def __init__(self,host,port,db,user,passwd,charset='utf8'): self.host=host self.port=port self.db=db self.user=user self.passwd=passwd self.charset=charset def connect(self): self.conn=MySQLdb.connect(host=self.host,port=self.port,db=self.db,user=self.user,passwd=self.passwd,charset=self.charset) self.cursor=self.conn.cursor() def close(self): self.cursor.close() self.conn.close() def get_one(self,sql,params=()): result=None try: self.connect() self.cursor.execute(sql, params) result = self.cursor.fetchone() self.close() except Exception, e: print e.message return result def get_all(self,sql,params=()): list=() try: self.connect() self.cursor.execute(sql,params) list=self.cursor.fetchall() self.close() except Exception,e: print e.message return list def insert(self,sql,params=()): return self.__edit(sql,params) def update(self, sql, params=()): return self.__edit(sql, params) def delete(self, sql, params=()): return self.__edit(sql, params) def __edit(self,sql,params): count=0 try: self.connect() count=self.cursor.execute(sql,params) self.conn.commit() self.close() except Exception,e: print e.message return count

nfs 卸载技巧

Linux file system nfs 卸载技巧 由于 nfs 的网络通信,一般来说,df或者ls等影响到磁盘的命令卡住,甚至卡死是因为 nfs 连接出现了问题。一般来说,要么服务端重启服务或者客户端重启服务就好。退而求其次的方法是umount nfs盘,但往往没办法直接搞定。一般会直接卡住或者提示 device busy。 那么我们就去伪造一个对端,我们可以搞个虚拟机,或者本机网络接口分配一个服务端端的ip,可以ping通。 ifconfig eth0:fakenfs 192.0.2.55 netmask 255.255.255.255 #其中 192.0.2.55 是 nfs 服务端的ip ip link set eth0 up 此时我们的机器需要开启nfs服务,Ubuntu的话就 apt install ntfs-kernel-server。 然后再尝试强制卸载 nfs 云盘:umount -fl /your/path。 之后需要把本机配置的 ip 给清掉: ifconfig eth0 del 192.0.2.55 ip link set eth0 down 参考 mount - 强制卸载NFS挂载目录 Linux强制卸载设备 nfs挂载无法卸载

nfs 的基本使用

Linux [[file system]] nfs 的基本使用 nfs 的架构 nfs 可以理解为“网盘”,即本地可以挂载远端的盘,不考虑物理上的io瓶颈,上下行带宽多大则io速度多快。典型的C/S的架构,运行过程中对CPU有依赖。 nfs 安装 # 服务端 sudo apt install nfs-kernel-server # 客户端 sudo apt install nfs-common nfs 使用 简单来说,分三步: 服务端创建文件系统 nfs配置文件中确定文件系统以及访问限制 客户端连接指定的nfs /etc/exports NFS服务端对分享目录的配置文件 /etc/exports.d NFS服务端对分享目录配置文件的扩展目录,值得注意的是:只有扩展名为.exports的文件会被NFS读取并应用,其他文件都会被忽略。 /var/lib/nfs/etab NFS对外分享目录的主配置文件,它是由exportfs命令维护的,其信息与NFS内核中的配置信息保持同步。注:请不要手动编辑该文件。 /var/lib/nfs/rmtab 客户端访问的目录列表,由NFS系统维护,请不要手动编辑。 root@localhost:~# cat /etc/exports # /etc/exports: the access control list for filesystems which may be exported # to NFS clients. See exports(5). # # Example for NFSv2 and NFSv3: # /srv/homes hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check) # # Example for NFSv4: # /srv/nfs4 gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check) # /srv/nfs4/homes gss/krb5i(rw,sync,no_subtree_check) # /mnt/nfs 192.168.0.0/24(rw,sync,no_subtree_check) $ sudo mount -t nfs host:/$dir $ddir 参考 如何在Ubuntu 18.04上设置NFS挂载 Linux 下的 NFS 系统简介

Oracle 的字符集与乱码

database Oracle Oracle 的字符集与乱码 最近有个需求,通过 python 处理数据,然后将数据存入到 oracle 11g 库中,中间遇到了一些编码相关的问题。由于可以直接登录上 oracle 所在的服务器,所以在本机上的 sqlplus 属于客户端,只是直接连接了本机,既然这样的话,就需要配置 NLS_LANG。 很多文章只会提到,将 NLS_LANG 配置改成 SIMPLIFIED CHINESE_CHINA.AL32UTF8,或者通过 os.environ 进行设置,这确实可以解决问题,但真正的原因并不是改个这个就完事了。 其实 oracle 数据库已经做了很多的字符转换工作,只要配置得当,那么数据就能正常存入,查询,转码的过程中也不会出问题,所以就必须知道,字符具体会在那些地方变更。 下面的这篇文章解决了我的问题,也让编码问题更为清晰。 字符集的作用 字符集问题一直叫人头疼,究其原因还是不能完全明白其运作原理。 在整个运行环节中,字符集在 3 个环节中发挥作用: 软件在操作系统上运作时的对用户的显示,此时采用操作系统定义的字符集进行显示。我们在系统 I/O 编程的时候经常要指定字符集,C# 中的 Text.Encoding=Encoding.Default 实际上就是告诉编译器,文本使用系统定义的默认字符集进行编码。sqlplus 也是运行在操作系统上的软件,当然要使用系统所指定的字符集对外显示内容。 数据向 Oracle 服务端传送前的通告。也就是 sqlplus 告诉服务器现在使用的字符集是什么。 数据流到达服务器后,按照服务器所使用的字符集自动翻译客户端的数据,然后存储进系统。 在客户端 sqlplus 和服务端传送数据,数据会按照服务端字符集进行翻译,这个过程是自动完成的不需要人工干预。任何时候,oracle 服务端总是按照自己的字符集设置来存取数据,客户端要想正确显示从服务端读取到的数据,也需要按照本地的字符集设置进行翻译,这个过程也是自动的。(重点是 按照本地的字符集设置) 服务器端需要采用合适的字符集进行数据存储,这个很容易理解,ASCII 字符集没办法用来存储中文汉字,因为它根本没有描述汉字所需要的编码空间。 问题常常存在于客户端与服务端通讯的过程中,sqlplus 作为运行在操作系统上的软件,无论是显示还是通讯,必然使用操作系统所使用的字符集设置。无论 sqlplus 设置的字符集,作用只有一个,那就是通告服务器端,为相互之间的字符集翻译做准备。 客户端的字符集设置是在NLS_LANG环境变量中设置的,客户读端的字符集可以和oracle客户端设置得不一样(本来人家就是自动翻译的),但是客户端字符集一定要和操作系统设置的字符集相匹配!(后面会有匹配表) 出现编码错误的原因 考虑一下,sqlplus 使用的是操作系统的字符集定义在显示和发送数据(假设是 TYPE_A),却告诉 oracle 服务器自己使用的字符集是 TYPE_B,oracle 服务器会怎么办?它会将客户端发送过来的 TYPE_A 数据当作 TYPE_B 字符集格式用自身的 TYPE_C 字符集进行翻译,然后再存储进系统,这就形成了乱码。反向的过程类似,Oracle服务器发出的数据格式没有疑问是 TYPE_C,但是客户端软件认为自己使用的编码是 TYPE_B 并进行了翻译,交给操作系统用 TYPE_A 字符集总的字符/编码映射关系进行翻译显示,最终导致了无法正确显示。 ...

paramiko 库的简单学习

[[Python]] [[Python Module]] paramiko 库的简单学习 paramiko,一个听起来不像英语的库,在诸多英文名的库中独立旗帜(官方解释为:“Paramiko” is a combination of the Esperanto words for “paranoid” and “friend”)。 它的主要功能就是实现对 ssh 协议的封装,能够在一个更高层面上,轻松地使用 ssh 以及 sftp 等功能。 一、安装 pip install paramiko 二、ssh 连接对象 1.使用密码连接 import paramiko # 这行代码可以生成连接日志,大部分情况下不需要 # paramiko.util.log_to_file('/tmp/sshout') ssh = paramiko.SSHClient() #这行代码的作用是允许连接不在know_hosts文件中的主机。 ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect("IP", port, "username", "password") 2.使用秘钥连接 import paramiko ssh = paramiko.SSHClient() ssh.connect('10.120.48.109', port, '用户名', key_filename='私钥') 三、ssh 执行指令 成功连接主机后,可以使用 ssh.exec_command(cmd) 的方法执行指令。 但默认返回三个 paramiko.channelfile 对象,我们可以用以下的方法读取数据或者写入确认等。 stdin, stdout, stderr = ssh.exec_command(cmd) # 如果成功,stdout会拿到输出的结果 for line in stdout.readlines(): print(line) # 执行过程中,可以使用以下方法进行确认,但此时的确认是对指令操作过程中的指令,例如“确认删除”等 stdin.write('Y') # 执行过程中若出现错误信息,报错信息会保存在stderr中 四、sftp 对象 paramiko 的 sftp 对象有多种生成方式。 倘若已有 ssh 对象,则: ...

pipenv+virtualenv配置全新的python环境

[[Python]] [[Linux]] 提示信息说三遍,本文最终的结果并不如人意,只是一些探索的过程记录。问题在于:当使用paramiko库时会提示openssh服务,而如果继续封装就有点违背当初的想法,应该有更优秀的解决方案。 提示信息说三遍,本文最终的结果并不如人意,只是一些探索的过程记录。问题在于:当使用paramiko库时会提示openssh服务,而如果继续封装就有点违背当初的想法,应该有更优秀的解决方案。 提示信息说三遍,本文最终的结果并不如人意,只是一些探索的过程记录。问题在于:当使用paramiko库时会提示openssh服务,而如果继续封装就有点违背当初的想法,应该有更优秀的解决方案。 pipenv+virtualenv配置全新的python环境 如果需要用python写个项目,并且允许其运行在稍低版本的Linux下,需要构建一套完整的虚拟环境,这中间有许多坑,花了一个星期终于打包出来了。 总的来说, 首先需要构造完整的python环境 再构造一个虚拟环境以便于启动 打包相应的glibc包 执行指令时用绝对路径来运行命令。 全篇遇到了不少坑,主要依据这篇文章进行操作制作python虚拟环境包,大体上没有什么问题,但是更注重于操作,而缺少一些解释,以及没有glibc包的打包过程。 创建完整的python环境 如果只是用virtualenv或者pipenv等工具直接创建虚拟环境,那么虚拟环境中的很多.py文件都只是软连接指向系统自带的python环境对应的.py文件。 这样的话,即便虚拟环境ok了,在另一个python版本不对或者没有python环境的机器上就会找不到对应的位置而报错。 可以通过查看虚拟环境中的lib目录得知指向的位置, 所以在创建虚拟环境前需要创建完整的python环境。 由于那篇博客关于安装环境说得足够详细,所以这里不再赘述,请直接从制作python虚拟环境包的Centos换源到安装python进行操作,相关依赖最好直接安装好,包括zlib和openssl相关的依赖,前者主要作用在打包压缩,后者主要作用在加密解密。 tips:虽然理论上可以通过python2.6直接装2.7甚至3.x的python,但是由于版本古老,可能(大概率)python2.6下的virtualenv工具无法使用,因为python2.6不支持字典推导式,会报语法错误。尽量使用python2.7以上的版本。 tips2: centos6.x系统使用的是python2.6.6,centos7系统使用的是python2.7.5。 tips3: MacOSX上的/tmp并不是/tmp,而是/private/tmp。 python2.6安装pip,可以直接wget https://bootstrap.pypa.io/2.6/get-pip.py下载get-pip.py文件,然后python get-pip.py来安装 构造一个虚拟环境 在指定的目录创建好完整的python环境了,为什么还需要构造虚拟环境? 以我(浅薄的眼光)看来,安装好的python环境可以通过绝对路径调用,但是很多环境还是会调用系统自身的,这样会造成一种紊乱,我们需要用虚拟环境打包这个完整环境,给它换个皮,创建个单独的空间。 由于那篇博客关于安装虚拟环境说得足够详细,所以这里不再赘述,请直接看制作python虚拟环境包的虚拟环境操作进行操作,一般情况下会安装的特别快,如果出现了ImportError: No module named zlib那就是缺少zlib环境。 还记得前文提到的,“虚拟环境中的很多.py文件都只是软连接指向系统自带的python环境对应的.py文件”,此时我们再去看下虚拟环境的lib目录,可以看出虽然有指向,但指向的是之前安装的完整环境,所以理论上可以在任何Linux环境上使用。 打包glibc环境 一般情况下,创建完虚拟环境,就可以直接上传到测试机器,然后激活环境source .venv/bin/activate,然后执行项目入口文件就行了python run.py,如果不出错,那么就可以了,以下的步骤不用看了。 但是我的测试机系统是rhel6.7,会出现一个python: /lib64/libc.so.6: version 'GLIBC_2.14' not found (required by python)错误。 既然是/lib64/libc.so.6下报的错误,那么应该和glibc版本有关系。 通过查找资料,这篇文章解决libc.so.6: version `GLIBC_2.14’ not found问题写得足够详细,原因是系统的glibc版本太低,软件编译时使用了较高版本的glibc引起的,解决方法上面的文章也可以解决,注意将glib安装到之前设置的文件夹下,方便打包。 tips:一般我会将虚拟环境安装在.venv下,而将lib相关的包安装在.lib下 用绝对路径来运行命令 既然glibc也打包了,那么上传到测试机器,如何让python使用高版本的glibc而不使用系统自带的glibc? 直接思路当然是 export LD_LIBRARY_PATH=/YourDir/.lib/glibc-2.14/lib:$LD_LIBRARY_PATH 强制先使用自己制定的glibc,某些时候可以成功,某些时候会报另外一种错, python: error while loading shared libraries: __vdso_time: invalid mode for dlopen(): Invalid argument 通过查找StackFlow,发现了一个人的遭遇和我一摸一样,Error while using a newer version of glibc,给出的理由是export LD_LIBRARY_PATH覆盖的范围太广了,python不知道该使用哪一个glibc,按照给出的解决方案,测试过了并没有什么用。 ...

pip安装mysql-python出现的问题

Python Python Module pip安装mysql-python出现的问题 使用 pip 安装 mysql-python 这个包,总是会遇到各种问题,以我个人为例,就在 deepin linux,MacOSX,rhel6.7 上遇到过三次,这里主要针对的是 EnvironmentError: mysql_config not found 问题,解决方案来自于stackoverflow。 问题描述 (mysite)zjm1126@zjm1126-G41MT-S2:~/zjm_test/mysite$ pip install mysql-python Downloading/unpacking mysql-python Downloading MySQL-python-1.2.3.tar.gz (70Kb): 70Kb downloaded Running setup.py egg_info for package mysql-python sh: mysql_config: not found Traceback (most recent call last): File "<string>", line 14, in <module> File "/home/zjm1126/zjm_test/mysite/build/mysql-python/setup.py", line 15, in <module> metadata, options = get_config() File "setup_posix.py", line 43, in get_config libs = mysql_config("libs_r") File "setup_posix.py", line 24, in mysql_config raise EnvironmentError("%s not found" % (mysql_config.path,)) EnvironmentError: mysql_config not found Complete output from command python setup.py egg_info: sh: mysql_config: not found Traceback (most recent call last): File "<string>", line 14, in <module> File "/home/zjm1126/zjm_test/mysite/build/mysql-python/setup.py", line 15, in <module> metadata, options = get_config() File "setup_posix.py", line 43, in get_config libs = mysql_config("libs_r") File "setup_posix.py", line 24, in mysql_config raise EnvironmentError("%s not found" % (mysql_config.path,)) EnvironmentError: mysql_config not found ---------------------------------------- Command python setup.py egg_info failed with error code 1 Storing complete log in /home/zjm1126/.pip/pip.log (mysite)zjm1126@zjm1126-G41MT-S2:~/zjm_test/mysite$ pip install mysql-python Downloading/unpacking mysql-python Running setup.py egg_info for package mysql-python sh: mysql_config: not found Traceback (most recent call last): File "<string>", line 14, in <module> File "/home/zjm1126/zjm_test/mysite/build/mysql-python/setup.py", line 15, in <module> metadata, options = get_config() File "setup_posix.py", line 43, in get_config libs = mysql_config("libs_r") File "setup_posix.py", line 24, in mysql_config raise EnvironmentError("%s not found" % (mysql_config.path,)) EnvironmentError: mysql_config not found Complete output from command python setup.py egg_info: sh: mysql_config: not found Traceback (most recent call last): File "<string>", line 14, in <module> File "/home/zjm1126/zjm_test/mysite/build/mysql-python/setup.py", line 15, in <module> metadata, options = get_config() File "setup_posix.py", line 43, in get_config libs = mysql_config("libs_r") File "setup_posix.py", line 24, in mysql_config raise EnvironmentError("%s not found" % (mysql_config.path,)) EnvironmentError: mysql_config not found ---------------------------------------- Command python setup.py egg_info failed with error code 1 Storing complete log in /home/zjm1126/.pip/pip.log 解决方案 Debian/Ubuntu sudo apt-get install libmysqlclient-dev 新版本(比如2018)的 Debian/Ubuntu ...

prometheus 的安装和配置

[[Prometheus]] [[Monitoring]] prometheus 的安装和配置 Prometheus 是一个开放性的监控解决方案,用户可以非常方便的安装和使用 Prometheus 并且能够非常方便的对其进行扩展。为了能够更加直观的了解 Prometheus Server,接下来我们将在本地部署并运行一个 Prometheus Server实例,通过 Node Exporter 采集当前主机的系统资源使用情况。 并通过 Grafana 创建一个简单的可视化仪表盘。 Prometheus 基于 Golang 编写,编译后的软件包,不依赖于任何的第三方依赖。用户只需要下载对应平台的二进制包,解压并且添加基本的配置即可正常启动 Prometheus Server。具体安装过程可以参考如下内容。 以 Centos7 为系统环境。 部署 prometheus 安装 prometheus wget https://github.com/prometheus/prometheus/releases/download/v2.9.2/prometheus-2.9.2.linux-amd64.tar.gz tar xzvf prometheus-2.9.2.linux-amd64.tar.gz mv prometheus-2.9.2.linux-amd64 /usr/local/prometheus 添加 prometheus 用户,非必须 groupadd prometheus useradd -g prometheus -m -d /var/lib/prometheus -s /sbin/nologin prometheus prometheus 系统服务配置 vim /etc/systemd/system/prometheus.service [Unit] Description=prometheus After=network.target [Service] Type=simple User=prometheus ExecStart=/usr/local/prometheus/prometheus -config.file=/usr/local/prometheus/prometheus.yml -storage.local.path=/var/lib/prometheus Restart=on-failure [Install] WantedBy=multi-user.target 启动 prometheus systemctl start prometheus systemctl status prometheus 部署 node_exporter 安装在将要监控的主机上。 ...

pyconcrete的简单学习

Python Python Module pyconcrete 的简单学习 pypi-pyconcrete 0.12.1 (个人感觉用这个库加密 python 程序的人不多。。。) (我在 MacOS python3.7.3 下又无法安装了) pyconcrete 是一个 python 文件加密库,它可以将常规的 .py 文件或 .pyc 文件加密为 .pye 文件,这样就无法直接打开源代码,避免了源代码的泄漏,也为 python 项目商用提供了解决方案。 该库在国内用的人不多,中文教程也少得可怜,Google 首页就两篇中文相关内容,一篇还是认识的人写的,一篇是对 GitHub 上对应项目的自述文件进行机翻,这里参考的是Falldog/pyconcrete。 安装 尽量不要使用 pip 安装!!! 我的几次安装经历,通过 pip 安装总是会出现各种各样的问题,可以试着通过 $ pip install pyconcrete --egg --install-option="--passphrase=<your passphrase>" 进行安装,或者下载源代码,进行安装,这可能是最快的安装方式。 保护你的 python 代码工作流 在 your_script.py 首行 import pyconcrete pyconcrete 将会自动和其他模块挂钩 当 your_script.py 开始导入其他模块,pyconcrete 首先会尝试寻找 MODULE.pye,然后通过 _pyconcrete.pyd 对MODULE.pye 进行解密 执行加密后的文件。 加密 只支持 AES 128 位加密 通过 OpenAES 加解密 用法 完整加密 将所有以 .py 结尾的文件转为 .pye。 $ pyconcrete-admin.py compile --source=<your py script> --pye $ pyconcrete-admin.py compile --source=<your py module dir> --pye 移除所有的 *.py 和 *.pyc 文件,或者将所有的 *.pye 文件移动到其他的文件夹 main.py 文件也会被加密为 main.pye,它无法被普通的 python 直接调用。必须使用 pyconcrete 来启动 main.pye。 pyconcrete main.pye src/*.pye # your libs 部分加密 将库文件被部分加密。 ...