I'd like to run something like (in myProgram.sh):
java -cp whatever.jar com.my.program $1
within PHP and read the output.
So far I have something like:
$processOrderCommand = 'bash -c "exec nohup setsid /myProgram.sh ' . $arg1 . ' > /dev/null 2>&1 &"';
exec($processOrderCommand);
But what I'd really like is to be able to get the output of the java program within the PHP script and not just execute it as another thread.
How can this be done?
You can do this :
exec($processOrderCommand, $output);
From the documentation :
If the output argument is present, then the specified array will be filled with every line of output from the command. Trailing whitespace, such as \n, is not included in this array. Note that if the array already contains some elements, exec() will append to the end of the array. If you do not want the function to append elements, call unset() on the array before passing it to exec().
For a better control on your execution you can take a look at proc_open()
Resources :
php.net - exec()
php.net - proc_open()
The key is that the classpaths need to be absolute within the shell_exec
PHP script.
Or at least that's the only way I could get it to correctly work. Basically it's almost impossible to tell from environment to environment what the relative directory is that the php script is running the JVM.
As well, it helped to put the absolute path location for java, such as usr/.../bin/java
Related
I just cannot fathom how to get the PHP exec() or shell_exec() functions to treat a '*' character as a wildcard. Is there some way to properly encode / escape this character so it makes it through to the shell?
This is on windows (via CLI shell script if that matters, Terminal or a git-bash yields the same results).
Take the following scenario:
C:\temp\ contains a bunch of png images.
echo exec('ls C:\temp\*');
// output: ls: cannot access 'C:\temp\*': No such file or directory
Permissions is not the problem:
echo exec('ls C:\temp\exmaple.png');
// output: C:\temp\example.png
Therefore the * character is the problem and is being treated as a literal filename rather than a wildcard. The file named * does not exist, so from that point of view, it's not wrong...
It also does not matter if I use double quotes to encase the command:
echo exec("ls C:\temp\*");
// output: ls: cannot access 'C:\temp\*': No such file or directory
I have also tried other things like:
exec(escapeshellcmd('ls C:\temp\*'));
exec('ls C:\temp\\\*');
exec('ls "C:\temp\*"');
exec('ls "C:\temp\"*');
And nothing works...
I'm pretty confused that I cannot find any other posts discussing this but maybe I'm just missing it. At this point I have already worked around the issue by manually programming a glob loop and using the internal copy() function on each file individually, but it's really bugging me that I do not understand how to make the wildcard work via shell command.
EDIT:
Thanks to #0stone0 - The answer provided did not particularly answer my initial question but I had not tried using forward slashes in the path and when I do:
exec('ls C:/temp/*')
It works correctly, and as 0stone0 said, it only returns the last line of the output, which is fine since this was just for proof of concept as I was not actually attempting to parse the output.
Also, on a side note, since posting this question my system had been updated to Win11 22H2 and now for some reason the original test code (with the backslashes) no longer returns the "Cannot access / no file" error message. Instead it just returns an empty string and has no output set to the &$output parameter either. That being said, I'm not sure if the forward slashes would have worked on my system prior to the 22H2 update.
exec() only returns the last output line by default.
The wildcard probably works, but the output is just truncated.
Pass an variable by ref to exec() and log that:
<?php
$output = [];
exec('ls -lta /tmp/*', $output);
var_dump($output);
Without any additional changes, this returns the same as when I run ls -lta /tmp/* in my Bash terminal
That said, glob() is still the preferred way of getting data like this especcially since
You shouldn't parse the output of ls
I hope you can help me.
I am dealing with a problem that I cannot solve. This is my issue. I am trying to exec a bash script through PHP. I tried with the method
exec()
with 3 arguments, arg1, arg2, and arg3.
php code
<?php exec("./randomScript.sh arg1 arg2 arg3"); ?>
randomScript.sh
.... # random code which exploits the three arguments -> executed normally..
.... # random code which exploits the three arguments -> executed normally..
./secondScript.sh $arg1 $arg2 $arg3 #<- this is the script that is not running (is not even started).
I have tried to change the permission (I've got full permission), change the way I call the randomScript.sh (through absolute path), but nothing occurred. Besides, I tried with:
shell_exec()
method, but nothing changed. Of course, if I run the secondScript.sh via terminal everything works fine.
I cannot understand which is the problem. Could you please help me?
Thanks in advance.
In the inner shell, the arguments are not called like that (because it is invoked by the shell, not by PHP).
./secondScript.sh "$1" "$2" "$3"
or just
./secondScript.sh $*
At this stage, just remember that spaces, quotes, and dollar signs in the arguments you pass must be avoided at all costs (the solution is escaping them, but how to do it exactly is tricky).
You also might want to do instead:
$ret = shell_exec("./randomScript.sh 'arg1' 'arg2' 'arg3' 2>&1");
so that in $ret you might find error messages and output from the inner shell.
You should escape your string command before passing it in exec function, i think it may help you
Escapeshellcmd()
...
$escaped_command = escapeshellcmd("./randomScript.sh arg1 arg2 arg3");
exec($escaped_command);
...
Escapeshellarg()
For system command, i recommand using system
...
$escaped_command = escapeshellarg("./randomScript.sh arg1 arg2 arg3");
system($escaped_command);
...
You also need to make sure that your PHP code does not change working dir, and both shell scripts have execute permissions, and filesystems allows to exec files on it.
I would avoid exec("./script $arg ...");, I would rather specify the interpreter to use and full path to the script like exec("sh /home/user/project/script.sh $arg ...");
I want to pass the string from my php like
<?php
str1="string to pass"
#not sure about passthru
?>
And my tcl script
set new [exec $str1]#str1 from php
puts $new
Is this Possible? Please let me know I'm stuck with this
The simplest mechanism is to run the Tcl script as a subprocess that runs a receiving script (that you'd probably put in the same directory as your PHP code, or put in some other location) which decodes the arguments it is passed and which does what you require with them.
So, on the PHP side you might do (note the important use of escapeshellarg here! I advise using strings with spaces in as test cases for whether your code is quoting things right):
<?php
$str1 = "Stack Overflow!!!";
$cmd = "tclsh mycode.tcl " . escapeshellarg($str1);
$output = shell_exec($cmd);
echo $output;
echo $output;
?>
On the Tcl side, arguments (after the script name) are put in a list in the global argv variable. The script can pull them out with any number of list operations. Here's one way, with lindex:
set msg [lindex $argv 0]
# do something with the value from the argument
puts "Hello to '$msg' from a Tcl script running inside PHP."
Another way would be to use lassign:
lassign $argv msg
puts "Hello to '$msg' from a Tcl script running inside PHP."
Note however (if you're using Tcl's exec to call subprograms) that Tcl effectively automatically quotes arguments for you. (Indeed it does that literally on Windows for technical reasons.) Tcl doesn't need anything like escapeshellarg because it takes arguments as a sequence of strings, not a single string, and so knows more about what is going on.
The other options for passing values across are by environment variables, by pipeline, by file contents, and by socket. (Or by something more exotic.) The general topic of inter-process communication can get very complex in both languages and there are a great many trade-offs involved; you need to be very sure about what you're trying to do overall to pick an option wisely.
It is possible.
test.php
<?php
$str1="Stackoverflow!!!";
$cmd = "tclsh mycode.tcl $str1";
$output = shell_exec($cmd);
echo $output;
?>
mycode.tcl
set command_line_arg [lindex $argv 0]
puts $command_line_arg
I have a C code that I have to execute through PHP,
I have used exec('./sys'), sys is my executable file.
I have also tried system(), passthrough(), shell_exec() and they are not giving output.
When I executed exec('who'); it gives the output.
What can I do to execute sys?
Each of those methods you reference will execute your sys file, but you need to make sure you are executing the correct path. Your working path is determined by what script is actually executing PHP. For example, if you're executing your code through apache or the command line your working directory may be different. Lets assume this file structure:
+ src/
| + script.php
| + sys
I would recommend using PHP's __DIR__ magic variable in your script.php to always reference the current file's directory, and then work from there:
// script.php
exec(__DIR__ . "/sys");
Retrieving output can be done a couple different ways. If you want to store the output of the script in a variable, I would recommend using exec according the the manual:
Parameters ΒΆ
command
The command that will be executed.
output
If the output argument is present, then the specified array will be filled with every line of output from the command. Trailing whitespace, such as \n, is not included in this array. Note that if the array already contains some elements, exec() will append to the end of the array. If you do not want the function to append elements, call unset() on the array before passing it to exec().
return_var
If the return_var argument is present along with the output argument, then the return status of the executed command will be written to this variable.
exec will return the first line of output, but if you want more than that you need to pass a variable by reference:
// script.php
$output = array();
exec(__DIR__ . "/sys", $output);
$output will then contain an array of each line of output from the command. However if you want to run your sys script and directly pass through the output then use passthru(__DIR__ . "/sys"); For example, if you wanted to execute a command that required input on the command line, passthru would be the best option.
I have installed SymPi in the server and from the command line, I am able to execute the following.
python ./sympy-0.7.5/bin/isympy
(this will open a console where I can type mathematical expressions. then the following expression)
1 + 2
(will give 3 as output)
My aim is to do the same from php using shell_exec. I have written a php file as given below, but is not working.
$command = escapeshellcmd('python ./sympy-0.7.5/bin/isympy');
shell_exec($command);
$output = shell_exec('1 + 2');
Can anybody help me to figure out why this is not working?
Please note that the following script works fine which just execute a python script and retrieve the output.
$command = escapeshellcmd('python C:\PythonPrograms\test3.py');
$output = shell_exec($command);
echo $output;
My guess is that the working directory (cwd) of shell_exec is different from the one you're in when you execute it manually.
Your working example specifies a hard path that will work from anywhere. Whereas your not-working example specifies a relative path (./ is the cwd).
Convert your call to isympy to give its full path on disk. Or figure out how to set the cwd of shell_exec.
(If this doesn't solve it, say more than "is not working." What happens? An error? What is the full text of the error?)
Each time you run shell_exec, it opens a completely new instance of the shell.
Edit:
You can pass a command for python to execute like this:
$expression = '1 + 2';
$cmd = 'python -c \'print "%f" % (' . $expression . ')\'';
$output = shell_exec($cmd);
This, admittedly is not using sympy, but for simple mathmatical expressions you may not need to. If you do, you would just need to import the library in the same command, like this: python -c 'import sympy; print "%f" % sympy.sqrt(3)'
I could manage the desired result in a different way.
Created a python script which accepts the expression as the command line argument , execute and display the output.
Call this script from php by passing the expression as the command line argument.