解决golang xorm连接数据库 default addr for network localhost:3306 unknown

仅解决default addr for network unknown的错误,直接看代码

       var Orm *xorm.Engine
       var err error
       connection := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s",
		mysqlConfig["MysqlUser"].(string),
		mysqlConfig["MysqlPass"].(string),
		mysqlConfig["MysqlHost"].(string),
		mysqlConfig["MysqlPort"].(int),
		mysqlConfig["MysqlDb"].(string),
		mysqlConfig["MysqlCharSet"].(string),
	)
	fmt.Println(connection)
	Orm, err = xorm.NewEngine("mysql", connection)
	if err != nil {
		fmt.Println(err.Error())
	}
	Orm.ShowSQL(true)
	iris.RegisterOnInterrupt(func() {
		Orm.Close()
	})
即使用的字符串应该是
dbuser:dbpassword@tcp(dbhost:dbport)/databasename?charset=utf8

变量参考如下

  #Database
  #Mysql database
  MySql:
    MysqlUser: root
    MysqlPass: root
    MysqlHost: localhost
    MysqlPort: 3306
    MysqlDb: mydatabase
    MysqlCharSet: utf8mb4

以上解决

使用CodeIgniter4(CI4)遇到的BUG(2) curl_setopt_array cannot represent a stream of type Output as a STDIO FILE

使用CodeIgniter 的 curl

$this->curlClient = \Config\Services::curlrequest();
$result = $this->curlClient->request('GET', $list_domain, [
            CURLOPT_SSL_VERIFYHOST  =>  2,
            CURLOPT_SSL_VERIFYPEER  =>  1,
            CURLOPT_TRANSFERTEXT    =>  false,
        ]);

返回的报错信息是:

ErrorException
curl_setopt_array(): cannot represent a stream of type Output as a STDIO FILE*

导致此问题的 curlopt 是

define ('CURLOPT_STDERR', 10037);

找到 sendRequest函数, 在 system/HTTP/CURLRequest.php的805行

$ch = curl_init();
unset($curl_options[CURLOPT_STDERR]);  //添加此行
curl_setopt_array($ch, $curl_options);

这样就可以解决 cannot represent a stream of type Output as a STDIO FILE* 的错误了。

使用CURL的实例如下

$list_domain = str_replace('https', 'http', $list_domain);
$options = [
	'allow_redirects' => [
		'max'       => 15,
	],
	CURLOPT_SSL_VERIFYPEER  =>  false,
	CURLOPT_SSL_VERIFYHOST  =>  false,
	'headers' => [
		'User-Agent'    =>  'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
		'Accept'        =>  'text/html',
		'Referer'       =>  $list_domain,
	],
];
try {
	$result = $this->curlClient->request('GET', $list_domain, $options);
	$content = $result->getBody();
} catch (\Exception $e) {
	log_message_file('curl', $e->getMessage());
	//var_dump($e->getMessage());
	$context = null;
	if( substr($list_domain, 0, 5) == 'https') {
		$list_domain = str_replace('https://', 'http://', $list_domain);
		$options = array(
			'http' => array(
				'method' => 'GET',
				'header' => [
					'Content-type: text/html;charset=UTF-8',
					'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
					'Referer: ' . $list_domain,
				],
			),
			// 解决SSL证书验证失败的问题
			"ssl"=>array(
				"verify_peer"=>false,
				"verify_peer_name"=>false,
			)
		);
		$context = stream_context_create($options);
	}
	$content = file_get_contents($list_domain, false, $context);
}
return $content;

仅记录使用CodeIgniter4(CI4)遇到的BUG(1)

1.System/Entity.php 173行报错,报错原因使用的变量没有定义

"title": "ErrorException",
"type": "ErrorException",
"code": 500,
"message": "Undefined index: xxxx",
"file": "/system/Entity.php",
"line": 173,

修复此BUG,修改此行

if ($onlyChanged && $this->_original[$key] === null && $value === null)

修改为

if ($onlyChanged && ! isset($this->_original[$key]) && $value === null)

因为变量 $this->_original[$key] 不存在,直接使用会抛出异常。

mysql8.0授权用户,数据库,修改密码验证方式

仅记录mysql8.0授权用户,授权数据库表,修改连接数据库的验证格式

mysql8.0不能直接在授权数据库时创建新用户,需分开设置。

//错误执行代码
# grant all privileges on windigniter.* to 'windigniter'@'127.0.0.%' identified by 'windigniter.com' with grant option;
//mysql8授权数据库的报错信息
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'identified by 'windigniter.com' with grant option' at line 1

1.创建用户并设置密码。第一种简单操作, 已存在的用户用 alter user , 这种授权方式不能正常访问,除非 my.conf 里设置了

default_authentication_plugin=mysql_native_password

否则连接数据库时可能会报 The server requested authentication method unknown to,因为默认mysql8.0的默认加密方式是 caching_sha2_password

# create user 'windigniter'@'127.0.0.%' identified by 'windigniter.com';

使用一个能正常使用的授权语句 create/alter user

# create user 'windigniter'@'127.0.0.%' identified with mysql_native_password by 'windigniter.com';

2.授权数据库,授权数据库时不要带 identified 了,可以带 grant option

grant all privileges on yourdatabase.* to 'windigniter'@'127.0.0.%' with grant option;

单独修改账号的密码类型和创建账号如出一辙。

# alter user 'windigniter'@'127.0.0.%' identified with mysql_native_password by 'windigniter.com';

近期搭建服务器配置了几次mysql8.0,这里记录下,方便下次使用。

使用docker的那些坑

依然是拿建网站来说明docker搭建mysql,php,nginx。使用PHP搭建起来的网站,自然 nginx要依赖php, php要依赖mysql,先看下所需容器

# docker images
REPOSITORY    TAG        IMAGE ID            CREATED             SIZE
mysql        latest      990386cbd5c0        2 weeks ago         443MB
nginx        latest      53f3fd8007f7        2 weeks ago         109MB
php          fpm         5b747f4fb231        2 weeks ago         367MB

1.首先docker一个mysql,我使用的是mysql8.0,获取就不说了,这里直接docker

#运行mysql
docker run --name mysql8 -d -p 3306:3306 -v /usr/local/software/mysql/conf:/etc/mysql -v /data/logs:/logs -v /data/db_mysql:/var/lib/mysql -v /usr/local/software/mysql/mysql-files:/var/lib/mysql-files -v /etc/localtime:/etc/localtime:ro -e MYSQL_ROOT_PASSWORD='password' mysql

--name 是为新容器起的名字, -p 本地端口:容器端口  -v 本地路径:容器路径, -v可设置很多路径映射,配置信息,日志信息,数据库存放路径,等等,记得还要同步本地时间哦,不然东八区的总差8小时, -e 环境变量,这个ROOT password 可以让我们避免首次登陆时去log查询初始密码的麻烦。 如果发现docker启动不起来,可以使用下面命令查看原因。

docker logs -t mysql8

因为上面命令是我反复测试得到的命令,每次删除container后都可以直接使用则个命令启动,也不用担心重新配置信息或者数据丢失。出来下面的目录设置配置外,其他几个自定义目录都可以留空

# ls /usr/local/software/mysql/conf
conf.d  my.cnf

通过下面的命令进入到 mysql8的容器中,使用上面的初始密码登录,需要提醒的是mysql8授权用户的时候,需要先创建相关用户,在赋予权限,不可一次执行。

docker exec -it mysql8 /bin/bash

现在我已经能正常使用数据库了,接下来是docker php-fpm。使用下面的命令创建php-fpm的容器,拉取php的fpm的最新版就行了

#运行php-fpm
docker run --name php-fpm -p 9000:9000 -v /data/www:/etc/nginx -v /data/www:/data/www -v /usr/local/software/php/conf:/usr/local/etc -v /usr/local/software/php/extensions:/usr/local/lib/php/extensions -v /etc/localtime:/etc/localtime:ro --link mysql8:mysql -d php:fpm

/data/www是我部署的网站,里面含有好几个站点,这里直接全部映射过去,php/extensions的相关扩展需要在启动docker后,进入docker中安装,比如下面是进入php的docker中安装pdo_mysql的扩展命令,最好在进入安装前,先打开php.ini中相应的扩展,如果不打开,创建后会在一个子目录下创建一个相应配置文件,并设置为开启,虽然结果都一样,但最好还是能统一在php.ini中配置。

# docker exec -it php-fpm /bin/bash
# /usr/local/bin/docker-php-ext-install pdo_mysql

这个docker命令中 我们使用 --link mysql8:mysql来把 mysql的网络段和php的网络段打通,我们可以进入php的docker中查看 /etc/hosts 里面会帮我们绑定mysql的IP,这样php就能够正常访问到mysql的网络中,以便访问数据库。 这里面的坑就是很多时候我们访问访问php地址的时候都是找不到文件,这个时候就需要你确保是否将网站路径映射到php docker中的正确位置了, 可以看到我使用了两次 -v /data/www的映射,这是因为才安装好的php docker 默认访问网站根目录是/etc/nginx/html, 我/data/www/中有html文件夹,所以我只绑定了前面, 而 -v /data/www:/data/www 则是因为我自定义了其他站点配置信息里面的目录都使用的/data/www/zizhandian的方式。

现在我们已经配置了几个php站点,需要使用nginx开启这些站点了,这里我们需要 --link下 php-fpm 这样就能让nginx正常访问到 php docker的网络段。

#运行nginx
docker run --name nginx80 -d -p 80:80 -v /usr/local/software/nginx/conf:/etc/nginx -v /data/logs:/var/log/nginx -v /data/www:/data/www -v /etc/localtime:/etc/localtime:ro --link php-fpm:php nginx

经过上面几条命令 我们已经能够正常访问php的站点了,php也能正常访问数据库了。 现在出现了另外一个问题,我有些服务是在 宿主机上开启的,那docker 容器怎么正常和宿主机通信呢? 当我查找这方面资料时,都是一些配置 iptable 防火墙策略,或者别名lo网络,真的有那么麻烦吗,我也被折腾了好几天,其实很简单。 docker 容器里面定义的网络段首个地址就是主机IP。这个我之所以被折腾很久,就是因为所谓的内网地址作怪。

我当前这台服务器内外IP是 172.17.1.4,我们分别进入 docker php-fpm 和 nginx80中查看hosts就会发现他们里面也绑定了,172.17.1.2 mysql,172.17.1.3 php-fpm, 172.17.1.4 nginx80 怎么回事呢,如果我们连主机内网IP 172.17.1.4却连到了nginx80上, 这里我们必须理解在 docker中的网络段他们都是相互独立的,当我们使用--link后 他们之间会通过host 绑定并且会在同一个网段呢, 那么我们的宿主机在docker里就是 172.17.1.1 这个初始IP,所以如果想连主机的IP,需要配置docker网络段的其实IP,不是127.0.0.1 也不是内网地址172.17.1.4。

这次docker学习的心得差不多就这些了,終わり。