生命之中的最大错误在于:终日担心犯错误。— 爱尔伯特·哈伯德 (Elbert Hubbard 1856-1915),《笔记》
# 什么是supervisord
Supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启。它是通过fork/exec的方式把这些被管理的进程当作supervisor的子进程来启动,这样只要在supervisor的配置文件中,把要管理的进程的可执行文件的路径写进去即可。也实现当子进程挂掉的时候,父进程可以准确获取子进程挂掉的信息的,可以选择是否自己启动和报警。supervisor还提供了一个功能,可以为supervisord或者每个子进程,设置一个非root的user,这个user就可以管理它对应的进程。
# 怎么安装
CentOS: yum install supervisor
其它:
1:easy_install 安装:
easy_install supervisor
2:pip 安装:
pip install supervisor
3:Debian / Ubuntu可以直接通过apt安装:
apt-get install supervisor
# 如何配置
用yum安装的,需要看看conf里的include
[include]
files = supervisord.d/*.ini
在 supervisord.d 目录里创建 task.ini 即可,比如:
directory 执行command之前切换到此目录
command 执行命令
autostart 自动启动
autorestart 自动重启
user 执行的用户
# 服务管理
记得把服务做成自动启动的
# 服务监控
conf 文件有一个选项开启,可以有网页控制后台
;[inet_http_server] ; inet (TCP) server disabled by default
;port=127.0.0.1:9001 ; (ip_address:port specifier, *:port for all iface)
解开注释即可,重启后,我们可以访问到,但不是公开的,所以可以用ssh转换一下
比如:
ssh root@your-server.com -L9001:127.0.0.1:9001
那你就可以访问 127.0.0.1:9001 就相当于在服务器访问 127.0.0.1:9001 了
# 详细配置参数参考
https://www.cnblogs.com/zhoujinyi/p/6073705.html
Supervisor是用Python开发的一套通用的进程管理程序,能将一个普通的命令行进程变为后台daemon,并监控进程状态,异常退出时能自动重启。它是通过fork/exec的方式把这些被管理的进程当作supervisor的子进程来启动,这样只要在supervisor的配置文件中,把要管理的进程的可执行文件的路径写进去即可。也实现当子进程挂掉的时候,父进程可以准确获取子进程挂掉的信息的,可以选择是否自己启动和报警。supervisor还提供了一个功能,可以为supervisord或者每个子进程,设置一个非root的user,这个user就可以管理它对应的进程。
# 怎么安装
CentOS: yum install supervisor
其它:
1:easy_install 安装:
easy_install supervisor
2:pip 安装:
pip install supervisor
3:Debian / Ubuntu可以直接通过apt安装:
apt-get install supervisor
# 如何配置
用yum安装的,需要看看conf里的include
[include]
files = supervisord.d/*.ini
在 supervisord.d 目录里创建 task.ini 即可,比如:
[program:daemon]
directory=/Data/webapps/aslibra.com/
command=/usr/bin/php index.php messages daemon
autostart=true
autorestart=true
stderr_logfile=/Data/logs/daemon_stderr.log
stdout_logfile=/Data/logs/daemon_stdout.log
user=www
directory=/Data/webapps/aslibra.com/
command=/usr/bin/php index.php messages daemon
autostart=true
autorestart=true
stderr_logfile=/Data/logs/daemon_stderr.log
stdout_logfile=/Data/logs/daemon_stdout.log
user=www
directory 执行command之前切换到此目录
command 执行命令
autostart 自动启动
autorestart 自动重启
user 执行的用户
# 服务管理
记得把服务做成自动启动的
service supervisord restart
chkconfig supervisord on
chkconfig supervisord on
# 服务监控
conf 文件有一个选项开启,可以有网页控制后台
;[inet_http_server] ; inet (TCP) server disabled by default
;port=127.0.0.1:9001 ; (ip_address:port specifier, *:port for all iface)
解开注释即可,重启后,我们可以访问到,但不是公开的,所以可以用ssh转换一下
比如:
ssh root@your-server.com -L9001:127.0.0.1:9001
那你就可以访问 127.0.0.1:9001 就相当于在服务器访问 127.0.0.1:9001 了
# 详细配置参数参考
https://www.cnblogs.com/zhoujinyi/p/6073705.html
Docker是个伟大的发明,以前,运维的理念是软件层次的,现在变成了功能层次的。
以前要开一个网站服务,需要安装php/mysql/nginx,自己编译,需要花时间收集下载地址或者文件,记录编译参数,做成批处理脚本减轻重复操作。好点的方式是有人做了个合集,比如lnmp的包,这个也让人省心不少,还有一些小激动,运行一个命令就安装好了。
如今,docker有各种各样的image,都配置好了软件,需要nginx,下载个nginx的image即可,运行就有,就两句话解决了。
需要php支持,安装一个php的image,一个个软件都变成了功能,自己组装,而且可以快速在另外一台服务器开启,环境是一模一样的,更加重要的是,每个功能都是独立容器运行的,不会威胁到系统安全,这个是非常让运维放心了。
比如,我们手机需要科学上网,几句话就解决了,下面在阿里云安装这个:
第一步,安装并运行docker
第二步,下载ikeV2的image
如果提示:
Using default tag: latest
Cannot connect to the Docker daemon. Is the docker daemon running on this host?
可以运行 service docker start
第三步,运行
第四步,给iphone生成配置文件,换成自己的域名
第五步,把文件放网站,下载安装即可
iPhone里显示的名字比较古怪,需要自定义名字,可以修改mobileconfig里的定义 UserDefinedName,然后再下载
如果连接不上,那可能是阿里云的安全组,编辑vps的安全组,把500和4500的udp开放了即可
天哪,繁琐的IKEV2的安装就变成了几句话,非常的便利。
以前要开一个网站服务,需要安装php/mysql/nginx,自己编译,需要花时间收集下载地址或者文件,记录编译参数,做成批处理脚本减轻重复操作。好点的方式是有人做了个合集,比如lnmp的包,这个也让人省心不少,还有一些小激动,运行一个命令就安装好了。
如今,docker有各种各样的image,都配置好了软件,需要nginx,下载个nginx的image即可,运行就有,就两句话解决了。
需要php支持,安装一个php的image,一个个软件都变成了功能,自己组装,而且可以快速在另外一台服务器开启,环境是一模一样的,更加重要的是,每个功能都是独立容器运行的,不会威胁到系统安全,这个是非常让运维放心了。
比如,我们手机需要科学上网,几句话就解决了,下面在阿里云安装这个:
第一步,安装并运行docker
yum install docker
第二步,下载ikeV2的image
docker pull gaomd/ikev2-vpn-server
如果提示:
Using default tag: latest
Cannot connect to the Docker daemon. Is the docker daemon running on this host?
可以运行 service docker start
第三步,运行
docker run -d --name ikev2-vpn-server --restart=always --privileged -p 500:500/udp -p 4500:4500/udp gaomd/ikev2-vpn-server
第四步,给iphone生成配置文件,换成自己的域名
docker run -i -t --rm --volumes-from ikev2-vpn-server -e "HOST=vpn.example.com" gaomd/ikev2-vpn-server generate-mobileconfig > ikev2-vpn-iphone.mobileconfig
第五步,把文件放网站,下载安装即可
iPhone里显示的名字比较古怪,需要自定义名字,可以修改mobileconfig里的定义 UserDefinedName,然后再下载
如果连接不上,那可能是阿里云的安全组,编辑vps的安全组,把500和4500的udp开放了即可
天哪,繁琐的IKEV2的安装就变成了几句话,非常的便利。
从A表选出数据更新A表是不允许的,需要借助中间临时表操作
联合两个表查询做更新
update table_A set department_id=1425
where user_id IN(
select id from (
select user_id as id from table_B
left join table_A using(m_id)
where l_id=143969
) as tmp
)
where user_id IN(
select id from (
select user_id as id from table_B
left join table_A using(m_id)
where l_id=143969
) as tmp
)
联合两个表查询做更新
UPDATE table_A t1 , (
select d_id,count(*) as cnt from table_B
where h_id = 143969
group by d_id
) t2
SET t1.d_cnt = t2.cnt
WHERE t1.d_id = t2.d_id;
select d_id,count(*) as cnt from table_B
where h_id = 143969
group by d_id
) t2
SET t1.d_cnt = t2.cnt
WHERE t1.d_id = t2.d_id;
如果要管理多个数据库,方便切换,可以在phpMyadmin里直接配置多个数据库
选择即可跳转到相应的数据库
要注意,这是明文保存密码在配置文件里的,所以需要注意安全
复制一份 config.sample.inc.php 为 config.inc.php
可以看到这个是基于cookie来验证登录的
我们可以改为config方式,并且加上用户名和密码
把user和password配置好即可
复制多个即可增加多个server,同时访问phpMyadmin会出现下拉选择框,选择即可跳转到另外的数据库
选择即可跳转到相应的数据库
要注意,这是明文保存密码在配置文件里的,所以需要注意安全
复制一份 config.sample.inc.php 为 config.inc.php
/**
* First server
*/
$i++;
/* Authentication type */
$cfg['Servers'][$i]['auth_type'] = 'cookie';
/* Server parameters */
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['compress'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;
* First server
*/
$i++;
/* Authentication type */
$cfg['Servers'][$i]['auth_type'] = 'cookie';
/* Server parameters */
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['compress'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;
可以看到这个是基于cookie来验证登录的
我们可以改为config方式,并且加上用户名和密码
/**
* First server
*/
$i++;
/* Authentication type */
$cfg['Servers'][$i]['auth_type'] = 'config';
/* Server parameters */
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['user'] = 'user';
$cfg['Servers'][$i]['password'] = 'password';
$cfg['Servers'][$i]['compress'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;
* First server
*/
$i++;
/* Authentication type */
$cfg['Servers'][$i]['auth_type'] = 'config';
/* Server parameters */
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['user'] = 'user';
$cfg['Servers'][$i]['password'] = 'password';
$cfg['Servers'][$i]['compress'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false;
把user和password配置好即可
复制多个即可增加多个server,同时访问phpMyadmin会出现下拉选择框,选择即可跳转到另外的数据库
在github上发现了个不错的项目
https://github.com/chaegumi/cxpcms
我一直还说着要做一个管理框架来着,有人做了就拿下看看
结果在本地配置好之后,一直都登录提示验证码错误,这个倒是开始怀疑人生了
1 验证码错误?
反复确认了Captcha.php里生成的和我输入的是一致的
然后确认对比流程,发现提交的是对的,但本地读取的是空值
另外查看session目录的文件,每次访问都产生新的session文件
说明session会话根本没有跟踪到,每次访问都是当做新用户看待,所以比对失败
2 那为什么每次都是新的session呢?
CI根据cookie里的ci_session值作为session_id
做了个简单的页面,打印cookie和session,每次这两个值都在变
另外做了个原生页面的,这个值是不会变的
3 那肯定是CI的问题
直接查看文件
system/libraries/Session/Session.php
检查session的处理流程:
调试起来发现,总是进入del的流程,cookie被删掉了
导致后面会重新设置cookie
很明显是这个导致的
4 表达式在做什么
我们看到表达式是 [0-9a-f]{40,} 而cookie长度是26个字符,所以总是不能符合要求
打印出来配置,发现也一直是26,ini_set也不起作用
5 如何修复
我们看到新版本的CI已经修复了这个问题
简单升级替换system文件夹即可解决
项目更新在 https://github.com/hqlulu/cxpcms
https://github.com/chaegumi/cxpcms
我一直还说着要做一个管理框架来着,有人做了就拿下看看
结果在本地配置好之后,一直都登录提示验证码错误,这个倒是开始怀疑人生了
1 验证码错误?
反复确认了Captcha.php里生成的和我输入的是一致的
然后确认对比流程,发现提交的是对的,但本地读取的是空值
另外查看session目录的文件,每次访问都产生新的session文件
说明session会话根本没有跟踪到,每次访问都是当做新用户看待,所以比对失败
2 那为什么每次都是新的session呢?
CI根据cookie里的ci_session值作为session_id
做了个简单的页面,打印cookie和session,每次这两个值都在变
另外做了个原生页面的,这个值是不会变的
3 那肯定是CI的问题
直接查看文件
system/libraries/Session/Session.php
检查session的处理流程:
print_r($_COOKIE);
echo $this->_config['cookie_name'].'//'.$this->_sid_regexp.'//';
if (isset($_COOKIE[$this->_config['cookie_name']])
&& (
! is_string($_COOKIE[$this->_config['cookie_name']])
OR ! preg_match('#\A'.$this->_sid_regexp.'\z#', $_COOKIE[$this->_config['cookie_name']])
)
)
{
echo 'del//';
unset($_COOKIE[$this->_config['cookie_name']]);
}
echo $this->_config['cookie_name'].'//'.$this->_sid_regexp.'//';
if (isset($_COOKIE[$this->_config['cookie_name']])
&& (
! is_string($_COOKIE[$this->_config['cookie_name']])
OR ! preg_match('#\A'.$this->_sid_regexp.'\z#', $_COOKIE[$this->_config['cookie_name']])
)
)
{
echo 'del//';
unset($_COOKIE[$this->_config['cookie_name']]);
}
调试起来发现,总是进入del的流程,cookie被删掉了
导致后面会重新设置cookie
很明显是这个导致的
preg_match('#\A'.$this->_sid_regexp.'\z#', $_COOKIE[$this->_config['cookie_name']]
4 表达式在做什么
if (PHP_VERSION_ID < 70100)
{
if ((int) ini_get('session.hash_function') === 0)
{
ini_set('session.hash_function', 1);
ini_set('session.hash_bits_per_character', $bits_per_character = 4);
}
else
{
$bits_per_character = (int) ini_get('session.hash_bits_per_character');
}
}
elseif ((int) ini_get('session.sid_length') < 40 && ($bits_per_character = (int) ini_get('session.sid_bits_per_character')) === 4)
{
ini_set('session.sid_length', 40);
}
switch ($bits_per_character)
{
case 4:
$this->_sid_regexp = '[0-9a-f]{40,}';
break;
case 5:
$this->_sid_regexp = '[0-9a-v]{40,}';
break;
case 6:
$this->_sid_regexp = '[0-9a-zA-Z,-]{40,}';
break;
}
{
if ((int) ini_get('session.hash_function') === 0)
{
ini_set('session.hash_function', 1);
ini_set('session.hash_bits_per_character', $bits_per_character = 4);
}
else
{
$bits_per_character = (int) ini_get('session.hash_bits_per_character');
}
}
elseif ((int) ini_get('session.sid_length') < 40 && ($bits_per_character = (int) ini_get('session.sid_bits_per_character')) === 4)
{
ini_set('session.sid_length', 40);
}
switch ($bits_per_character)
{
case 4:
$this->_sid_regexp = '[0-9a-f]{40,}';
break;
case 5:
$this->_sid_regexp = '[0-9a-v]{40,}';
break;
case 6:
$this->_sid_regexp = '[0-9a-zA-Z,-]{40,}';
break;
}
我们看到表达式是 [0-9a-f]{40,} 而cookie长度是26个字符,所以总是不能符合要求
打印出来配置,发现也一直是26,ini_set也不起作用
5 如何修复
我们看到新版本的CI已经修复了这个问题
// Yes, 4,5,6 are the only known possible values as of 2016-10-27
switch ($bits_per_character)
{
case 4:
$this->_sid_regexp = '[0-9a-f]';
break;
case 5:
$this->_sid_regexp = '[0-9a-v]';
break;
case 6:
$this->_sid_regexp = '[0-9a-zA-Z,-]';
break;
}
switch ($bits_per_character)
{
case 4:
$this->_sid_regexp = '[0-9a-f]';
break;
case 5:
$this->_sid_regexp = '[0-9a-v]';
break;
case 6:
$this->_sid_regexp = '[0-9a-zA-Z,-]';
break;
}
简单升级替换system文件夹即可解决
项目更新在 https://github.com/hqlulu/cxpcms