fpm模式下读取到is_cli为何为true
php-fpm下读取到is_cli为true,不知道你们是否遇到过,我是遇到了。。。。
有人会说,即使为true又怎么了,你是没遇到有些根据is_cli来走不同逻辑判断的,如果读取的是错的就会引起很大的问题。。。。
问题出现和简单排查
维护的老系统里有个上传的服务,用的是比较老的codeigniter,构建完代码后,突然发现 1个上传url报路径找不到
具体表现如下
因为这里是a1.domain.com 去调取upload.domain.com,所以出现跨域(如果upload.domain.com 正常的话,是有设置跨域的),现在明显设置跨域的失效了
直接打开链接看,如下图
因为是线上,即使再自信没改到这里,也要赶紧联系运维同事回滚代码,但是回滚后发现依然如此。
当时急的不行,让测试同事让他看看其它的上传链接是否可正常上传,发现其它的上传(比如视频上传,其它的图片的上传)是没问题的,唯一的区别就是走不走这个index.php入口文件
排查
因为当时已经晚上近10点了,使用的人也不多,一边让测试同学帮验证。我这边赶紧查代码。日常开发用的不是CI框架,赶紧搜索
ERROR: Not Found The controller/method pair you requested was not found.
这个是哪提示出来的,
在项目中发现代码位置如下,而且仅此一处
而且看到前面的is_cli,就是纳闷我这是php-fpm的网页请求,为何is_cli为true呢
追到is_cli的实现
if ( ! function_exists('is_cli'))
{
/**
* Is CLI?
*
* Test to see if a request was made from the command line.
*
* @return bool
*/
function is_cli()
{
return (PHP_SAPI === 'cli' OR defined('STDIN'));
}
}
后来一路追到ci的路由解析
system/core/Router.php
124 public function __construct($routing = NULL)
125 {
126 $this->config =& load_class('Config', 'core');
127 $this->uri =& load_class('URI', 'core');
128 //var_dump(PHP_SAPI);
129 //var_dump(defined('STDIN'));
130 //var_dump( is_cli());
131 $this->enable_query_strings = ( ! is_cli() && $this->config->item('enable_query_strings') === TRUE);
132
133 // If a directory override is configured, it has to be set before any dynamic routing logic
134 is_array($routing) && isset($routing['directory']) && $this->set_directory($routing['directory']);
135 $this->_set_routing();
136
137 // Set any routing overrides that may exist in the main index file
138 if (is_array($routing))
139 {
140 empty($routing['controller']) OR $this->set_class($routing['controller']);
141 empty($routing['function']) OR $this->set_method($routing['function']);
142 }
143
144 log_message('info', 'Router Class Initialized');
145 }
结合上图128,129行和上面is_cli函数的实现代码,130行不可能为true啊
脑袋快要炸了,通过调试发现只要131行的$this->enable_query_strings为true,那么上传功能就没问题
经过思考和猜测,严重怀疑是fpm读取到了cli下的opcache
主要基于以下几点
- 其它入口(非index.php)的路径没问题
- 命令行里有php index.php 这种定时脚本在跑
- opcache的配置
ri了一下如下
$ php --ri 'Zend opcache'
Zend OPcache
Opcode Caching => Up and Running
Optimization => Enabled
SHM Cache => Enabled
File Cache => Enabled
Startup => OK
Shared memory model => mmap
Cache hits => 0
Cache misses => 0
Used memory => 36560720
Free memory => 231874736
Wasted memory => 0
Interned Strings Used memory => 415960
Interned Strings Free memory => 16361256
Cached scripts => 0
Cached keys => 0
Max keys => 16229
OOM restarts => 0
Hash keys restarts => 0
Manual restarts => 0
Directive => Local Value => Master Value
opcache.enable => On => On
opcache.use_cwd => On => On
opcache.validate_timestamps => On => On
opcache.validate_permission => Off => Off
opcache.validate_root => Off => Off
opcache.inherited_hack => On => On
opcache.dups_fix => Off => Off
opcache.revalidate_path => Off => Off
opcache.log_verbosity_level => 1 => 1
opcache.memory_consumption => 256 => 256
opcache.interned_strings_buffer => 16 => 16
opcache.max_accelerated_files => 8000 => 8000
opcache.max_wasted_percentage => 10 => 10
opcache.consistency_checks => 0 => 0
opcache.force_restart_timeout => 3600 => 3600
opcache.revalidate_freq => 2 => 2
opcache.file_update_protection => 2 => 2
opcache.preferred_memory_model => no value => no value
opcache.blacklist_filename => no value => no value
opcache.max_file_size => 0 => 0
opcache.protect_memory => 0 => 0
opcache.save_comments => 1 => 1
opcache.fast_shutdown => 0 => 0
opcache.optimization_level => 0x7FFFBFFF => 0x7FFFBFFF
opcache.opt_debug_level => 0 => 0
opcache.enable_file_override => Off => Off
opcache.enable_cli => On => On
opcache.error_log => no value => no value
opcache.restrict_api => no value => no value
opcache.lockfile_path => /tmp => /tmp
opcache.file_cache => /tmp => /tmp
opcache.file_cache_only => 0 => 0
opcache.file_cache_consistency_checks => 1 => 1
opcache.huge_code_pages => Off => Off
这里有下面几个配置项对fpm下读取到cli的缓存有关
zend_extension=opcache.so
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=8000
opcache.max_wasted_percentage=10
opcache.use_cwd=1
opcache.force_restart_timeout=3600
opcache.file_cache=/tmp
- 1.开启了cli的opcache 即(enable_cli=1)
- 2.使用了二级文件缓存 即(opcache.file_cache=/tmp)
于是尝试删除opcache的文件缓存,然后重启fpm,就好了
(实际上是,我打日志调着调着 突然自己好了,看fpm的日志是fpm触发了自动重启,我打日志时有修改了相关文件,fpm重启时检查文件更新重新生成了opcache)
后来为了防止这种情况再次发生就关闭了cli下的opcache,删除opcache文件缓存,重启fpm
然后我在测试上不断复现,发现可以稳定复现,实锤是fpm下读取到了cli已经生成好的缓存了
原起
这次的问题,我归结为以下两点
- 对opcache的机制认识不够
- CI框架这种fpm里和cli用了同样的入口文件而且根据is_cli来进行路由解析,会在我上面的配置和使用下出问题
粗浅探索
测试代码
现在有以下代码
路径为/data/www/emlog/op/
test.php
include/fun.php
invalidate
test.php
include "include/fun.php";
var_dump(sapi());
var_dump(is_cli());
include/fun.php
function sapi(){
return php_sapi_name();
}
function is_cli()
{
return (PHP_SAPI === 'cli' OR defined('STDIN'));
}
invalidate.php
$files=[
'/data/www/emlog/op/test.php',
'/data/www/emlog/op/include/fun.php',
];
foreach($files as $f){
$r=opcache_invalidate($f,true);
var_dump($r);
}
opcache配置
[opcache]
zend_extension=opcache.so
opcache.enable=1
opcache.enable_cli=1
opcache.file_cache=/tmp
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=8000
opcache.max_wasted_percentage=10
opcache.use_cwd=1
opcache.force_restart_timeout=3600
opcache.validate_timestamps=1
opcache.revalidate_freq=2
opcache.revalidate_path=0
主要是前4个的配置
按照下图操作
is_cli为true时的缓存
[root@hkui-qy tmp]# cat 8fc9c56d14b6542c6ff7147207730f6b/data/www/emlog/op/include/fun.php.bin |strings
OPCACHE
8fc9c56d14b6542c6ff7147207730f6b0
%%1n
include/fun.php:235496:235544:/data/www/emlog/op
/data/www/emlog/op/include/fun.php
is_cli
sapi
php_sapi_name
is_cli为false时的缓存
[root@hkui-qy tmp]# cat 8fc9c56d14b6542c6ff7147207730f6b/data/www/emlog/op/include/fun.php.bin |strings
OPCACHE
8fc9c56d14b6542c6ff7147207730f6b`
include/fun.php:235648:235696:/data/www/emlog/op
/data/www/emlog/op/include/fun.php
496:
is_cli
STDIN
stdin
sapi
php_sapi_name
共享内存缓存与文件缓存
- fpm在启动或者重启时
- 如果发现代码文件和缓存文件匹配,那么会读取文件的缓存到共享内存,所以使用文件缓存(可提前用opcache_compile_file生成opcache),在fpm重启时,能更快的获取opcache,减少内存使用
- 如果发现代码文件和缓存文件对不匹配(缓存不存在或者代码文件有改变),那么会重新生成缓存,并同步到文件缓存里
- 文件修改,fpm检测到了文件的变化,会重新生成共享内存缓存,并不会立马更新到文件缓存里,fpm重启 然后重新生成缓存后才会更新到文件缓存
fpm模式下读取到is_cli为何为true的更多相关文章
- 【Spark】Spark-shell案例——standAlone模式下读取HDFS上存放的文件
目录 可以先用local模式读取一下 步骤 一.先将做测试的数据上传到HDFS 二.开发scala代码 standAlone模式查看HDFS上的文件 步骤 一.退出local模式,重新进入Spark- ...
- unity editor模式下读取文件夹资源
string path = EditorUtility.OpenFolderPanel("Load png Textures", "", "" ...
- [PHP] swoole在daemonize模式下,chdir失效问题
swoole version: 1.9.6 其实跟swoole的版本无关,因为原代码体系,fpm模式下,在启动的时候,是使用 chdir 函数改变了当前目录的,而其它代码在做类的自动加载的时候,都是写 ...
- 读取模式下cbc latch的事件模拟(热块竞争和热链竞争)-P62
文章目录 1. 背景 2. 过程 2.1 热块竞争 2.1.1 版本11.2.0.1.0 2.1.1.1 session 1(sid:34) 2.1.1.2 session 2(sid:35) 2.1 ...
- 处理Codeigniter CLI模式无法读取通过Apache写入的文件缓存
运行环境: Ubuntu 16.04 + PHP 5.6.40 + Apache/2.4.18 Codeigniter: 3.1.10 Codeigniter 3.1.10,缓存驱动方式是文件方式 遇 ...
- ASM:《X86汇编语言-从实模式到保护模式》越计卷:实模式下对DMA和Sound Blaster声卡的控制
说实话越计卷作者用了16页(我还是删过的),来讲怎么控制声卡,其实真正归纳起来就那么几点. ★PART1:直接存储访问 1. 总线控制设备(bus master) 在硬件技术不发达的早期,处理器是最重 ...
- ASM:《X86汇编语言-从实模式到保护模式》第17章:保护模式下中断和异常的处理与抢占式多任务
★PART1:中断和异常概述 1. 中断(Interrupt) 中断包括硬件中断和软中断.硬件中断是由外围设备发出的中断信号引发的,以请求处理器提供服务.当I/O接口发出中断请求的时候,会被像8259 ...
- ASM:《X86汇编语言-从实模式到保护模式》第9章:实模式下中断机制和实时时钟
中断是处理器一个非常重要的工作机制.第9章是讲中断在实模式下如何工作,第17章是讲中断在保护模式下如何工作. ★PART1:外部硬件中断 外部硬件中断是通过两个信号线引入处理器内部的,这两条线分别叫N ...
- Apache Spark技术实战之8:Standalone部署模式下的临时文件清理
未经本人同意严禁转载,徽沪一郎. 概要 在Standalone部署模式下,Spark运行过程中会创建哪些临时性目录及文件,这些临时目录和文件又是在什么时候被清理,本文将就这些问题做深入细致的解答. 从 ...
- 软件调试——IA-32 保护模式下寄存器一览
最近在看张银奎先生的<调试软件>一书,想将关键的技术记录下来,以便日后查阅,也分享给想看之人吧. 1 通用寄存器 EAX,EBX,ECX,EDX:用于运算的通用寄存器,可以使用AX,BX等 ...
随机推荐
- element 表格show-overflow-tooltip的属性设置样式
在style标签中不要加scoped .el-tooltip__popper { max-width: 60% !important; } .el-tooltip__popper, .el-toolt ...
- 挖坑——未完成题目列表QwQ
OI一些的小计划: 日拱一卒,功不唐捐! Unfinished luogu P2814 家谱 Luogu P2076 聚会 luogu P2212 Watering the Fields 草坪上有N ...
- 【LeetCode】 907 子数组的最小值之和
Decrisption Given an array of integers arr, find the sum of min(b), where b ranges over every (conti ...
- OpenStack 云主机ping通外网
- 第17章 使用日志记录监视和排除错误(ASP.NET Core in Action, 2nd Edition)
第3部分 扩展应用程序 我们在第1部分和第2部分中介绍了大量内容:我们查看了您将用于构建传统服务器渲染的 Razor Pages 应用程序以及 Web API 的所有主要功能组件.在第3部分中,我们将 ...
- Nginx 代理解决跨域问题分析
Nginx 代理解决跨域问题分析 当你遇到跨域问题,不要立刻就选择复制去尝试.请详细看完这篇文章再处理 .我相信它能帮到你. 分析前准备: 前端网站地址:http://localhost:8080 ...
- eclipse静态资源保存不重启(热部署静态资源/html)
简单的来说就是windows->Prefrence->搜索 build automatically 并勾选就可以 不同的版本设置选项可能略微不同,其实比较简单但是新手可能不好找,所以帮到的 ...
- applicationContext使用注解代替
创建一个类SpringConfig @Configuration//证明这个类是spring的配置文件类 @ComponentScan("com.itheima")//扫描的哪些包 ...
- tf.keras.layers.MaxPool2D 简介
tf.keras.layers.Max2D( pool_size=(2, 2), strides=None, padding='valid', data_format=None ) pool_size ...
- 转 oracle 无法使用sys用户登录 connection as SYS should be as SYSDBA OR SYSOPER
转自: https://blog.csdn.net/u012004128/article/details/80781979 安装Oracle11g后,为了测试安装是否成功,通过cmd命令打开了sql ...