技术标签: SELinux MySQL 8 笔记 systemd mysql 数据库
首先看一下这个脚本的原内容:
[root@ic-source ~]$ cat /usr/bin/mysqld_pre_systemd
#! /bin/bash
# Copyright (c) 2015, 2022, Oracle and/or its affiliates.
#
# Script used by systemd mysqld.service to run before executing mysqld
#
get_option () {
local section=$1
local option=$2
local default=$3
local instance=$4
ret=$(/usr/bin/my_print_defaults ${
instance:+--defaults-group-suffix=@$instance} $section | \
grep '^--'${
option}'=' | cut -d= -f2- | tail -n 1)
[ -z "$ret" ] && ret=$default
echo $ret
}
install_validate_password_sql_file () {
local initfile
initfile="$(mktemp /var/lib/mysql-files/install-validate-password-plugin.XXXXXX.sql)"
chmod a+r "$initfile"
echo "SET @@SESSION.SQL_LOG_BIN=0;" > "$initfile"
echo "INSERT INTO mysql.component (component_id, component_group_id, component_urn) VALUES (1, 1, 'file://component_validate_password');" >> $initfile
echo $initfile
}
fix_mysql_upgrade_info () {
datadir=$(get_option mysqld datadir "/var/lib/mysql${instance:+-$instance}" $instance)
if [ -d "$datadir" ] && [ -O "$datadir/mysql_upgrade_info" ]; then
chown --reference="$datadir" "$datadir/mysql_upgrade_info"
if [ -x /usr/bin/chcon ]; then
/usr/bin/chcon --reference="$datadir" "$datadir/mysql_upgrade_info" > /dev/null 2>&1
fi
fi
}
install_db () {
# Note: something different than datadir=/var/lib/mysql requires SELinux policy changes (in enforcing mode)
# mysql_upgrade_info file should be owned by mysql user since MySQL 8.0.16
fix_mysql_upgrade_info
# No automatic init wanted
[ -e /etc/sysconfig/mysql ] && . /etc/sysconfig/mysql
[ -n "$NO_INIT" ] && exit 0
local instance=$1
datadir=$(get_option mysqld datadir "/var/lib/mysql${instance:+-$instance}" $instance)
log=$(get_option mysqld 'log[_-]error' "/var/log/mysql${instance:+-$instance}.log" $instance)
# Restore log, dir, perms and SELinux contexts
if [ ! -d "$datadir" -a ! -h "$datadir" -a "x$(dirname "$datadir")" = "x/var/lib" ]; then
install -d -m 0751 -omysql -gmysql "$datadir" || exit 1
fi
if [ ! -e "$log" -a ! -h "$log" -a x$(dirname "$log") = "x/var/log" ]; then
case $(basename "$log") in
mysql*.log) install /dev/null -m0640 -omysql -gmysql "$log" ;;
*) ;;
esac
fi
if [ -x /usr/sbin/restorecon ]; then
/usr/sbin/restorecon "$datadir"
[ -e "$log" ] && /usr/sbin/restorecon "$log"
for dir in /var/lib/mysql-files /var/lib/mysql-keyring ; do
if [ -x /usr/sbin/semanage -a -d /var/lib/mysql -a -d $dir ] ; then
/usr/sbin/semanage fcontext -a -e /var/lib/mysql $dir >/dev/null 2>&1
/sbin/restorecon -r $dir
fi
done
fi
# If special mysql dir is in place, skip db install
[ -d "$datadir/mysql" ] && exit 0
# Create initial db and install validate_password plugin
initfile="$(install_validate_password_sql_file)"
/usr/sbin/mysqld ${instance:+--defaults-group-suffix=@$instance} --initialize \
--datadir="$datadir" --user=mysql --init-file="$initfile"
rm -f "$initfile"
# Generate certs if needed
if [ -x /usr/bin/mysql_ssl_rsa_setup -a ! -e "${datadir}/server-key.pem" ] ; then
/usr/bin/mysql_ssl_rsa_setup --datadir="$datadir" --uid=mysql >/dev/null 2>&1
fi
exit 0
}
install_db $1
exit 0
/usr/bin/my_print_defaults
,打印某个 MySQL 程序的默认参数,通过 get_option()
调用。get_option()
用来获取 MySQL 实例的选项配置。install_validate_password_sql_file ()
用来创建并执行为 `root`@`localhost` 用户生成随机密码的 MySQL 初始化语句。- fix_mysql_upgrade_info ()
用来修复 mysql_upgrade_info 的文件属主和 SELinux 安全上下文。install_db ()
是主函数,负责整个 MySQL 实例的初始化安装工作,datadir
不以目录形式存在,且不以符号链接存在,且绝对路径前缀不是/var/lib
则创建一个名为/var/lib/mysql-实例名
的默认数据目录;使用类似的判断条件,会创建一个/var/log/mysql-实例名.log
的默认错误日志文件。这些是为 SELinux 环境考虑的。install_db ()
还会创建 SSL/RSA 证书。如果存在 /etc/sysconfig/mysql
文件,则运行它,之后判断如果NO_INIT
环境变量的值为非空,则直接以 0 为退出状态退出 mysqld_pre_systemd 主进程。有问题的点在于脚本默认会创建数据目录和日志文件,却没有在后续使用时显式指定使用它们(因为用户没有配置它们):
/tmp
)。虽然 MySQL 会给它们赋予默认值,但在特定情况下会无法向错误日志文件记录错误日志。/usr/lib/systemd/system/[email protected]
中启动 mysqld 服务时只使用了MYSQLD_OPTS
环境变量的值而并没有显式指定默认创建的数据目录和错误日志文件,以及可能存在的用户自定义tmpdir
临时目录选项。这点会在后文介绍 [email protected] 部分体现。[root@ic-source ~]$ cat /usr/lib/systemd/system/[email protected]
# Copyright (c) 2016, 2022, Oracle and/or its affiliates.
#
# systemd service file for MySQL forking server
#
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
Type=notify
# Disable service start and stop timeout logic of systemd for mysqld service.
TimeoutSec=0
# Execute pre and post scripts as root
PermissionsStartOnly=true
# Needed to create system tables
ExecStartPre=/usr/bin/mysqld_pre_systemd %I
# Start main service
ExecStart=/usr/sbin/mysqld --defaults-group-suffix=@%I $MYSQLD_OPTS
# Use this to switch malloc implementation
EnvironmentFile=-/etc/sysconfig/mysql
# Sets open_files_limit
LimitNOFILE = 10000
Restart=on-failure
RestartPreventExitStatus=1
# Set enviroment variable MYSQLD_PARENT_PID. This is required for restart.
Environment=MYSQLD_PARENT_PID=1
PrivateTmp=false
如果我将执行部分的内容修改为:
ExecStart=/usr/sbin/mysqld --defaults-group-suffix=@%I --datadir=/var/lib/mysql-%I $MYSQLD_OPTS
则可以直接运行,否则必须指定 datadir
选项。同样的方法,也适用于错误日志。
mysqld 的默认逻辑是用户必须指定 datadir
、log-error
,且如果需要使用自定义的临时文件目录 tmpdir
,必须提前创建并授予适当文件访问权限。而如果是这样设计的,就应该在文档中有所声明,而事实是 MySQL 并没有有关这些内容的明确清晰的声明。此外,[email protected] 的设计逻辑与 mysql_pre_systemd 中默认初始化的设计逻辑难以自洽,即既然后者初始化了数据目录和错误日志文件,为什么不在启动 mysqld 服务时如未定义这些选项则默认使用呢?
datadir
和 log-error
的 bugs在 /etc/my.cnf
中添加如下内容:
[mysqld@test01]
#datadir=/var/lib/mysql-test01
port=3309
mysqlx_port=33090
admin_port=33092
#socket=/var/lib/mysql-test01/mysql.sock
#log-error=/var/log/mysql-test01.log
innodb_buffer_pool_size=256M
innodb_redo_log_capacity=100M
innodb_flush_method=O_DIRECT_NO_FSYNC
执行如下命令,验证当前不存在 /var/libmysql-test01
目录及/var/log/mysql-test01.log
:
[root@ic-source lib]$ ll /var/lib/mysql-test01
[root@ic-source lib]$ ll /var/log/mysql-test01.log
使用 systemctl 启动 MySQL 实例 test01 :
[root@ic-source lib]$ systemctl start mysqld@test01
一定会启动失败,systemctl status [email protected] -l
查看错误日志:
再看一下journalctl -xe
:
一般看到 polkitd[679]: Unregistered Authentication Agent for unix-process
这种字样的报错,不是文件属主、权限问题,就是文件/目录不存在。[Warning]
里还说了因没找到而生成了一个新的 Server UUID ,那么它在哪呢?在 /var/lib/mysql
这个 mysqld.service 的默认目录下。可以通过 server-uuid 内容证明。而另一个 /var/lib/mysql-test01/auto.cnf
为实例初始化时生成的文件,也即应该查找的文件。
同时,我们查看一下默认创建的错误日志文件是否存在。输出结果证明存在,但内容为空。
[root@ic-source lib]$ ll /var/log/mysql-test01.log
下面我们手动启动一下:
[root@ic-source lib]$ mysqld --defaults-group-suffix=@test01 --datadir=/var/lib/mysql-test01 --user=mysql $MYSQLD_OPTS &
注释
$MYSQLD_OPTS
默认值为空,可以不加。
由上图可知,可以正常启动,但使用的 socket 均为默认配置,其中包括 MySQL 标准协议的 socket(/var/lib/mysql/mysql.sock
) 和 MySQL X 协议的 socket(/run/mysqld/mysqlx.sock
) 。这里因为我没有启动 mysqld.service ,且已启动的实例中有一个没有显式指定 mysqlx_socket
选项,所以只对 mysqlx.sock 文件已被其他进程使用进行了报错。
启动是启动了,可我们怎么访问呢?
注意,因为初始化后错误日志仍为空,证明刚刚的初始化操作将初始化信息输出到 stderr 里了。我们需要使用 journalctl -xe
找到初始化的 root@`localhost` 用户的临时密码,然后使用 mysql 客户端访问即可。
[root@ic-source ~]$ mysql -uroot -S /var/lib/mysql/mysql.sock -p
此时已证明可以正常启动了,也进而证明了我的猜想。所以后面的修改初始密码等步骤不做了,我们停止这个进程,并删除掉这个实例相关的文件。
注意
这里还说明一个问题,如果我们要在一台主机上创建并启动多个 MySQL 实例,我们应还需要显式为每个实例指定不同的 MySQL X 协议 的mysqlx_port
和mysqlx_socket
选项 ,而不只是 MySQL 标准协议 的port
和socket
。
[root@ic-source lib]$ ps -ef |grep test01 |grep -v grep |awk '{print $2}' |kill -9 $!
[root@ic-source ~]$ rm -rf /var/lib/mysql-test01/
[root@ic-source ~]$ rm -f /var/log/mysql-test01.log
# 这里我删除了/var/lib/mysql目录下除目录以外的所有文件。如果你的目的不一样,请自行删除
[root@ic-source mysql]$ ll /var/lib/mysql|grep -v "^d"|awk -F \ '{print $9}'|while read i;do rm -f $i;done
注意
即便刚刚我们启动了 mysqld ,但错误日志默认使用的是 stderr 而非 mysqld_pre_systemd 创建的/var/log/mysql-test01.log
文件,除非你在启动 mysqld 时在命令行显式指定--log-error
选项。
国内一般都会关闭 SELinux,即便是生产环境,我这个测试环境之前也是改成关闭了的,现在改回默认值:
[root@ic-source lib]$ vi /etc/sysconfig/selinux
SELINUX=enforcing
SELINUXTYPE=targeted
再在根目录 /
下创建一个名为 .autorelabel
空文件,重新刷新SELinux 安全上下文标记。
touch /.autorelabel
说明
.autorelabel
文件用于重新标记 SElinux 的文件系统。
可能在如下场景使用到它:
- 重启系统时,它会自动重新标记 SElinux 的文件系统。
- 首次为 SELinux 标记文件系统时。
- 在不同类型的策略之间切换时发生,例如从禁用策略更改为强制策略(即由
disabled
切换到enforcing
)。
然后重启,有文章说可能需要很长时间,因为要为操作系统中的所有文件重建 SELinux 安全上下文,可笔者并未遇到,启动很快。
将 SELinux 从 targeted
修改为 enforcing
的具体操作过程详见 【MySQL 安全】如何与 SELinux 配合使用 。
在正确配置了 MySQL 有关 SELinux 的配置后,可以顺利启动所有如下 /etc/my.cnf
中定义的 MySQL 服务器实例。
[mysqld@ics_pc_pri]
port=3306
datadir='/var/lib/mysql/data/ics_pc_pri'
tmpdir='/var/lib/mysql/tmp/ics_pc_pri'
socket='/var/lib/mysql/data/ics_pc_pri/mysql.sock'
log-error='/var/log/mysql-ics_pc_pri.log'
slow_query_log_file='/var/log/slow_query-ics_pc_pri.log'
log-bin='ics_pc_pri-bin'
innodb_buffer_pool_size=2048M
innodb_redo_log_capacity=1G
innodb_flush_method=O_DIRECT_NO_FSYNC
[mysqld@ics_rc01_pri]
port=3307
datadir='/var/lib/mysql/data/ics_rc01_pri'
tmpdir='/var/lib/mysql/tmp/ics_rc01_pri'
socket='/var/lib/mysql/data/ics_rc01_pri/mysql.sock'
mysqlx_port=33070
mysqlx_socket='/var/lib/mysql/data/ics_rc01_pri/mysqlx.sock'
admin_port=33072
log-error='/var/log/mysql-ics_rc01_pri.log'
slow_query_log_file='/var/log/slow_query-ics_rc01_pri.log'
log-bin='ics_rc01_pri-bin'
innodb_buffer_pool_size=1024M
innodb_redo_log_capacity=100M
innodb_flush_method=O_DIRECT_NO_FSYNC
[mysqld@replica01]
datadir=/var/lib/mysql/replica01
port=3308
mysqlx_port=33080
mysqlx_socket=/var/lib/mysql/replica01/mysqlx.sock
admin_port=33082
socket=/var/lib/mysql/replica01/mysql.sock
log-error=/var/log/mysql-replica01.log
innodb_buffer_pool_size=256M
innodb_redo_log_capacity=100M
innodb_flush_method=O_DIRECT_NO_FSYNC
[mysqld@test01]
datadir=/var/lib/mysql-test01
socket=/var/lib/mysql-test01/mysql.sock
port=3309
mysqlx_socket=/var/lib/mysql-test01/mysqlx.sock
mysqlx_port=33090
admin_port=33092
#log-error=/var/log/mysql-test01.log
log-error=/var/lib/mysql-test01/mysql-test01.log
innodb_buffer_pool_size=256M
innodb_redo_log_capacity=100M
innodb_flush_method=O_DIRECT_NO_FSYNC
由此可见:
systemd 或 SELinux 并没有强制单元名称的分隔符必须且仅为 @
,而可以是 _
、@
、.
、-
等(我按查阅的 systemd 说明文章只尝试了这四个,可能其他的特殊字符也适用)。
SELinux 默认并没有强制 MySQL 相关目录及文件的位置,而是 MySQL 提供的策略限制:
笔者使用自定义数据目录、临时文件目录和错误日志位置,均可以启动 MySQL 服务。
参考
有效的单元名称由一个“名称前缀”、一个点(“.”)和一个指定单元类型的后缀组成。“单元前缀”必须包含一个或多个有效字符( ASCII 字母、数字、“:”、“-”、“_”、“.”和“\”)。单元名称(包括后缀)的总长度不得超过 256 个字符。类型后缀必须是“.service”、“.socket”、“.device”、“.mount”、“.automount”、“.swap”、“.target”、“.path”、“.timer”、“.slice”或“.scope” 之一。
systemd 对单元名称中的“实例名”部分并没有明确要求,因而可以是任何 ASCII 字符(估计控制字符不行),但建议沿用其对“单元前缀”的命名规则限制。
--datadir
命令行选项(不建议)sed -i -e 's|^\(ExecStart=/usr/sbin/mysqld --defaults-group-suffix=@%I\)|\1 --datadir=/var/lib/mysql-%I|g' /usr/lib/systemd/system/[email protected]
该方法最简单,但限制 datadir
必须使用 /var/lib/mysql-实例名
的格式,在选项文件中使用其他自定义的 datadir
不会生效,且会报错。因为命令行选项的优先级高于选项文件的优先级,详见 MySQL 选项优先级 及4.2.2 指定程序选项 。
datadir
选项(建议)使用如下内容替换 /usr/bin/mysqld_pre_systemd
脚本内容:
#! /bin/bash
# Copyright (c) 2015, 2022, Oracle and/or its affiliates.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License, version 2.0,
# as published by the Free Software Foundation.
#
# This program is also distributed with certain software (including
# but not limited to OpenSSL) that is licensed under separate terms,
# as designated in a particular file or component or in included license
# documentation. The authors of MySQL hereby grant you an additional
# permission to link the program and your derivative works with the
# separately licensed software that they have included with MySQL.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License, version 2.0, for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# Script used by systemd mysqld.service to run before executing mysqld
get_option () {
local section=$1
local option=$2
local default=$3
local instance=$4
ret=$(/usr/bin/my_print_defaults ${
instance:+--defaults-group-suffix=@$instance} $section | \
grep '^--'${
option}'=' | cut -d= -f2- | tail -n 1)
[ -z "$ret" ] && ret=$default && sed -i -E \
"/^\[mysqld@${instance}\]\$/a ${option}=$ret" /etc/my.cnf
echo $ret
}
install_validate_password_sql_file () {
local initfile
initfile="$(mktemp /var/lib/mysql-files/install-validate-password-plugin.XXXXXX.sql)"
chmod a+r "$initfile"
echo "SET @@SESSION.SQL_LOG_BIN=0;" > "$initfile"
echo "INSERT INTO mysql.component (component_id, component_group_id, component_urn) VALUES (1, 1, 'file://component_validate_password');" >> $initfile
echo $initfile
}
fix_mysql_upgrade_info () {
datadir=$(get_option mysqld datadir "/var/lib/mysql${instance:+-$instance}" $instance)
if [ -d "$datadir" ] && [ -O "$datadir/mysql_upgrade_info" ]; then
chown --reference="$datadir" "$datadir/mysql_upgrade_info"
if [ -x /usr/bin/chcon ]; then
/usr/bin/chcon --reference="$datadir" "$datadir/mysql_upgrade_info" > /dev/null 2>&1
fi
fi
}
install_db () {
# Note: something different than datadir=/var/lib/mysql requires SELinux policy changes (in enforcing mode)
# mysql_upgrade_info file should be owned by mysql user since MySQL 8.0.16
fix_mysql_upgrade_info
# No automatic init wanted
[ -e /etc/sysconfig/mysql ] && . /etc/sysconfig/mysql
[ -n "$NO_INIT" ] && exit 0
local instance=$1
datadir=$(get_option mysqld datadir "/var/lib/mysql${instance:+-$instance}" $instance)
log=$(get_option mysqld 'log[_-]error' "/var/log/mysql${instance:+-$instance}.log" $instance)
tmpdir=$(get_option mysqld tmpdir "/tmp" $instance)
socket=$(get_option mysqld socket "/var/lib/mysql${instance:+-$instance}/mysql.sock" $instance)
# Restore log, dir, perms and SELinux contexts
if [ ! -d "$datadir" -a ! -h "$datadir" -a "x$(dirname "$datadir")" = "x/var/lib" ]; then
install -d -m 0751 -omysql -gmysql "$datadir" || exit 1
fi
if [ ! -e "$log" -a ! -h "$log" -a x$(dirname "$log") = "x/var/log" ]; then
case $(basename "$log") in
mysql*.log) install /dev/null -m0640 -omysql -gmysql "$log" ;;
*) ;;
esac
fi
if [ ! -d "$tmpdir" -a ! -h "$tmpdir" ]; then
install -d -m 0751 -omysql -gmysql "$tmpdir" || exit 1
fi
if [ -x /usr/sbin/restorecon ]; then
/usr/sbin/restorecon "$datadir"
/usr/sbin/restorecon "$tmpdir"
[ -e "$log" ] && /usr/sbin/restorecon "$log"
[ -e "$socket" ] && /usr/sbin/restorecon "$socket"
for dir in /var/lib/mysql-files /var/lib/mysql-keyring ; do
if [ -x /usr/sbin/semanage -a -d /var/lib/mysql -a -d $dir ] ; then
/usr/sbin/semanage fcontext -a -e /var/lib/mysql $dir >/dev/null 2>&1
/sbin/restorecon -r $dir
fi
done
fi
# If special mysql dir is in place, skip db install
[ -d "$datadir/mysql" ] && exit 0
# Create initial db and install validate_password plugin
initfile="$(install_validate_password_sql_file)"
/usr/sbin/mysqld ${instance:+--defaults-group-suffix=@$instance} --initialize \
--datadir="$datadir" --user=mysql --init-file="$initfile" \
--tmpdir="$tmpdir" --log-error="$log" --socket="$socket"
rm -f "$initfile"
# Generate certs if needed
if [ -x /usr/bin/mysql_ssl_rsa_setup -a ! -e "${datadir}/server-key.pem" ] ; then
/usr/bin/mysql_ssl_rsa_setup --datadir="$datadir" --log-error="$log" --uid=mysql >/dev/null 2>&1
fi
exit 0
}
install_db $1
exit 0
笔者已将如上脚本 pull request 到 GitHub 上的 mysql/mysql-server 仓库了。
文章浏览阅读3.5k次,点赞2次,收藏13次。为了从FTP服务器下载文件,需要要实现一个简单的FTP客户端。FTP(文件传输协议) 是 TCP/IP 协议组中的应用层协议。FTP协议使用字符串格式命令字,每条命令都是一行字符串,以“\r\n”结尾。客户端发送格式是:命令+空格+参数+"\r\n"的格式服务器返回格式是以:状态码+空格+提示字符串+"\r\n"的格式,代码只要解析状态码就可以了。读写文件需要登陆服务器,特殊用..._ftp 登录返回230
文章浏览阅读648次。前提:systemctl stop firewalld 关闭防火墙关闭selinux查看getenforce临时关闭setenforce 0永久关闭sed-i'/SELINUX/s/enforcing/disabled/'/etc/selinux/configselinux的三种模式enforcing:强制模式,SELinux 运作中,且已经正确的开始限制..._centos7 安装rabbitmq3.6.5
文章浏览阅读5.8k次。满意答案s55f2avsx2017.09.05采纳率:46%等级:12已帮助:5646人新版Android Studio/IntelliJ IDEA可以直接导入eclipse项目,不再推荐使用eclipse导出gradle的方式2启动Android Studio/IntelliJ IDEA,选择 import project3选择eclipse 项目4选择 create project f..._android studio 项目导入idea 看不懂安卓项目
文章浏览阅读860次,点赞2次,收藏6次。AI大模型技术已经在自然语言处理、计算机视觉、多模态交互等领域取得了显著的进展和成果,同时也引发了一系列新的挑战和问题,如数据质量、计算效率、知识可解释性、安全可靠性等。城市运维涉及到多个方面,如交通管理、环境监测、公共安全、社会治理等,它们需要处理和分析大量的多模态数据,如图像、视频、语音、文本等,并根据不同的场景和需求,提供合适的决策和响应。知识搜索有多种形式,如语义搜索、对话搜索、图像搜索、视频搜索等,它们可以根据用户的输入和意图,从海量的数据源中检索出最相关的信息,并以友好的方式呈现给用户。_ai大模型应用开发
文章浏览阅读8.2k次,点赞12次,收藏121次。为什么要测量阻抗呢?阻抗能代表什么?阻抗测量的注意事项... ...很多人可能会带着一系列的问题来阅读本文。不管是数字电路工程师还是射频工程师,都在关注各类器件的阻抗,本文非常值得一读。全文13000多字,认真读完大概需要2小时。一、阻抗测试基本概念阻抗定义:阻抗是元器件或电路对周期的交流信号的总的反作用。AC 交流测试信号 (幅度和频率)。包括实部和虚部。图1 阻抗的定义阻抗是评测电路、元件以及制作元件材料的重要参数。那么什么是阻抗呢?让我们先来看一下阻抗的定义。首先阻抗是一个矢量。通常,阻抗是_阻抗实部和虚部
文章浏览阅读955次。前面章节分享试用了pyzero,pygame但随着想增加更丰富的游戏内容,好多还要进行自己编写类,从今天开始解绍一个新的python游戏库arcade模块。通过此次的《连连看》游戏实现,让我对swing的相关知识有了进一步的了解,对java这门语言也有了比以前更深刻的认识。java的一些基本语法,比如数据类型、运算符、程序流程控制和数组等,理解更加透彻。java最核心的核心就是面向对象思想,对于这一个概念,终于悟到了一些。_arcade语言 like
文章浏览阅读1.1k次。源码简介与安装说明:2021增强版短视频去水印源码 去水印微信小程序源码网站 去水印软件源码安装环境(需要材料):备案域名–服务器安装宝塔-安装 Nginx 或者 Apachephp5.6 以上-安装 sg11 插件小程序已自带解析接口,支持全网主流短视频平台,搭建好了就能用注:接口是公益的,那么多人用解析慢是肯定的,前段和后端源码已经打包,上传服务器之后在配置文件修改数据库密码。然后输入自己的域名,进入后台,创建小程序,输入自己的小程序配置即可安装说明:上传源码,修改data/_去水印机要增强版
文章浏览阅读557次。1. 触发器是FPGA存储数据的基本单元2. 触发器作为时序逻辑的基本元件,官方提供了丰富的配置方式,以适应各种可能的应用场景。_fdre #(.init(1'b0) // initial value of register (1'b0 or 1'b1) ) fdce_osc (
文章浏览阅读560次。本该是不同编译器结果不同,但是尝试了g++ msvc都是先计算c,再计算b,最后得到a+b+c是经过赋值以后的b和c参与计算而不是6。由上表可知,将q复制到p数组可以表示为:*p++=*q++,*优先级高,先取到对应q数组的值,然后两个++都是在后面,该行运算完后执行++。在电脑端编译完后会分为text data bss三种,其中text为可执行程序,data为初始化过的ro+rw变量,bss为未初始化或初始化为0变量。_嵌入式面试笔试c语言知识点
文章浏览阅读2.3k次。57 Things I've Learned Founding 3 Tech CompaniesJason Goldberg, Betashop | Oct. 29, 2010, 1:29 PMI’ve been founding andhelping run techn_mature
文章浏览阅读1.9k次。问题:先讲下需求,有若干个文本文件(txt或者csv文件等),每行代表一条数据,现在希望能合并成 1 个文本文件,且需要去除重复行。分析:一向奉行简单原则,如无必要,绝不复杂。如果数据量不大,那么如下两条命令就可以搞定合并:cat a.txt >> new.txtcat b.txt >> new.txt……去重:cat new...._python 超大文本合并
文章浏览阅读489次。这个过渡页是第一次打开小程序展示的,点击某个小程序前把手机的开发者->network link conditioner->enable & very bad network 就会在停在此页。比如《支付宝运动》这个小程序先看这个类的.h可以看到它继承于DTViewController点击左上角返回的方法- (void)back;#import "DTViewController.h"#import "APBaseLoadingV..._类似支付宝页面过度加载页