PHP: declared variables, strlen vs isset

greetings,

pretty new to php and i think i might be missing some fundamental limitation of isset. i have two php scripts below that are executed by crond, one using --host X and one that does not. and below that are three different attempts at generating a command line that will be executed. the first example using strlen works as expected. please see bottom of thread for the command line that is generated for each php script respectively. when i came across isset it seemed to make more sense to use that instead, especially the third example. HOWEVER, both isset examples fail when $server is the value for -host. as you might guess -host is $host, --server is $server and --path is $path. is this an issue of having $server twice on the same line when using isset? i've been tinkering with this off and on for a few days and i'm stumped. i need not be spoon fed but some plain speak on what i might be misunderstanding would be great, thanks.

grid_lmx_capture_test.php --server=t70aic100 --host=denasv004 --path=/opt/IBM/lmx/bin --port=6200
grid_lmx_capture_test.php --server=t70aic100 --path=/opt/IBM/lmx/bin --port=6200
if (strlen($host)) {
        $command2  = "ssh -o ConnectTimeout=60 $server \"cd $path ; " . (strlen($path) ? $path . "/": "") . "lmxendutil -licstat -port $port -host $host 2> /dev/null\"";
}elseif (!strlen($host)) {
        $command2  = "ssh -o ConnectTimeout=60 $server \"cd $path ; " . (strlen($path) ? $path . "/": "") . "lmxendutil -licstat -port $port -host $server 2> /dev/null\"";
}


if (isset($host)) {
        $command2  = "ssh -o ConnectTimeout=60 $server \"cd $path ; " . (strlen($path) ? $path . "/": "") . "lmxendutil -licstat -port $port -host $host 2> /dev/null\"";
}elseif (!isset($host)) {
        $command2  = "ssh -o ConnectTimeout=60 $server \"cd $path ; " . (strlen($path) ? $path . "/": "") . "lmxendutil -licstat -port $port -host $server 2> /dev/null\"";
}


if (isset($host)) {
        $command2  = "ssh -o ConnectTimeout=60 $server \"cd $path ; " . (strlen($path) ? $path . "/": "") . "lmxendutil -licstat -port $port -host $host 2> /dev/null\"";
}else{
        $command2  = "ssh -o ConnectTimeout=60 $server \"cd $path ; " . (strlen($path) ? $path . "/": "") . "lmxendutil -licstat -port $port -host $server 2> /dev/null\"";
}

when using strlen example:

ssh -o ConnectTimeout=20 t70aic100 "cd /opt/IBM/lmx/bin ; /opt/IBM/lmx/bin/lmxendutil -licstat -port 6200 -host denasv004 2> /dev/null"
ssh -o ConnectTimeout=20 t70aic100 "cd /opt/IBM/lmx/bin ; /opt/IBM/lmx/bin/lmxendutil -licstat -port 6200 -host t70aic100 2> /dev/null"

when using either isset example:

ssh -o ConnectTimeout=20 t70aic100 "cd /opt/IBM/lmx/bin ; /opt/IBM/lmx/bin/lmxendutil -licstat -port 6200 -host denasv004 2> /dev/null"
ssh -o ConnectTimeout=20 t70aic100 "cd /opt/IBM/lmx/bin ; /opt/IBM/lmx/bin/lmxendutil -licstat -port 6200 -host  2> /dev/null"

How do you set $host? Do you assume $host is automatically set by appending --host=$host to your php-program-call? If that is so: That's not happening - you have to parse command line args. Or did you just leave the command line parsing code out? If so, please show the code, how you parse the command line args.

yes, i just left that bit out since i would let you guys assume i had that part covered and to limit how big the post got.

<?php
#!/usr/bin/php -q

if (!isset($_SERVER["argv"][0]) || isset($_SERVER['REQUEST_METHOD'])  || isset($_SERVER['REMOTE_ADDR'])) {
        die("<br><strong>This script is only meant to run at the command line.</strong>");
}

$no_http_headers = true;

chdir(dirname(__FILE__));
chdir("../../");
include("./include/global.php");
include_once("./lib/xml.php");

$parms = $_SERVER["argv"];
array_shift($parms);

global $debug;

$debug   = FALSE;
$server  = "";
$host    = "";
$port    = "";
$path    = "";
$timeout = 20;

foreach($parms as $parameter) {
        @list($arg, $value) = @explode("=", $parameter);

        switch ($arg) {
        case "-D":
        case "--debug":
                $debug = TRUE;
                break;
        case "-S":
        case "--server":
                $server = $value;
                break;
        case "-H":
        case "--host":
                $host = $value;
                break;
        case "-O":
        case "--port":
                $port = $value;
                break;
        case "-P":
        case "--path":
                $path = $value;
                break;
        case "-T":
        case "--timeout":
                $timeout = $value;
                break;
        case "-v":
        case "-V":
        case "--version":
        case "--help":
        case "-h":
        case "-H":
                display_help();
                exit;
        default:
                print "ERROR: Invalid Parameter " . $parameter . "\n\n";
                display_help();
                exit;
        }
}

Hi crimso,

This is very appreciated indeed.

First of all. There are functions and libs for everything. Command-Line-Option Parsing may be done with getopt: Look here: PHP: getopt - Manual

(But you may ignore that, if your code works).

The following does not work:

<?php 
#!/usr/bin/php -q

If you decide to use #!, it has to be at the very beginning of the Script-File. Only then the kernel will read the following binary as interpreter for the actual file.

Further without testing the code myself, I suggest you test, if your Arg-parsing produces correct output. I suspect it may not fully work as expected and the values are not what you assume them to be. I suggest you insert some debug statements before+after Arg parsing like:

print_r($parms);
print_r($arg);
print_r($value);
print_r($host);
print(gettype($host));

A logging function would help you to debug your code independently of the running environment(webserver or command line).

#!/usr/bin/php
<?PHP
# global log-file handle
$log = NULL;
function mylog($msg=NULL) {
       $logfile="/tmp/myapp.log";  # There may be better locations than /tmp for the logfile
       global $log;
       if(!$log) {   
            # only open logfile once per script run. After the first
            # mylog() invocation the open filehandle will be used.
            # Also be lazy and let it automatically be closed at 
            # end of programm by php itself
          $log = fopen($logfile,"a");
          if(! $log) die("Cannot open Logfile: " . error_get_last());
       }
       if($msg) {
                fwrite($log,date("Y/m/d h:i:s",mktime())." : ".getmypid()." : ".(string)$msg."\n");
       }
}

The above mentioned debug statements are easily usable with such a log function(print_r needs to be told, that it returns the formated dump data and so it does not print it to stdout itself).

mylog(print_r($host,true));

PHP: Hypertext Preprocessor

PHP.net is a great and fabulous source of documentation for PHP. Nearly all functions documentation pages have directly attached real-life coding examples down at the bottom of each page.

before i posted my query i commented all the parsing, processing and db statements and simply put echoes at the bottom so it would print the ssh command and all of the variables i expected to get set. the variables were all set as expected and so was the ssh command when i use strlen to determine if the $host variable was set. however, when i use either of the isset chunks the $server after the -host argument is null but the $server after the ConnectTimeout=60 is okay. i just don't get why my isset chunks won't put $server in both places i expect it to be when $host is not set. so let me ask this, do the two isset pieces look okay? thanks.

Read the documentation at php.net and what there is written to isset() and strlen(). That are different tests.

Check out your values of $host and check them against:

<?PHP 

function test ($var=NULL) {

        print("\$var is ".(isset($var)?"":"not ")."set\n");
        print("\$var check of len > 0 is ".(strlen($var)?"true(".(strlen($var)).")":"false")."\n");

}

test("");
test();
test(0);

?>

---------- Post updated at 06:33 PM ---------- Previous update was at 06:25 PM ----------

And an offer for another coding style of your specific snippet:

<?PHP

$host="bla";
$server="blub";
$path="";
$port="123";

$template = "ssh -o ConnectTimeout=60 %s \"cd %s ; %slmxendutil -licstat -port %s -host %s 2>/dev/null\"";
$command  = sprintf(
                $template,
                $server,
                $path,
                (strlen($path)?"$path/":""),
                $port,
                strlen($host)?$host:$server);

print("$command\n");

?>

and maybe you like to use "ssh2"-functinality of php.

PHP: SSH2 - Manual

finally figured this one out. if i delete or comment the line in the php script:

$host    = "";

the code works as expected now. it finally sunk in after reading the isset documentation untold times that a NULL variable is still a set variable. so although i had not supplied the:

--host=denasv004

as a command line arg to the script it would not put the $server value there because i had set $host as NULL with the:

$host    = "";

so consequently is displayed it as NULL.

Hi crimso,

congrats that you got it fixed!

Let me mention that NULL is a special value. An empty string is NOT NULL. An empty string is still a string.

The interactive php interpreter may help you with testing of code.

hellfire@hellfire:~$ php -a
Interactive mode enabled
php > var_dump("");
string(0) ""
php > 

The mentioned function gettype() and var_dump() help you a lot in debugging!

yeah, so i've discovered. been reading up on that today, had no idea it had such a large scope. thanks again for chiming in. this thread was surprisingly quiet. people here have been more vocal in the past typically.