【问题标题】:Issue of ps_files_cleanup_dir: Permission deniedps_files_cleanup_dir 问题:权限被拒绝
【发布时间】:2015-05-24 00:18:00
【问题描述】:

以 10% 的概率,我在我的项目中遇到以下问题:

ps_files_cleanup_dir opendir(/var/lib/php5) failed permission denied (13)

根据我的一些研发,我理解问题的原因是:

PHP 正在尝试删除会话文件,同时这也是 由 Debian 软件包维护者在系统上放置的 cron-job 完成 PHP 的。 Ubuntu 的包维护者认为解决方案 在 PHP 中清理会话数据是不安全的。

所以,我在网上搜索了解决这个问题并找到了 2 个解决方案:

  1. php.inisession.gc_probability 设置为 0
  2. 将自定义路径写入session.save_path

解决方案 1 的问题是我不允许 PHP 管理 垃圾收集过程并让所有身份验证给操作系统 (Ubuntu 12.04) 维护者来处理这个和这个 可能导致 PHP 不安全。所以,我不打算这样做 解决方案。

对于第二个,我必须更改会话默认路径 将由 php 使用,默认路径(可能是 tmp 路径)由 Ubntu 维护者。

那么,在上述两种解决方案中,哪一种可能是最好的和安全的?或者对于 Ubuntu Os 的会话权限问题还有其他解决方案吗?

谢谢。

【问题讨论】:

    标签: php session garbage-collection ini permission-denied


    【解决方案1】:

    您可以(也许应该)使用自己的会话处理程序;例如数据库支持的。然后,您可以将会话扩展到单个实例之外并同时解决您的问题。

    编辑:您可以使用我的旧代码,可能需要对 DBAL 进行一些修改。

    <?php
    
      require_once('lib/Mapper.php');
    
      class Session extends Mapper {
      	
      	protected $_pKey = 'session_id';
      	protected $_table = 'sessions';
      	protected $_columns = array('session_id', 'session_data', 'expires', 'updated');
      	
      	protected $_session_id = NULL;
      	protected $_lifetime = NULL;
      	
      	protected $_acl = NULL;
      	
      	public function __construct(Database $db, $session_id = NULL){
      		parent::__construct($db);
      		
      		$this->_session_id = $session_id;
      		
      		// Read the maxlifetime setting from PHP
      		$this->_lifetime = ini_get("session.gc_maxlifetime");
      	}
      	
      	public function __destruct(){
      		session_write_close();
      	}
      	
      	public function open($save_path, $session_id){
      		return true;
      	}
      	
      	public function read($session_id){
      		$data = $this->find(array('session_id' => $session_id));
      		if(!empty($data[0]))
      			$session = $data[0]['session_data'];
      		return (!empty($session)) ? $session : '';
      	}
      	
      	public function write($session_id, $data){
      		// where does the session data come from??? set it in the code in the auth and login!!!
      		$bind = array('session_id' => $session_id, 'session_data' => $data, 'expires' => REQUEST_TIME + $this->_lifetime, 'updated' => REQUEST_TIME);
      		if($this->replace($bind)){
      			return true;
      		}
      		return false;
      	}
      	
      	public function close(){
      		return true;
      	}
      	
      	public function destroy($session_id){
      		$this->remove($session_id);
      		return true;
      	}
      	
      	public function gc(){ 
      		$this->_db->query('DELETE FROM '.$this->_table.' WHERE expires < '.(REQUEST_TIME + $this->_lifetime));
      		return true;
      	}
      	
      	public function setId($id){
      		$this->_session_id = $id;
      	}
      	
        public function getId(){
          return $this->_session_id;
        }
      	
        public function find($params = array(), $order = array(), $skip = 0, $limit = NULL){
          return $this->_finder($params, $order, $skip, $limit);
        }
      	
      }
    
    $Session = new Session($_db);
    // Register this object as the session handler
    session_set_save_handler(
    	array( $Session, "open" ),
    	array( $Session, "close" ),
    	array( $Session, "read" ),
    	array( $Session, "write"),
    	array( $Session, "destroy"),
    	array( $Session, "gc" )
    );
    session_start();
    register_shutdown_function('session_write_close');

    【讨论】:

    • Own Session Handler 意思是你想让我使用自定义会话路径?
    • 查看我更新的评论,基本上是的(但无需修改 php.ini)
    • 好的,这可能是第三种解决方案,但我需要确保代码对我的会话处理程序完美运行。仅针对 10% 的警告概率,我不能使用 own or custom session
    • 您可以向其中一种方法添加一些东西,例如构造函数、析构函数或在 10% 的请求上调用 gc() 的东西。即 if(rand(1,100)%10 == 0) $this->gc();
    • 此外,您永远不会遇到数据库支持的会话处理程序的错误,因为您的代码永远不会尝试删除文件支持的会话文件,并且您的 debian 实例将从未使用的会话中删除文件(因为它们现在由数据库支持)
    猜你喜欢
    • 2018-04-13
    • 2015-01-28
    • 2021-08-30
    • 2011-07-11
    • 2011-03-09
    • 2012-12-29
    • 2011-07-15
    • 2014-08-10
    • 2016-06-19
    相关资源
    最近更新 更多