php命令行程序编写范例

 
命令行下有两个常量,STDOUT和STDIN分别代表标准输出和标准输入,通过它们来实现命令行的交互。
 
#!/usr/bin/php -q
<?php
/**
 * php命令行的编写介绍
 * @author Rains rains31@gmail.com
 * @copyright http://rains.cn
 */
//怎么判断程序是否是以命令行的方式运行的呢?
//最简单的方式就是:命令行程序中$_SERVER['REQUEST_METHOD']为空。
//web请求的话,一般是用post或get方法,而命令行不存在请求方法。
define('USER_DIR','./data');
if(empty($_SERVER['REQUEST_METHOD']))
{
//获得命令行参数,是一个数组
    $args = $_SERVER['argv'];
    if(isset($_SERVER['_']) && basename($_SERVER['_'])!='php')
    {
$cmd = $_SERVER['_'];
    }
    else 
    {
        $cmd = 'php '.array_shift($args);
    }
    /**
     * 获取选项参数
     */
    $option = array_shift($args);
    switch($option)
    {
case '':
case '-h':
case '--help':
    $msg .= "Usage:\t$cmd option [id]\r\n\tAvailable options:\r\n";
    $msg .= "\t-h \tShow this help.\r\n";
    $msg .= "\t-a\tAdd User\r\n";
    $msg .= "\t-d name\tDelete User\r\n";
    $msg .= "\t-p name\tModify password\r\n";
    $msg .= "\t-l\tList all users.\r\n";
break;
case '-a':
$name = read_name();
$pass = read_pass();
$msg = save_user(array('name'=>$name,'pass'=>$pass));
break;
case '-d':
$name = array_shift($args);
$msg = del_user($name);
break;
case '-p':
$name = array_shift($args);
$msg = modify_user($name);
break;
case '-l':
$files = glob(USER_DIR.'/*.dat');
foreach ($files as $file)
{
$msg .= basename($file,'.dat')."\r\n";
}
$msg .= count($files)." user(s)\r\n";
break;
default:
    $msg = "Invalid option '$option', please try '-h' for instructions.\r\n";
break;
    }
    fwrite(STDOUT,$msg);
    exit;
}
function read_name()
{
$msg = 'Plese input your prefered name(1-16 chars, 0-9 a-z A-Z _ and - ):';
fwrite(STDOUT,$msg);
while(preg_match('/^[-_0-9a-zA-Z]{1,16}$/',($name = trim(fgets(STDIN,16))),$matches)==false)
{
fwrite(STDOUT,"Invalid name!\r\n".$msg);
}
return trim($name);
}
function read_pass()
{
$msg = "Please set your password(1-16 chars):";
fwrite(STDOUT,$msg);
while(($pass = trim(fgets(STDIN,16)))=='')
{
fwrite(STDOUT,"Invalid password!\r\n".$msg);
}
return trim($pass);
}
function save_user($param=array())
{
if($param['name']=='' || $param['pass']=='')
{
$msg = 'User name or password is empty!';
}
$user_data = USER_DIR.'/'.$param['name'].'.dat';
if(file_exists($user_data))
{
$msg = "Sorry, user {$param['name']} already exists!";
}
else 
{
$fp = fopen($user_data,'w');
if(!$fp)
{
$msg = "Sorry, some error occurred while writing user data.";
}
else 
{
if(fwrite($fp,md5($param['pass'])))
{
$msg = "Congratulations! User {$param['name']} has been accepted.";
}
else 
{
$msg = "Sorry, some error occurred while writing user data.";
}
}
fclose($fp);
}
return $msg;
}
function del_user($name)
{
if(!preg_match('/^[-_0-9a-zA-Z]{1,16}$/',$name,$matches))
{
return 'invalid user name '.$name;
}
$user_data = USER_DIR.'/'.$name.'.dat';
if(!file_exists($user_data))
{
return "Sorry, user {$name} doesn't exist!";
}
else 
{
$msg = "Are you sure to delete user $name? press y to confirm or any other key to cancel:";
if(confirm($msg)!='y')
{
return "Canceled!\r\n";
}
}
if(unlink($user_data))
{
return "user $name has been successfully deleted!";
}
else 
{
return "delete failed!";
}
}
function confirm($msg = '')
{
fwrite(STDOUT,$msg);
return fgetc(STDIN);
}
function modify_user($name)
{
$user_data = USER_DIR.'/'.$name.'.dat';
if(!file_exists($user_data))
{
return "Sorry, user {$name} doesn't exist!";
}
$msg = "Please enter OLD password(1-16 chars):";
fwrite(STDOUT,$msg);
while(($pass = trim(fgets(STDIN,16)))=='')
{
fwrite(STDOUT,"Invalid password!\r\n".$msg);
}
$fp = fopen($user_data,'r+');
if(!$fp)
{
return "Sorry, some error occurred while reading user data.";
}
else 
{
$old_pass = fread($fp,32);
if(md5($pass)!=$old_pass)
{
return "Old password $old_pass!=$pass doesn't match";
}
$msg = "Please enter NEW password(1-16 chars):";
fwrite(STDOUT,$msg);
while(($pass = trim(fgets(STDIN,16)))=='')
{
fwrite(STDOUT,"Invalid password!\r\n".$msg);
}
rewind($fp);
if(fwrite($fp,md5($pass)))
{
$msg = "New password accepted!";
}
else 
{
$msg = "Sorry, some error occurred while writing user data.";
}
fclose($fp);
}
return $msg;
}
>
后面还可以继续实现WEB下面的功能。不过,没必要让两个功能共用一个文件。命令行运行的东西。最好放在web目录之外,以免由于配置错误,泄漏机密。
posted @ 2008-11-25 09:02  酷越  阅读(309)  评论(0编辑  收藏  举报