Solved

PHP and shell_exec return value

Posted on 2007-12-06
14
2,025 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
 
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
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
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 500 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

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

If I have to fix slow responding website my first thoughts are server side optimizations: the database may not be optimized or caching is not enabled, or things like that. We often overlook another major part of our web application: the client. We o…
Real-time is more about the business, not the technology. In day-to-day life, to make real-time decisions like buying or investing, business needs the latest information(e.g. Gold Rate/Stock Rate). Unlike traditional days, you need not wait for a fe…
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
Learn how to set-up custom confirmation messages to users who complete your Wufoo form. Include inputs from fields in your form, webpage redirects, and more with Wufoo’s confirmation options.

706 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

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now