Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

PHP and shell_exec return value

Posted on 2007-12-06
14
Medium Priority
?
2,191 Views
Last Modified: 2013-12-12
All,

I'm 100% certain that the following code should return an error, however $res appears to be null.

$res = shell_exec($this->cmd);

According to php.net documentation, the return value is the result of the command and should appear in $res.  $this->cmd looks like the following:

          $this->cmd = "mysqldump -Q -u $this->dbUser -p$this->dbPass $this->dbName";
            
          $this->cmd .= ($this->zip==="bz2") ?
                  " | bzip2 > $this->dest". '/' ."$fname"  :
                  " | gzip > $this->dest".'/'."$fname";

Thanks for any ideas... this should only not come back with any results for a successful dump.
0
Comment
Question by:stevefNYC
  • 6
  • 4
  • 3
  • +1
14 Comments
 
LVL 21

Expert Comment

by:nizsmo
ID: 20422966
hi steve,

try and print out $this->cmd and is it the command you are expecting? when you actually use shell to execute the command does it return anything?
0
 
LVL 35

Expert Comment

by:Terry Woods
ID: 20422996
Don't you just want two equal signs for this command, rather than 3?:
($this->zip==="bz2")
0
 
LVL 3

Author Comment

by:stevefNYC
ID: 20423007
Hey nizsmo,

Yes I've tried that.  I copy/pasted the command from my debug console where I spit it out to make sure the syntax is right... I should be getting an error back:

sf:tmp sf$ mysqldump -Q -u root -pthisisnotmypass foobar | bzip2 > /tmp/builder/foobar.sql.bz2
-bash: /tmp/builder/foobar sql.bz2: No such file or directory
mysqldump: Got error: 2002: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) when trying to connect

I'm intentionally creating that error on the server-side... I just want the return value to pick it up... (just giving a heads up for those who come into this thread and try to start fixing my mysqldump error... it's intentional.)
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 35

Expert Comment

by:Terry Woods
ID: 20423012
I suspect also that:
                  " | bzip2 > $this->dest". '/' ."$fname"  :
                  " | gzip > $this->dest".'/'."$fname";

may need curly brackets added, like this:
                  " | bzip2 > {$this->dest}". '/' ."$fname"  :
                  " | gzip > {$this->dest}".'/'."$fname";

though I'm not 100% sure
0
 
LVL 3

Author Comment

by:stevefNYC
ID: 20423018
TerryAtOpus,

The identity operator works fine in this scenario. I'm making sure that the type in this case matches as well.
0
 
LVL 21

Expert Comment

by:nizsmo
ID: 20423037
how about simplifying the command and trying it? its not hard to produce an error :)
as you can see here:
http://www.php.net/shell_exec

the return value is indeed the return message, maybe give the example on that webpage a try?
0
 
LVL 3

Author Comment

by:stevefNYC
ID: 20423107
Works fine when I try the 'ls -ltr' example. Still not returning anything for my mysqldump invocation though
0
 
LVL 21

Expert Comment

by:nizsmo
ID: 20423154
oh? maybe then it will only capture successful command outputs and not error outputs? just a thought.
0
 
LVL 3

Author Comment

by:stevefNYC
ID: 20423186
Well, according to php.net the following reads in a user comment:

``ALSO, note that shell_exec() does not grab STDERR, so use "2>&1" to redirect it to STDOUT and catch it.''

I've modified my code to read           

$this->cmd .= ($this->zip==="bz2") ?
                  " | bzip2 > $this->dest". '/' ."$fname 2>&1"  :
                  " | gzip > $this->dest".'/'."$fname 2>&1";

Still no go though.

0
 
LVL 35

Expert Comment

by:Terry Woods
ID: 20423455
The following worked for me:
  $cmd = "mjysqldump -Q -u 2>&1";
  $result = shell_exec($cmd);
  echo "Result: '$result'";

Outputs:
Result: 'sh: line 1: mjysqldump: command not found '
0
 
LVL 35

Expert Comment

by:Terry Woods
ID: 20423491
Not sure how likely it is that you're running a different shell from what's normal, but different shells use different syntax to redirect the STDERR. How about trying copying and pasting my example, and see what you get?
0
 
LVL 3

Author Comment

by:stevefNYC
ID: 20424992
I'm just using good ol' bash, Terry.

foo:~ sf$ echo $SHELL
/bin/bash
foo:~ sf$ bash --version
GNU bash, version 3.2.17(1)-release (i386-apple-darwin9.0)
Copyright (C) 2005 Free Software Foundation, Inc.
0
 
LVL 9

Accepted Solution

by:
tkalchev earned 2000 total points
ID: 20448522
Adding  "2>&1" at the end of the command should show you the actual error.  Your problem here is that you are using a complex command, which uses pipes and redirects the output to a file. Actually you are executing 2 commands, first is

mysqldump -Q -uUSERNAME -pPASSWORD DATABASENAME

second is

gzip > FILENAME  (I will assume that you use GZIP to simplify the explanation )


When you pipe the commands as you did the complete output from the first command is sent to the STDIN of the second one.
When you add 2>&1 at the end of the command line you get the following :

mysqldump -Q -uUSERNAME -pPASSWORD DATABASENAME | gzip > FILENAME 2>&1

the following is happened :
1. The first command is executed
2. The contents of everything printed on the 1st's command STDOUT is send to the STDIN of the second command
3. If something (the error message in your case) is sent to the STDERR, it is displayed on the system's STDERR and won't be catched by your shell_exec, as it catches only STDOUT
4. The STDOUT of the second command is redirected to FILENAME
5. The STDERR of the second command is redirected to its STDOUT

This situation won't help you, because you need the STDERR of the first command, not the senond's
So, let's modify it a little bit :

mysqldump -Q -uUSERNAME -pPASSWORD DATABASENAME 2>&1 | gzip > FILENAME

what is changed here :

1. The first command is executed
2. The contents of everything printed on the 1st's command STDOUT is send to the STDIN of the second command
3. If something (the error message in your case) is sent to the STDERR, it is also redirected to the STDOUT, actually to the second command's STDIN
4. The STDOUT of the second command is redirected to FILENAME

Now you have the error message gzipped in the FILENAME, you can check it if you run  zcat FILENAME ... Also not exactly what you have expected.

One possible solution for your case is to play a little bit with the I/O redirection, you can for example issue a command line like this :

exec 6>&1 2>&1 1>/tmp/output; mysqldump  -uUSER -pPASSWORD DATABASENAME ; exec 1>&6 6>&-; if [ -s /tmp/output ]; then cat /tmp/output | gzip > FILENAME; rm -f /tmp/output; fi

What it does :

1. exec 6>&1 2>&1 1>/tmp/output : redirects the STDERR to STDOUT and then STDOUT to a file /tmp/output
2. mysqldump  -uUSER -pPASSWORD DATABASENAME  : it just runs your 1st command
3. exec 1>&6 6>&-   : restores the STDOUT and closes descriptor 6
4. if [ -s /tmp/output ]; then cat /tmp/output | gzip > FILENAME; rm -f /tmp/output; fi   : if the file /tmp/output exists and is not empty it is being gzipped to a file FILENAME and then deleted


Hope it will help you
0
 
LVL 3

Author Closing Comment

by:stevefNYC
ID: 31413250
Beautiful and concise answer. Thank you kindly.  

Until you responded, I just ended up splitting the commands into two, avoiding any file redirection...
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This article is intended for those who are new to PHP error handling (https://www.experts-exchange.com/articles/11769/And-by-the-way-I-am-New-to-PHP.html).  It addresses one of the most common problems that plague beginning PHP develop…
While opting for any web-to-print solution, you need to discuss with your team and some of your end users and know their opinions about your decisions. In this article we list down some questions you need to ask yourself.
This video teaches users how to migrate an existing Wordpress website to a new domain.
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.
Suggested Courses

877 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question