当前位置: 首页 > news >正文

php-phar打包避坑指南2025

有很多php脚本工具都是打包成phar形式,使用起来就很方便,那么如何自己做一个呢?也找了很多文档,也遇到很多坑,这里就来总结一下

phar安装

现在直接装yum php-cli包就有phar文件,很方便

可通过phar help查看帮助

重要修改:

php配置文件中

;phar.readonly = On

一定要改成

phar.readonly = Off

phar简单打包

先打包跟简单的单文件

先写一个简单的index.php文件

<?php
echo "HelloWorld\n";

打包

phar pack -f helloworld.phar -c gz -b '#!/usr/bin/php'  index.php 

参数说明

选中描述
-f指定生成的phar文件名
-c指定压缩算法
-b在首行添加内容(可直接执行类似于sh)(单文件时未生效)

执行

php helloworld.phar 

则会输出helloworld

如果文件名不是index.php呢?

[root@localhost test]# phar pack -f helloworld.phar -c gz -b '#!/usr/bin/php' helloworld.php
helloworld.php
[root@localhost test]# php helloworld.phar 
PHP Warning:  include(phar:///tmp/test/helloworld.phar/index.php): Failed to open stream: phar error: "index.php" is not a file in phar "/tmp/test/helloworld.phar" in /tmp/test/helloworld.phar on line 9
PHP Warning:  include(): Failed opening 'phar:///tmp/test/helloworld.phar/index.php' for inclusion (include_path='phar:///tmp/test/helloworld.phar:.:/opt/remi/php83/root/usr/share/pear:/opt/remi/php83/root/usr/share/php:/usr/share/pear:/usr/share/php') in /tmp/test/helloworld.phar on line 9
[root@localhost test]# 

打包虽然没报错,但运行找不到index.php文件

通过查看help,看到可以使用-s设置启动文件(使用-s时,后面...文件中可省略该文件,但单文件种情况还是要把单文件加上)

满怀期待的你是不是跃跃欲试了??

root@localhost test]# phar pack -f helloworld.phar -s helloworld.php
PHP Fatal error:  Uncaught PharException: illegal stub for phar "/tmp/test/helloworld.phar" (__HALT_COMPILER(); is missing) in phar:///opt/remi/php83/root/usr/bin/phar.phar/pharcommand.inc:534
Stack trace:
#0 phar:///opt/remi/php83/root/usr/bin/phar.phar/pharcommand.inc(534): Phar->setStub()
#1 phar:///opt/remi/php83/root/usr/bin/phar.phar/pharcommand.inc(592): PharCommand->phar_set_stub_begin()
#2 phar:///opt/remi/php83/root/usr/bin/phar.phar/clicommand.inc(87): PharCommand->cli_cmd_run_pack()
#3 /opt/remi/php83/root/usr/bin/phar.phar(52): CLICommand->__construct()
#4 {main}thrown in phar:///opt/remi/php83/root/usr/bin/phar.phar/pharcommand.inc on line 534
[root@localhost test]# 

哈哈报错了

注意-s指定的文件行尾必须要加上__HALT_COMPILER()

helloworld.php代码如下

<?php
echo "Hello Wolrd\n";
__HALT_COMPILER();
[root@localhost test]# phar pack -f helloworld.phar -s helloworld.php helloworld.php
helloworld.php
[root@localhost test]# php helloworld.phar 
Hello Wolrd
[root@localhost test]# 

打包通过运行成功

phar多文件打包

比较单文件打包,坑点比较多,最大的问题是路径问题

先写2个文件

├── helloworld.php
├── lib
│   └── app.php
└── start.php
<?php
//helloworld.php
include __DIR__ . '/lib/app.php';
echo "DIR:" . __DIR__ . "\n";
echo "FILE:" . __FILE__ . "\n";
$app = new app();
$app->show();
echo "HelloWorld\n";
<?php
//lib/app.php
class app {function show() {echo "AppName:" . __CLASS__ . "\n";echo "AppFunc:" . __FUNCTION__ . "\n";echo "AppDir:" . __DIR__ . "\n";echo "AppFile:" . __FILE__ . "\n";}
}

不建议直接改helloworld.php,要改的很多,不是简单的添加__HALT_COMPILER(); 

不死心的小伙伴可以试试

强烈建议重新写一个启动文件

这里经过不断尝试整理出来比较简单的写法,模板化,后面完全可以全部套用

<?php
//start.php
//工作目录切换到文件所在目录,否则不在文件目录执行会报错
chdir(__DIR__);
//Phar::mapPhar();这样也能通过
Phar::mapPhar("helloworld.phar");
//只能用phar路径,否则不通过
require_once 'phar://helloworld.phar/helloworld.php';
//必须要加,否则stub-set会报错
__HALT_COMPILER(); 
[root@localhost test]# phar pack -f bin/helloworld.phar -c gz -b '#!/usr/bin/php' -s start.php helloworld.php lib/app.php
helloworld.php
lib/app.php
[root@localhost test]# chmod a+x bin/helloworld.phar 
[root@localhost test]# ./bin/helloworld.phar 
DIR:phar:///tmp/test/bin/helloworld.phar
FILE:phar:///tmp/test/bin/helloworld.phar/helloworld.php
AppName:app
AppFunc:show
AppDir:phar:///tmp/test/bin/helloworld.phar/lib
AppFile:phar:///tmp/test/bin/helloworld.phar/lib/app.php
HelloWorld
[root@localhost test]# 

多文件的-b参数就有效果

特别注意,如果有多级目录不能只写目录名,否则路径就会不对(-s文件可在文件列表中省略)

-s start.php helloworld.php lib/app.php

支持匹配写法

-s start.php *.php lib/*.php

下面这种绝对不行,虽然help中说可以是目录名

[root@localhost test]# phar pack -f bin/helloworld.phar -c gz -b '#!/usr/bin/php' -s start.php helloworld.php lib
helloworld.php
app.php
[root@localhost test]# ./bin/helloworld.phar 
PHP Parse error:  Unclosed '{' on line 4 in phar:///tmp/test/bin/helloworld.phar/lib/app.php on line 6
[root@localhost test]# 

文件直接找不到了,看打包时的文件名就可以看出,文件路径就不对了

Phar其它注意点

从上面的dir输出就可以看到,里面文件或目录都是一种虚拟路径,

实际过程中涉及到的文件及目录操作都需要特殊注意

坑爹示范

//helloworld.php
include __DIR__ . '/lib/app.php';
echo "DIR:" . __DIR__ . "\n";
echo "FILE:" . __FILE__ . "\n";
echo "PharTrue:" . Phar::running(true) . "\n";
echo "PharFalse:" . Phar::running(false) . "\n";
echo "CWD:" . getcwd() . "\n";
$app = new app();
$app->show();
echo "HelloWorld\n";
$filename=__DIR__."/aaa.txt";
file_put_contents($filename, "HelloWorld");
<?php//lib/app.php
class app {function show() {echo "AppName:" . __CLASS__ . "\n";echo "AppFunc:" . __FUNCTION__ . "\n";echo "AppDir:" . __DIR__ . "\n";echo "AppFile:" . __FILE__ . "\n";echo "AppPharTrue:" . Phar::running(true) . "\n";echo "AppPharFalse:" . Phar::running(false) . "\n";echo "AppCWD:" . getcwd() . "\n";$filename = __DIR__ . "/bbb.txt";file_put_contents($filename, "HelloWorld");}}

使用了file_put_contents

不打包应该这样

[root@localhost test]# php helloworld.php
DIR:/tmp/test
FILE:/tmp/test/helloworld.php
PharTrue:
PharFalse:
CWD:/tmp/test
AppName:app
AppFunc:show
AppDir:/tmp/test/lib
AppFile:/tmp/test/lib/app.php
AppPharTrue:
AppPharFalse:
AppCWD:/tmp/test
HelloWorld

打包后第一次看着通过(有的会报错)

[root@localhost test]# phar pack -f helloworld.phar -c gz -b '#!/usr/bin/php' -a helloworld.phar -s start.php helloworld.php lib/app.php
helloworld.php
lib/app.php
[root@localhost test]# phar list helloworld.phar
Unexpected default arguments to command list, check /usr/bin/phar help
[root@localhost test]# phar list -f helloworld.phar
|-phar:///tmp/test/helloworld.phar/helloworld.php
\-phar:///tmp/test/helloworld.phar/lib\-phar:///tmp/test/helloworld.phar/lib/app.php
[root@localhost test]# php helloworld.phar
DIR:phar:///tmp/test/helloworld.phar
FILE:phar:///tmp/test/helloworld.phar/helloworld.php
PharTrue:phar:///tmp/test/helloworld.phar
PharFalse:/tmp/test/helloworld.phar
CWD:/tmp/test
AppName:app
AppFunc:show
AppDir:phar:///tmp/test/helloworld.phar/lib
AppFile:phar:///tmp/test/helloworld.phar/lib/app.php
AppPharTrue:phar:///tmp/test/helloworld.phar
AppPharFalse:/tmp/test/helloworld.phar
AppCWD:/tmp/test
HelloWorld

 第一次运行看着正常

[root@localhost test]# phar list -f helloworld.phar
|-phar:///tmp/test/helloworld.phar/aaa.txt
|-phar:///tmp/test/helloworld.phar/helloworld.php
\-phar:///tmp/test/helloworld.phar/lib|-phar:///tmp/test/helloworld.phar/lib/app.php\-phar:///tmp/test/helloworld.phar/lib/bbb.txt
[root@localhost test]# php helloworld.phar
PHP Notice:  require_once(): zlib: data error in /tmp/test/helloworld.phar on line 8
PHP Warning:  require_once(phar://helloworld.phar/helloworld.php): Failed to open stream: phar error: internal corruption of phar "/tmp/test/helloworld.phar" (actual filesize mismatch on file "helloworld.php") in /tmp/test/helloworld.phar on line 8
PHP Fatal error:  Uncaught Error: Failed opening required 'phar://helloworld.phar/helloworld.php' (include_path='.:/opt/remi/php83/root/usr/share/pear:/opt/remi/php83/root/usr/share/php:/usr/share/pear:/usr/share/php') in /tmp/test/helloworld.phar:8
Stack trace:
#0 {main}thrown in /tmp/test/helloworld.phar on line 8
[root@localhost test]# 

但在看文件列表,多了aaa.txt和bbb.txt

并且再运行直接报错了

注意Phar::running(true)的返回

解决方式

如果未使用则返回空,可以根据这个来处理文件名

        $filename = __DIR__ . "/bbb.txt";if (!empty(Phar::running(true))) {$filename = str_replace(Phar::running(true), getcwd(), $filename);if(!file_exists(dirname($filename))){mkdir(dirname($filename), 0777, true);}}file_put_contents($filename, "HelloWorld");

这样不管打不打包都能正常运行

执行php情况

[root@localhost test]# tree
.
├── aaa.txt
├── helloworld.php
├── lib
│   ├── app.php
│   └── bbb.txt
└── start.php

执行phar情况

[root@localhost bin]# tree
.
├── aaa.txt
├── helloworld.phar
└── lib└── bbb.txt

有更好的方式可以提出来

还有其它参数-i -x 我暂未试出效果,有兴趣的可以自己尝试一下

相关文章:

php-phar打包避坑指南2025

有很多php脚本工具都是打包成phar形式&#xff0c;使用起来就很方便&#xff0c;那么如何自己做一个呢&#xff1f;也找了很多文档&#xff0c;也遇到很多坑&#xff0c;这里就来总结一下 phar安装 现在直接装yum php-cli包就有phar文件&#xff0c;很方便 可通过phar help查看…...

卡特兰数学习

1&#xff0c;概念 卡特兰数&#xff08;英语&#xff1a;Catalan number&#xff09;&#xff0c;又称卡塔兰数&#xff0c;明安图数。是组合数学中一种常出现于各种计数问题中的数列。它在不同的计数问题中频繁出现。 2&#xff0c;公式 卡特兰数的递推公式为&#xff1a;f(…...

第05章 10 地形梯度场模拟显示

在 VTK&#xff08;Visualization Toolkit&#xff09;中&#xff0c;可以通过计算地形数据的梯度场&#xff0c;并用箭头或线条来表示梯度方向和大小&#xff0c;从而模拟显示地形梯度场。以下是一个示例代码&#xff0c;展示了如何使用 VTK 和 C 来计算和显示地形数据的梯度场…...

2023CISCN初赛unzip

2023CISCN初赛unzip 随便上传一个文件&#xff0c;会自动跳转到uplaod.php目录下,源码如下&#xff1a; <?php error_reporting(0); highlight_file(__FILE__);$finfo finfo_open(FILEINFO_MIME_TYPE); if (finfo_file($finfo, $_FILES["file"]["tmp_name…...

计算机网络 (55)流失存储音频/视频

一、定义与特点 定义&#xff1a;流式存储音频/视频是指经过压缩并存储在服务器上的多媒体文件&#xff0c;客户端可以通过互联网边下载边播放这些文件&#xff0c;也称为音频/视频点播。 特点&#xff1a; 边下载边播放&#xff1a;用户无需等待整个文件下载完成即可开始播放…...

Linux通过docker部署京东矩阵容器服务

获取激活码 将京东无线宝app升级到最新版,然后打开首页,点击号 选择添加容器矩阵,然后获取激活码 运行容器 read -p "请输入你的激活码: " ACTIVECODE;read -p "请输入宿主机的缓存路径: " src;docker rm -f cmatrix;docker run -d -it --name cmatrix …...

【MySQL】悲观锁和乐观锁的原理和应用场景

悲观锁和乐观锁&#xff0c;并不是 MySQL 或者数据库中独有的概念&#xff0c;而是并发编程的基本概念。 主要区别在于&#xff0c;操作共享数据时&#xff0c;“悲观锁”认为数据出现冲突的可能性更大&#xff0c;而“乐观锁”则是认为大部分情况不会出现冲突&#xff0c;进而…...

Java Web-Tomcat Servlet

Web服务器-Tomcat Web服务器简介 Web 服务器是一种软件程序&#xff0c;它主要用于在网络上接收和处理客户端&#xff08;如浏览器&#xff09;发送的 HTTP 请求&#xff0c;并返回相应的网页内容或数据。以下是关于 Web 服务器的详细介绍&#xff1a; 功能 接收请求&#…...

老牌工具被破!

屏幕录制技术因其高效的信息传递能力在多个行业中得到了广泛应用&#xff0c;在教育领域&#xff0c;教师利用屏幕录制制作在线课程。在企业培训中&#xff0c;它为新员工提供了灵活的学习方式。在直播、游戏时&#xff0c;录制分享精彩内容。在客户支持中&#xff0c;客服人员…...

在计算机上本地运行 Deepseek R1

Download Ollama on Linux Download Ollama on Windows Download Ollama on macOS Deepseek R1 是一个强大的人工智能模型&#xff0c;在科技界掀起了波澜。它是一个开源语言模型&#xff0c;可以与 GPT-4 等大玩家展开竞争。但更重要的是&#xff0c;与其他一些模型不同&…...

MongoDB中常用的几种高可用技术方案及优缺点

MongoDB 的高可用性方案主要依赖于其内置的 副本集 (Replica Set) 和 Sharding 机制。下面是一些常见的高可用性技术方案&#xff1a; 1. 副本集 (Replica Set) 副本集是 MongoDB 提供的主要高可用性解决方案&#xff0c;确保数据在多个节点之间的冗余存储和自动故障恢复。副…...

【GoLang】利用validator包实现服务端参数校验时自定义错误信息

在C/S架构下&#xff0c;服务端在校验请求参数时&#xff0c;若出现参数错误&#xff0c;要响应给客户端一个错误消息&#xff0c;通常我们会统一响应“参数错误”。 但是&#xff0c;如果只是一味的提示参数错误&#xff0c;我并不知道具体是哪个参数错了呀&#xff01;能不能…...

异或哈希总结

例题 例题1https://codeforces.com/problemset/problem/1175/Fhttps://codeforces.com/problemset/problem/1175/F 例题2https://codeforces.com/contest/2014/problem/Hhttps://codeforces.com/contest/2014/problem/H例题4https://codeforces.com/contest/1418/problem/Ght…...

【Rust自学】15.7. 循环引用导致内存泄漏

说句题外话&#xff0c;这篇文章真心很难&#xff0c;有看不懂可以在评论区问&#xff0c;我会尽快作答的。 喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文&#xff09;&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω…...

C#AWS signatureV4对接Amazon接口

马上要放假了&#xff0c;需要抓紧时间测试对接一个三方接口&#xff0c;对方是使用Amazon服务的&#xff0c;国内不多见&#xff0c;能查的资(代)料(码)&#xff0c;时间紧比较紧&#xff0c;也没有时间去啃Amazon的文档&#xff0c;主要我的英文水平也不行&#xff0c;于是粗…...

C语言操作符(下)

上一篇文章传送门&#xff1a;操作符上 前言&#xff1a;上期我们介绍了C语言的操作符的使用方法&#xff0c;这期我们主要侧重讲当我们已经了解了操作符的基本知识后怎样样来看待运算路径的问题。 操作符 一&#xff0c;优先级和结合性1&#xff0c;优先级2&#xff0c;结合性…...

学习资料收藏 游戏开发

本文整理了本人在学习 Unity3D 游戏开发过程中知晓的一些学习资料。 视频教程 siki学院 M_Studio Unity中文课堂 博客 林新发 浅墨_毛星云 冯乐乐 Roystan Sorumi 宣雨松 陆泽西 书籍 《Unity 游戏设计与实现》&#xff08;加藤政树&#xff09; 《Unity Shader 入…...

我的2024年总结

趁着摸鱼赶紧写一下吧 去年目标review 还是将去年的目标完成了一些 【接纳不完美&#xff0c;多拍照片】 这个还是部分做到了&#xff0c;今年和一些朋友们见面时都注意拍照留记录了&#xff0c;不过还可以继续加强&#xff0c;因为外貌上发生了重大变化&#xff0c;下面细说…...

freeswitch在centos上编译过程

操作系统&#xff1a;centos9-last usr/local/freeswitch/bin/freeswitch -version FreeSWITCH version: 1.10.13-devgit~20250125T131725Z~3f1e4bf90a~64bit (git 3f1e4bf 2025-01-25 13:17:25Z 64bit)vi /etc/ssh/sshd_config ip a nmtui reboot ip a curl -o /etc/pki/rpm-…...

docker如何查看容器启动命令(已运行的容器)

docker ps 查看正在运行的容器 该命令主要是为了详细展示查看运行时的command参数 # 通过docker --no-trunc参数来详细展示容器运行命令 docker ps -a --no-trunc | grep <container_name>通过docker inspect命令 使用docker inspect&#xff0c;但是docker inspect打…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…...

基于服务器使用 apt 安装、配置 Nginx

&#x1f9fe; 一、查看可安装的 Nginx 版本 首先&#xff0c;你可以运行以下命令查看可用版本&#xff1a; apt-cache madison nginx-core输出示例&#xff1a; nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...