tivie/command 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

tivie/command

Composer 安装命令:

composer require tivie/command

包简介

An utility library that harmonizes OS differences and executes external programs in a safer way

README 文档

README

Build Status Latest Stable Version License

A cross-platform PHP utility library that harmonizes OS differences and executes external programs in a safer way

Introduction

Command is a small lightweight utility library that enables you to run external programs or commands in a safer way. It also harmonizes the differences between Windows and Unix environments, removing the need to create specific code for each platform.

Features

  • Platform independent: run the same code in Unix and Windows
  • Fixes issues with proc_open in windows environment
  • Object Oriented command builder with fluent interface
  • Argument escaping, for safer command calls
  • Command chaining with support for conditional calls and piping in both Windows and Unix environment

Installation

You can install it by cloning the git repository or using composer.

Git clone

git clone https://github.com/tivie/command.git

Composer

Add these lines to your composer.json:

    {
        "require": {
            "tivie/command": "*"
        }
    }

or run the following command:

php composer.phar require tivie/command

Quick Usage guide

Simple example

Let's say we want to 'ping' google.com 3 times with 32bytes packets. With PHP we could do something like this:

exec("ping -c 3 -s 24 www.google.com", $otp, $ec);

We want, however, to make our command a little bit safer and escape our arguments.

$host = 'www.google.com';
$c = 3;
$s = 24; //Linux adds 8 bytes of ICMP header data
$cmd = sprintf("ping -c %d -s %d %s", escapeshellarg($c), escapeshellarg($s), escapeshellarg($host));
exec($cmd, $otp, $ec);

This will work as expected in a GNU/Linux environment but will fail on Windows, since '-c' is an unrecognized flag and '-s' means something entirely different. The windows version would be :

$host = 'www.google.com';
$c = 3;
$s = 32;
$cmd = sprintf("ping -n %d -l %d %s", escapeshellarg($c), escapeshellarg($s), escapeshellarg($host));
exec($cmd, $otp, $ec);

If we want to ensure cross platform compatibility we will need to perform some kind of OS check and run the appropriate command based on that check:

$host = 'www.google.com';
$c = 3;
if (PHP_OS === 'WINDOWS' || PHP_OS === 'WIN32' || PHP_OS === 'WINNT' /* And a few more*/ ) {
    $s = 32;
    $cmd = sprintf("ping -n %d -l %d %s", escapeshellarg($c), escapeshellarg($s), escapeshellarg($host));
} else {
    $s = 24; //Linux adds 8 bytes of ICMP header data
    $cmd = sprintf("ping -c %d -s %d %s", escapeshellarg($c), escapeshellarg($s), escapeshellarg($host));
}
exec($cmd, $otp, $ec);

While this works in most cases, with more complex commands (or command chains) you would be forced to repeat yourself a lot, with a lot of conditional checks.

With command library, you don't need to: it will do this work for you.

$cmd = new \Tivie\Command\Command(\Tivie\Command\ESCAPE);
$cmd->setCommand('ping')
    ->addArgument(
        new Argument('-n', 3, \Tivie\OS\WINDOWS_FAMILY)
    )
    ->addArgument(
        new Argument('-l', 32, \Tivie\OS\WINDOWS_FAMILY)
    )
    ->addArgument(
        new Argument('-c', 3, \Tivie\OS\UNIX_FAMILY)
    )
    ->addArgument(
        new Argument('-s', 24, \Tivie\OS\UNIX_FAMILY)
    )
    ->addArgument(
        new Argument('www.google.com')
    );
    
$result = $cmd->run();

Command::run() returns a Result object that you can access to retrieve the result of the command.

echo $result->getStdOut();    // The Standard Output of the command
echo $result->getLastLine();  // The last line of the Standard Output
echo $result->getStdIn();     // The passed standard input
echo $result->getStdErr();    // The standard error
echo $result->getExitCode();  // The command's exit code

Chaining commands

Command library supports command chaining

$cmd1 = new \Tivie\Command\Command();
$cmd1->setCommand('php')
    ->addArgument(new Argument('-v'));

$cmd2 = new \Tivie\Command\Command();
$cmd2->setCommand('echo')
    ->addArgument(new Argument('foo'));
    
$results = $cmd1->chain()
                ->add($cmd2)
                /* any number of commands here */
                ->run(); 

$results will be an array of Result objects.

You can also specify chaining conditions, similar to Linux's Chaining Operators.

RUN_REGARDLESS (';')

$cmd1->chain()->add($cmd2, \Tivie\Command\RUN_REGARDLESS)->run(); 

$cmd2 will be run regardless of the exitcode of $cmd1. Mimics the ';' chaining operator and is the default action.

RUN_IF_PREVIOUS_SUCCEEDS ('&&')

$cmd1->chain()->add($cmd2, \Tivie\Command\RUN_IF_PREVIOUS_SUCCEEDS)->run(); 

$cmd2 will only be run if $cmd1 is successful, that is, if it exits with exitcode 0. Mimics the '&&' chaining operator.

RUN_IF_PREVIOUS_FAILS ('||')

$cmd1->chain()->add($cmd2, \Tivie\Command\RUN_IF_PREVIOUS_FAILS)->run(); 

$cmd2 will only be run if $cmd1 is not successful, that is, if it exits with exitcode different than 0. Mimics the '||' chaining operator.

Complex command chains

That being said, you can create complex command chains. For instance:

$cmd1->chain()
     ->add($cmd2, \Tivie\Command\RUN_IF_PREVIOUS_SUCCEEDS)
     ->add($cmd3, \Tivie\Command\RUN_IF_PREVIOUS_FAILS)
     ->add($cmd4, \Tivie\Command\RUN_REGARDLESS)
     ->run(); 

This will:

  1. Run $cmd1
  2. If $cmd1 is successful then runs $cmd2
  3. If $cmd1 or $cmd2 fails it will run $cmd3
  4. Finally will run $cmd4

Piping

Command library supports 2 types of piping:

  • STDOUT->STDIN
  • STDOUT->Argument

STDOUT to STDIN

Piping the standard output of one command to the next's standard input is easy. You just need to set the third argument of Chain::add() to true.

$cmd1->chain()->add($cmd2, \Tivie\Command\RUN_REGARDLESS, true)

STDOUT to Arguments

You can also pass the STDOUT of previous command as an argument of the next command. The library will look for the special keyword (placeholder) '!PIPE!' in the command's argument key and values and replace them with the previous command's STDOUT. You will then need to pass true as the third argument in Chain::add() function, same as the above case.

$cmd2->addArgument(new Argument('foo'), \Tivie\Command\PIPE_PH); // PIPE_PH = '!PIPE!'
$cmd1->chain()->add($cmd2, \Tivie\Command\RUN_REGARDLESS, true);

Add support for other OS

IF you need to more specific OS checks, you can extend Detector class or create a new class that implements DetectorInterface. For further information, please read the php-os-detector documentation.

Example:

const OS_2_WARP  = 65540; //65536 + 4

class MyOSDetector extends \Tivie\OS\Detector
{
    public function detect()
    {
        $os = parent::detect();
        
        switch($os->name) {
            case "OS/2":
            case "OS/2 WARP":
                $os->family = \Tivie\Command\OS\OTHER_FAMILY;
                $os->def = OS_2_WARP;
                break;
        }
        
        return $os;
    }
}

You don't need to create a new constant pertaining the new OS (you can use one of the pre existing families). If, however, you choose to do so, the new OS const value should be a unique number in the 2^n sequence plus the family the OS belongs to. In the example we chose 16th term (65536) plus the OS family (in this case, FAMILY_OTHER) which is 4.

Contribute

Feel free to contribute by forking or making suggestions.

Issue tracker: https://github.com/tivie/command/issues

Source code: https://github.com/tivie/command

Contributors

Tivie Sophie-OS

License

Command Library is released under Apache 2.0 license. For more information, please consult the LICENSE file in this repository or http://www.apache.org/licenses/LICENSE-2.0.txt.

tivie/command 适用场景与选型建议

tivie/command 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 58.97k 次下载、GitHub Stars 达 12, 最近一次更新时间为 2014 年 12 月 19 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「exec」 「proc_open」 「external programs」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 tivie/command 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 tivie/command 我们能提供哪些服务?
定制开发 / 二次开发

基于 tivie/command 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 58.97k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 13
  • 点击次数: 34
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 12
  • Watchers: 1
  • Forks: 2
  • 开发语言: PHP

其他信息

  • 授权协议: APACHE
  • 更新时间: 2014-12-19