通过shell_exec调用PHP脚本传递session_id时脚本无法终止求助
问题分析与解决方案
问题根源
PHP默认采用文件型会话存储,当一个脚本调用session_start()后,会对对应的会话文件加独占锁,直到脚本执行完毕或调用session_write_close()主动释放锁。你的场景中,executer.php启动会话后直接调用shell_exec执行job.php,此时会话文件仍被executer.php锁定,job.php尝试打开同一个会话文件时会被阻塞,卡在session_start()步骤无法继续。
你提到试过session_write_close()但无效,大概率是调用时机错误——必须在shell_exec之前调用,才能提前释放锁。
修复方案
方案1:提前释放会话锁(最直接)
修改executer.php,在调用shell_exec前调用session_write_close(),释放会话文件的独占锁:
<?php session_start(); $sessionID = session_id(); session_write_close(); // 关键:提前释放会话锁 $return = shell_exec('php '.__DIR__.'/job.php sessionID='.$sessionID); print_r($return); ?>
方案2:传递会话数据而非Session ID
如果不需要在job.php中完整操作会话,可直接将需要的数据序列化后作为参数传递,避免共享会话文件:
// executer.php <?php session_start(); $sessionData = serialize($_SESSION); $return = shell_exec('php '.__DIR__.'/job.php sessionData='.$sessionData); print_r($return); ?> // job.php <?php parse_str($argv[1], $params); $sessionData = unserialize($params['sessionData']); $returnValues = array('Submitted Session Data' => $sessionData); print_r($returnValues); ?>
方案3:改用非阻塞会话存储
如果你的业务场景需要频繁跨进程共享会话,建议将会话存储改为Redis、Memcached等支持并发访问的存储引擎,避免文件锁的阻塞问题。需要修改php.ini中的会话配置,例如:
session.save_handler = redis session.save_path = "tcp://127.0.0.1:6379"
内容的提问来源于stack exchange,提问作者Georg
相关产品推荐
相关产品推荐

