I execute the following command to make a database backup:
$exec = exec("mysqldump --opt
--user=$database_user
--password=$database_pass
--host=$database_host
$database_name > $output_filename", $out, $status);
To check if mysqldump failed I do:
if ($status == 0) {
// OK
} else {
// Error
// How could I print the error message here ?
}
In case something goes wrong and mysqldump fails, how could I get the error message ?
You can use proc_open (as also suggested by Emil). below is a somewhat more complete example of how to achieve what you want.
$exec_command = "mysqldump --opt
--user=$database_user
--password=$database_pass
--host=$database_host
$database_name"
$descriptorspec = array(
0 => array("pipe", "r"), // stdin pipe
1 => array("file", $output_filename, "w"), // stdout to file
2 => array("pipe", "w") // stderr pipe
);
$proc = proc_open($exec_command, $descriptorspec, $pipes);
fwrite($pipes[0], $input); //writing to std_in
fclose($pipes[0]);
$err_string = stream_get_contents($pipes[2]); //reading from std_err
fclose($pipes[2]);
$return_val = proc_close($proc);
EDIT:
changed output to write to file
You'll need to use proc_open if you want to read stderr. The example in the manual should get you going.
If you are using shell_exec, append 2>&1 to the command, it will redirect STDERR to STDOUT.
Related
I am running a command using shell_exec()
Let's say I have 400 directories and I can not wait for the command to run completely.
Is there a way, I can get the output Asynchronous?
$output = shell_exec('ls');
echo "<pre>$output</pre>";
$cmd = $command;
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a pipe that the child will write to
);
flush();
$process = proc_open($cmd, $descriptorspec, $pipes, realpath('./'), array());
echo "<pre>";
if (is_resource($process)) {
while ($s = fgets($pipes[1])) {
print $s;
flush();
}
}
echo "</pre>";
The Code above Worked perfectly for me, This is copied from another answer I can no longer find. If you put a ping 127.0.0.1 in the $command it works exactly like it does in a terminal.
Check this: Is there a way to use shell_exec without waiting for the command to complete?
And instead of redirecting to /dev/null you could redirect to a tmp file that you read later.
I have a Python script that prompts the user for inputs.
input = raw_input("Enter input file: ")
model = raw_input("Enter model file: ")
While I can use the following PHP command to execute the script, how can I provide inputs when prompted?
$output = shell_exec("python script.py");
Also, like shell_exec(), I want to return all lines of output, not just the first/last line printed.
Solution that worked:
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w")
);
$process = proc_open('python files/script.py', $descriptorspec, $pipes, null, null); // run script.py
if (is_resource($process)) {
fwrite($pipes[0], "files/input.txt\n"); // input 1
fwrite($pipes[0], "files/model.txt\n"); // input 2
fclose($pipes[0]); // has to be closed before reading output!
$output = "";
while (!feof($pipes[1])) {
$output .= fgets($pipes[1]);
}
fclose($pipes[1]);
proc_close($process); // stop script.py
echo ($output);
}
Reference: Piping between processes in PHP
I propose to concatenate all output lines with a delimiter character like $ and decompose it on the PHP side using explode function to have an array.
I decided to use Pygments for a website I'm working on, but my lack of terminal knowledge is amazing.
I want to use pygmentize to highlight syntax in blog posts, but as they are stored in database I can't just pass filename to it. Is there any way I can pass string into it?
If not, I will have to save post contents in a temp file, pygmentize it and load into database but this adds overhead that I would really like to avoid if at all possible.
I don't see CLI documentation saying anything about it.
The man page says it reads from stdin if infile is omitted and it writes to stdout if outfile is omitted.
So on the cmdline you would type:
$ pymentize -l php -f html
<?php
echo 'hello world!';
^D // type: Control+D
pymentize would output:
<div class="highlight"><pre><span class="cp"><?php</span>
<span class="k">echo</span> <span class="s1">'hello world!'</span><span class="p">; </span>
</pre></div>
If you'll run this with from PHP you'll have to start pygmentize using proc_open() as you'll have to write to stdin of it. Here comes a short example how to do it:
echo pygmentize('<?php echo "hello world!\n"; ?>');
/**
* Highlights a source code string using pygmentize
*/
function pygmentize($string, $lexer = 'php', $format = 'html') {
// use proc open to start pygmentize
$descriptorspec = array (
array("pipe", "r"), // stdin
array("pipe", "w"), // stdout
array("pipe", "w"), // stderr
);
$cwd = dirname(__FILE__);
$env = array();
$proc = proc_open('/usr/bin/pygmentize -l ' . $lexer . ' -f ' . $format,
$descriptorspec, $pipes, $cwd, $env);
if(!is_resource($proc)) {
return false;
}
// now write $string to pygmentize's input
fwrite($pipes[0], $string);
fclose($pipes[0]);
// the result should be available on stdout
$result = stream_get_contents($pipes[1]);
fclose($pipes[1]);
// we don't care about stderr in this example
// just checking the return val of the cmd
$return_val = proc_close($proc);
if($return_val !== 0) {
return false;
}
return $result;
}
Btw, pygmentize is pretty cool stuff! I'm using it too :)
i'm trying to write a php page that
call for a server program like
gdb
the problem is if i did
<?php
exec(" gdb code", $out);
?>
the PHP call for the command and exist
BUT what i want to do is like open a "terminal" session
where the user enter commands in that program like
gdb code
..
break main
..
run
and after each command i give him the output and he give me the next command
and it won't work if i did it like this
<?php
exec(" gdb code", $out);
exec(" break", $out);
exec(" run", $out);
?>
and the PHP can be run from a browser
and i tried it with pro_open
<?php
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("file", "/var/www/err.log", "a")
);
$cwd = '/var/www';
$env = array('some_option' => 'aeiou');
$StdErr='';
$process = proc_open('/bin/bash', $descriptorspec, $pipes, $cwd, $env);
if (is_resource($process)) {
fwrite($pipes[0], "gcc code ");
fwrite($pipes[0], " break main");
fflush($pipes[0]);
fclose($pipes[0]);
while(!feof($pipes[1])) {
echo fgets($pipes[1], 1024);
}
echo $StdErr;
fclose($pipes[1]);
$return_value = proc_close($process);
echo "command returned : $return_value\n";
}
and thank you .
Edit just saw you do try it from a browser. There is absolutely no simple way to do this. If you want an interactive session from the browser, you must run a separate daemon process and forward commands to it from PHP (and return output).
This is not simple at all; so if you still feel like doing this.. I would recommend starting with how to create a deamon; and then write a tcp socket server (or other IPC).
Excuse the crappy grammar
I've this shell script running from a PHP site.
In the shell script (Audit shell script),
I have 3 options:
1) Process script
2) Display results
3) Exit
Tried the codes below and doesn't seem to work, the PHP site displayed blanks.
<?php
session_start();
exec('/Desktop/test.sh');
exec('1');
$output = exec('2');
echo "<pre>$output</pre>";
?>
Any help will be greatly appreciated.
<?php
session_start();
// This line executes '/Desktop/test.sh' as if it had been called from the
// command line
// exec('/Desktop/test.sh');
// This line attempts to execute a file called '1', which would have to be
// in the same directory as this script
// exec('1');
// This line attempts to execute a file called '2', which would have to be
// in the same directory as this script, and capture the first line of the
// output in $output
// $output = exec('2');
// I think you want to be doing something more like this - this executes the
// shell script, passing "1" and "2" as arguments, and captures the whole
// output as an array in $output
exec('/Desktop/test.sh "1" "2"', $output);
// Loop the output array and echo it to the browser
echo "<pre>";
foreach ($output as $lineno => $line) echo "Line $lineno: $line\n";
echo "</pre>";
?>
It seems to me that you could do with reading the manual page for exec() properly...
Try using proc_open instead of exec; it gives you more control of process input/output. Something like:
<?php
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("file", "/dev/null", "a") // stderr is a file to write to
);
$cwd = '/Desktop';
$env = array();
$process = proc_open('/Desktop/test.sh', $descriptorspec, $pipes, $cwd, $env);
if (is_resource($process)) {
// $pipes now looks like this:
// 0 => writeable handle connected to child stdin
// 1 => readable handle connected to child stdout
// Any error output will be sent to /dev/null (ie, discarded)
fwrite($pipes[0], "1\n");
fwrite($pipes[0], "2\n");
fclose($pipes[0]);
$output = stream_get_contents($pipes[1]);
fclose($pipes[1]);
// It is important that you close any pipes before calling
// proc_close in order to avoid a deadlock
$return_value = proc_close($process);
echo $output;
}
?>
Note: I've lifted this code from the PHP Manual's proc_open page