I'm using PHPStorm and PyCharm as my IDE.
Is it possible to debug what's going on in the python script when called from PHP?
Here's my code:
$data = array('token' => $this->user_token, 'user_id' => User::getCurrentUser(),
'archive_id' => $archive_id, 'path' => $path );
$result = shell_exec('python /mypi/Main.py ' . escapeshellarg(json_encode($data)));
Ideally I would like to set a breakpoint in PyCharm and whenever the PHP script is executed, for it to allow me to debug the code.
Related
This question already has answers here:
Running a Python script from PHP
(10 answers)
Closed 7 years ago.
I have a python script that I would like to run from PHP. This is my PHP script:
$data = array('as', 'df', 'gh');
// Execute the python script with the JSON data
$result = shell_exec('python /path/to/myScript.py ' . escapeshellarg(json_encode($data)));
// Decode the result
$resultData = json_decode($result, true);
// This will contain: array('status' => 'Yes!')
var_dump($resultData);
And this is my Python script:
import sys, json
# Load the data that PHP sent us
try:
data = json.loads(sys.argv[1])
except:
print "ERROR"
sys.exit(1)
# Generate some data to send to PHP
result = {'status': 'Yes!'}
# Send it to stdout (to PHP)
print json.dumps(result)
I would like to be able to exchange data between PHP and Python, but the above error gives the output:
ERROR NULL
Where am I going wrong ?
:::::EDIT::::::
I ran this:
$data = array('as', 'df', 'gh');
// Execute the python script with the JSON data
$temp = json_encode($data);
$result= shell_exec('C:\Python27\python.exe test.py ' . "'" . $temp . "'");
echo $result;
I am getting No JSON object could be decoded
On my machine, the code works perfectly fine and displays:
array(1) {
'status' =>
string(4) "Yes!"
}
On the other hand, you may make a few changes to diagnose the issue on your machine.
Check the default version of Python. You can do this by running python from the terminal. If you see something like:
Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
you're fine. If you see that you are running Python 3, this could be an issue, since your Python script is written for Python 2. So:
Python 3.4.0 (default, Apr 11 2014, 13:05:11)
[...]
should be a clue.
Again from the terminal, run python myScript.py "[\"as\",\"df\",\"gh\"]". What do you see?
{"status": "Yes!"}
is cool. A different response indicates that the issue is probably with your Python script.
Check permissions. How do you run your PHP script? Do you have access to /path/to/? What about /path/to/myScript.php?
Replace your PHP code by:
<?php
echo file_get_contents("/path/to/myScript.php");
?>
Do you get the actual contents?
Now let's add a few debugging helpers in your PHP code. Since I imagine that you are not using a debugger, the simplest way is to print debug statements. This is OK for 10-LOC scripts, but if you need to deal with larger applications, invest your time in learning how to use PHP debuggers and how do use logging.
Here's the result:
/path/to/demo.php
<?php
$data = array('as', 'df', 'gh');
$pythonScript = "/path/to/myScript.py";
$cmd = array("python", $pythonScript, escapeshellarg(json_encode($data)));
$cmdText = implode(' ', $cmd);
echo "Running command: " . $cmdText . "\n";
$result = shell_exec($cmdText);
echo "Got the following result:\n";
echo $result;
$resultData = json_decode($result, true);
echo "The result was transformed into:\n";
var_dump($resultData);
?>
/path/to/myScript.py
import sys, json
try:
data = json.loads(sys.argv[1])
print json.dumps({'status': 'Yes!'})
except Exception as e:
print str(e)
Now run the script:
cd /path/to
php -f demo.php
This is what I get:
Running command: python /path/to/myScript.py '["as","df","gh"]'
Got the following result:
{"status": "Yes!"}
The result was transformed into:
array(1) {
'status' =>
string(4) "Yes!"
}
yours should be different and contain a hint about what is happening.
I got it to work by adding quotes around the argument!
Like so:
<?php
$data = array('as', 'df', 'gh');
$temp = json_encode($data);
echo shell_exec('python myScript.py ' . "'" . $temp . "'");
?>
I am writing my first BASH script to automate configuration of my (Laravel) web projects.
I have some config files (app/config/local/database.php,app/config/app.php) with PHP arrays that I need to access and modify. For example ...
'providers' => array(
/** Append new service provider value, if it does not exist already */
'Illuminate\Foundation\Providers\ArtisanServiceProvider',
'Illuminate\Auth\AuthServiceProvider',
// ...
)
... or ...
'mysql' => array(
/** Replace value under key "database" to "test_db" */
'database' => 'homestead',
'username' => 'homestead',
)
So far I was using sed expressions like this:
$LV_DB_NAME="test_db"
$LV_DB_FILE="app/config/local/database.php"
gsed -i "s/'database' .*/'database' => '$LV_DB_NAME',/g" $LV_FILE_DB_CONFIG
This feels a little messy to me, especially in the case of example 1.
What would be awesome
Is there any way to get PHP arrays to BASH arrays and work with like you would in PHP?
Example 1
if (!in_array($new_provider, $providers)) {
$providers[] = $new_provider;
}
Example 2
$config['mysql']['database'] = $database_name
Update: What would also be awesome
If there is any other common way how to modify PHP arrays using terminal, I would be glad if you point me to it! I'm sure I'm not the only one who needs to modify PHP configuration arrays using terminal.
mTorres was actually right. If your machine has php cli installed (which is probable), You can easily jump into PHP from your bash scripts. There are multiple ways to do so, I finally settled with this:
print_s "Putting data to file \"$PATH\" ... "
export PATH=$PATH
export DATA_JSON=$DATA_JSON
/usr/bin/php << 'EOF'
<?php
$path = getenv("PATH");
$data = getenv("DATA_JSON");
$data = json_decode($data);
$config = (file_exists($path) && is_array($config_data = require($path))) ? $config_data : array();
foreach ($data as $k => $v) {
$config[$k] = $v;
}
file_put_contents($path, "<?php \n \n return ".var_export($config,true).";");
?>
EOF
}
There are some gotchas with passing associative arrays in BASH, check my other question: Pass BASH associative arrays to PHP script
I can send function arguments to a SOAP client in PHP like this (searchLinks is a method name):
$client = new SoapClient("https://linksearch.api.cj.com/wsdl/version2/linkSearchServiceV2.wsdl", array('trace'=> true));
$results = $client->searchLinks(array("developerKey" => $developerKey,
"token" => '',
"websiteId" => $websiteId,
"advertiserIds" => 'joined'));
If I want to do the same thing in Python, how can I do this? This is the present code:
server=WSDL.Proxy(url)
results=server.searchLinks({'developerkey':dev_key,'token':'','websiteId':website_id,'advertiserIds':'joined'})
When I try to run this Python script, it throws errors. Why is it not taking function parameters like in PHP?
Which library are you using,
Assuming that you are using SOAPpy, You can do .
#!/usr/bin/python
import SOAPpy
url= 'https://linksearch.api.cj.com/wsdl/version2/linkSearchServiceV2.wsdl'
proxy = SOAPpy.WSDL.Proxy(url)
results=proxy.searchLinks({'developerkey': 'dev_key','token':'','websiteId': 'website_id','advertiserIds':'joined'})
I have a server running on SunOS 5.1, and I'm having an issue with the source of a php file displaying. The source starts displaying after => when setting up an array. After the first => it displays the rest of the file. Why would this be happening?
Example source:
index.php
<?php
$tmpVar = 'just testing';
$tmpArray = array(
'test1' => 'rawr1',
'test2' => 'rawr2',
'test3' => 'rawr3'
);
echo "Testing<br/>";
?>
This would output:
'rawr1', 'test2' => 'rawr2', 'test3' => 'rawr3'); echo "Testing<br/>"; ?>
The whole source is displaying, it's just interpreting the part before the > as an HTML tag so you don't see it. View source from your browser and you'll see that your file wasn't parsed at all. That's the problem, you haven't correctly configured your web server to parse PHP at all.
I want to build a php based site that (automate) some commands on my Ubuntu Server
first thing I did was going to the file (sudoers) and add the user www-data so I can execute php commands with root privileges!
# running the web apps with root power!!!
www-data ALL=(ALL) NOPASSWD: ALL
then my PHP code was
<?php
$command = "cat /etc/passwd | cut -d\":\" -f1";
echo 'running the command: <b>'.$command."</b><br />";
echo exec($command);
?>
it returns only one user (the last user) !!! how to make it return all users?
thank you
From the PHP manual on exec:
Return Values
The last line from the result of the
command. If you need to execute a
command and have all the data from the
command passed directly back without
any interference, use the passthru()
function.
To get the output of the executed command, be sure to set and use the
output parameter.
So you have to do something similar to this:
<?php
$output = array();
$command = "cat /etc/passwd | cut -d\":\" -f1";
echo 'running the command: <b>'.$command."</b><br />";
exec($command, &$output);
echo implode("<br />\n", $output);
?>
As #benjamin explains, no need to be root or sudo, no need for SUID.
Just pure PHP. I used the field names from posix_getpwnam.
function getUsers() {
$result = [];
/** #see http://php.net/manual/en/function.posix-getpwnam.php */
$keys = ['name', 'passwd', 'uid', 'gid', 'gecos', 'dir', 'shell'];
$handle = fopen('/etc/passwd', 'r');
if(!$handle){
throw new \RuntimeException("failed to open /etc/passwd for reading! ".print_r(error_get_last(),true));
}
while ( ($values = fgetcsv($handle, 1000, ':')) !== false ) {
$result[] = array_combine($keys, $values);
}
fclose($handle);
return $result;
}
It returns an array containing all users, formatted like this:
[
[
'name' => 'root',
'passwd' => 'x',
'uid' => '0',
'gid' => '0',
'gecos' => 'root',
'dir' => '/root',
'shell' => '/bin/bash',
],
[
'name' => 'daemon',
'passwd' => 'x',
'uid' => '1',
'gid' => '1',
'gecos' => 'daemon',
'dir' => '/usr/sbin',
'shell' => '/usr/sbin/nologin',
],
...
]
Like Matt S said, that's an incredibly bad idea to allow www-data root access on your server. The slightest compromise through your web applications could allow anyone full control of your system.
A better idea would be to make separate scripts for specific accessions then use SUID permissions. This means, a specific user (in this case, www-data) can make small changes to the system through the execution of scripts. Still not a good idea, though. You may be able to work around it with suPHP but security is still a major concern.
/etc/passwd is readable by anyone, so you should be able to execute your command without having any special rights (unless PHP prevents it?).