Using a single command line through php - php

I am trying to run a c++ executable that I have on my computer through my PHP interface. I do not have admin rights on the computer that my PHP is being hosted from and therefore cannot add the appropriate items to my PATH for my c++.
I am able to call the exec function in PHP and run my program via a batch file. In my batch file I am able to set my path variable to what I need it to be.
Here is what I am currently doing (with runVideoparser being the batch file):
exec("C:\\Users\\hewittjc\\Desktop\\runVideoParser", $output, $return);
echo "Program returned $return.";
The above works just fine when passing a fixed parameter to my c++ in the batch.
However, my issue is that I need to be able to pass the program different arguments each time. If I run it via batch file then I loose this ability.
So my question is, How can I:
1) Open a command prompt via PHP (I'm running windows)
2) Set my path variable in the prompt via PHP
3) Then, using that same prompt to preserve the path variable, run my program passing it the required argument.
I suppose I could generate the batch in my PHP then run that, but I am seeking any more elegant solutions.

In theory, you can do something like this:
$old_path = getenv("PATH");
$new_path = "/my/additional/path:$old_path";
putenv("PATH=$new_path");
system("command -with flags -and args -and such");
However, this won't work if the host machine has Safe Mode on and PATH is not in the safe_mode_allowed_env_vars directive.

Related

Using bash, how to change the name of a file based on feedback from PHP script?

I have git bash and I am making commits using it. I need however, to make the .bashrc alias, that will also run a php script, return a value N (which is a number) from that script, and use that value Nto change the name of a file like so:
nameOfFileN
How do I do this? I need this sequence of commands. It is my local windows machine. I have php installed. I use windows git bash to use git. I want to run this in it (in the git bash). I need this bash command together with the php file that just returns an echo-ed variable value.
If your PHP script is hosted in a webserver, use curl:
curl http://localhost/path/to/script.php
If it is a stand-alone script and you have the PHP CLI interpreter installed, run the script directly:
php /path/to/script.php
Both calls will give you the output of the PHP script. Use it however you need (pipe it to another process, redirect it to a file, use it for command substitution, assign it to a shell variable, …)

Accessing python nltk with php fails

Im trying to call a python file containing a sentence/word tokenizer from my php file like this:
$output = shell_exec('python tokenizer.py $sentence')
I've tried single exec, full paths to python and tokenizer.py, wrapping $sentence in double quotes. But logically, It should not be the problem because calling print(1) at the beginning of python the python code before actually using any nltk packages makes $output equal to '1'. So I came to conclusion that the problem here is the nltk itself, like the path to the modules is not correct or something...
But, calling python from the shell using the same command as above gives me fully tokenized output! To conclude: looks like when calling python from php magically 'turns off' nltk, while it fully works when executed from the shell.
Here's the part of the python code I am using:
import sys
import nltk
from nltk.tokenize import sent_tokenize
sample_text2 = sys.argv[1]
gust = sent_tokenize(sample_text2)
#print(1) here doesn't work, but everywhere above (before calling sent_tokenize) it does.
The server's running on CentOS (Linux), I am accessing it via SSH.
Obvious question: What am I doing wrong here with PHP? Or generally? Any alternatives?
EDIT
As visible in dvhh's answer and its comments, the situation happened because there were two versions installed on the server (2.6 and 2.7), while the www user had access to 2.6 and through console, the default version was 2.7. The solution was to change the default python to 2.7 for both cases and to put the nltk modules to one of the dependency folders. (Or append the dependency directory using sys.path.append)
Your php script is executed by the www user.
You could check if the python script interpreter is correctly called, it is usually in one of the directory in the PATH environment variable (like /usr/bin/python), but the www user don't have a PATH environment variable set.
Solution specify the whole path to your python interpreter in your shell_exec call ( also specify the full path to your script when you're at it )
What about the path the nltk library is installed, you could check if the python interpreter would correctly look for it by looking at the sys.path while running python with the www user.
Diagnostic : use the shell_exec call to run a python script to print the sys.path values
Solution : append the library path to the sys.path in your python script before the import nltk
These would be the most obvious solutions considering the information provided in the question.
Update :
As there is 2 version version of python installed (on that haven't got the library installed ), it is recommended to specify the path to the desired interpreter. The first solution help correct the issue.
In unix like system I would recommend using which python command to determine the path of your default python interpreter.
Option 1
Setup a simple python httpserver listening on localhost. This old answer might help but there are plenty of howtos out there. The advantage is that you don't have the overhead of starting the python interpreter each time the ntlk stuff needs to be executed and you don't have to worry about shell script executions, permissions etc. Disadvantage is a little of extra work and a little overhead.
Option 2
Using a task queue. Whatever said and done it's not safe to execute commands from your web facing PHP scripts. If you are already using RabbitMQ or something similar you can use that here. Or else if you are using redis you can use the lpush, rpop methods to make redis behave like a queue. Disadvantage: the result is not immidiately available.
Option 3
Anbother strategy for your php script to enter the data into a table and setup your python script to run as a cron job to check the table once a minute. Disadvantage: the result is not immidiately available.
Option 4
Your current choice but please make sure that you have escaped the data properly by #lafor if this option is chosen #dvhh 's answer ought to work.
In my case it wasn't problem of python version but problem (as I soon found) of the nltk_data folder. First I thought it was as permission problem, so I changed the permissions to 777, but that didn't work.
I had to copy the folder.
First you have to find where was the nltk folder installed. You will find it by running python3 command from your bash and then put following lines:
import nltk
nltk.download('punkt')
nltk.download('averaged_perceptron_tagger')
It will say something like:
[nltk_data] Downloading package punkt to /root/nltk_data...
[nltk_data] Package punkt is already up-to-date!
Now you know you have it installed eg in /root folder (i had it there).
Then put in your python script which is called by php this:
import nltk
print(nltk.data.path)
It will output something like: (note the folders are another if you run it from php script or if you call it from command line)
['/var/www/nltk_data', '/usr/nltk_data', '/usr/share/nltk_data', '/usr/lib/nltk_data', '/usr/share/nltk_data', '/usr/local/share/nltk_data', '/usr/lib/nltk_data', '/usr/local/lib/nltk_data']
Now just copy your original folder to any of the above folders. I did:
cp /root/nltk_data /var/www/nltk_data -r
Voila. It works now.

running a php program from command line with a default argument list

I want to run my php program from the command line, but I always have to type php program instead of just typing program. How do I make it known to the shell that whenever I type program it runs the program?
Also, I have some arguments that I parse using getopt(). I also have a configuration file, which has a DEFAULT_ARGS= setting. I want the user to be able to set the default args, and if they run program without arguments DEFAULT_ARGS takes over and becomes the argument list.
Without writing my own parser, is there a way to "spoof" the argv[] variable or somehow make getopt() work with the string I've specified in the configuration file instead?
For example, if I wanted to run this on the command line: php program -a 300 --debug, instead I will have DEFAULT_ARGS=-a 300 --debug in my configuration file and simply write program to run the program. This is my end goal.
If your OS os Linux add the sheabang on top of the script
#!/usr/bin/php

Why won't shell_exec execute files but does execute simple commands?

Is there any reason why I can not complied files in PHP's shell_exec/exec/system function?
Example of something that does work in command line and PHP's shell_exec function:
<?php
$data = shell_exec("ls");
echo $data;
?>
Example of something that does not work in PHP's shell_exec function but will work in command line (I can confirm that):
<?php
$data = shell_exec("./c-compiled-file argv1 argv2 argv3");
echo $data;
?>
Is there anything I can do on my server so this will work? I've looked everywhere and no solutions I found fixed the problem. The compiled file is in the same directory as the PHP script as well, it just won't execute it. Also if you're asking, yes I have tried this with SSH2 and it still will not execute.
Also PHP is not in safe mode and NO functions are disabled.
Some common glitches when executing external commands from PHP that work fine from shell:
Command uses relative paths but PHP is launched from an arbitrary location:
Use getcwd() / chdir() to get/set working directory
PHP and shell run with different user credentials. This is often the case when PHP runs through a web server.
PHP and shell run different commands. Many people call stuff like exec("foo $bar") and doesn't even check what "foo $bar" contains.
No error checking is done. The bare minimum is to capture and print standard output, standard error, status code and, of course, all PHP error messages including warnings and notices.
You can redirect stderr to sdtout
You can use a PHP function that allows to capture more information, such as exec()
The web server is disallowed to execute the command at operating system level.
Lookout for SELinux or similar tools.
Just a guess, but the binary you're trying to execute might not have the proper permissions. Prepeding it with ./ in the command line forces it to execute, but PHP probably strips that for security purposes. Try this:
chmod +x c-compiled-file
You want to use system in the second case, and not shell_exec.
system executes an external program and displays the output.
shell_exec executes a command via shell and returns the complete output as a string.
and for good measure:
exec simply executes an external program.
Furthermore you want to make sure your external program is executable and (though you have stated it, I'll restate this) has execute permissions for the user which is running the web server. You also want to make sure the directory your external program is running in has the ability to write to its directory or /tmp or whatever output directory you have set.
Finally you should always use absolute paths for executing things like this in cron or php or whatever... so don't use ./c-compiled-file argv1 argv2 argv3, but instead use /home/username/c-compiled-file argv1 argv2 argv3 or whatever the full path is.

Cleanest way to read config settings from PHP file and upload entire project code using shell script

I am a newbie with shell scripting so need a few ideas on parsing a PHP file using a shell script.
Ours is a PHP project and I am improving our shell script which is used to upload code to production server.
There is one PHP config file production.settings.php which needs to be read during upload, for a few constants -
BASE_PATH (path to project root on prod server)
db_host, db_name etc. (database settings of prod database - to be used for taking a backup of the database before upload)
Question
How to read the value of the constants?
They are defined like this:
define("BASE_PATH","/path/to/project/root");
How to read the first uncommented value of the constant?
Note - The constant may be defined more than once in the same file (let's assume the possibilty - this may happen by mistake or there may be commented instances of the line)
So far I am only able to get the number of lines containing the string define("BASE_PATH" using grep in my shell script -
cd ..
PROJECT_ROOT=$PWD
result= grep -ic 'define("BASE_PATH",' $PROJECT_ROOT'/config/main.settings.php'
echo "see"$result
Is this method of parsing good enough or a yml file would be better? Is there any shell command/snippet for doing this so that I can get the result by writing lesser amount of code?
Updates
Check my other questions for more details on this:-
Manipulating an array (printed by php-cli) in shell script,
Assigning values printed by PHP CLI to shell variables,
Initiating dynamic variables (variable variables) in bash shell script
just do it using the php, then call your shell script to invoke the php script.
Assuming you have your bunch of defines defined in defs.php:
define('NAME', 'JOHN');
define('HOBBY', 'FISHING');
then create a php script get_defs.php:
require_once 'defs.php';
$const = get_defined_constants(true);
foreach($const['user'] as $k => $v) {
echo "export $k=$v";
}
then in your shell script, run it like so:
`php get_defs.php`
What happen is, get_defs.php will output bunch of export KEY=VALUE, then shell will run those commands outputted by your php get_defs.php.
Why don't you just code with PHP CLI? That's what you understand? Also maybe you could put constants in a ini file and read them?
If youre comforttable with PHP then use PHP to write the shell script. IF you go this route i would move all config settings to a config file... INI, YAML, XML, whetever floats your boat. Then i would modify the bootstrap of the application that defines your constants to also read from this config file. That way you can use it in botht your script and the app without having to change it.

Categories