Change a PHP variable on the fly (while being executed) - php

I have a for-ever-running PHP script currently started on my machine.
I made some changes in the source code of that script: I've changed the value of one variable in global scope.
Now, if I want these changes to be applied, I could stop and restart the script, but then I would loose all the computations this script has already made. So I want to apply the code changes I made without restarting the PHP interpreter instance.
Can I do that?
What I thought about is maybe plug XDebug in the existing "php.exe" process, and try to alter the variable from there, but I don't know how to.
Another idea would be to use a software that could alter the PHP interpreter memory or symbol table, but I don't know any tool like that.
I started this script without a debuger, but I know that Java, when started with a debuger, has some option to "apply code changes without restarting the Java instance". Is there something similar for PHP interpreter?
There is a sample you might try yourself. Create the PHP file 'myfile.php' with the following code:
<?php
if (ob_get_status()) {
ob_end_clean();
}
$variable = 'Hello';
$i = mt_rand(0, 1000);
while (true) {
$i++;
echo $variable . ' ' . $i . PHP_EOL;
sleep(1);
}
Run it in command line: php -f myfile.php
You are now in my current situation: the script is running for ever, and it contains a dynamic variable $i (that I can not actually know the current value in my real world case, because that real world case has no output).
The challenge is now to change the value of $variable from 'Hello' to 'World' (which represents the variable value I changed in my real world case), but without loosing the current value of $i (that represents the currently done computations).
Remember that you cannot alter the 'myfile.php' code before running the script for the 1st time: you must run the 'myfile.php' with the exact same code as I shown, and then start the challenge.

Not within current file except invoking a function which tries to check a condition:
$variable = function() {
return date('l') == 'Saturday' ? ':)' : ':(';
};
while (true) {
echo $variable() . PHP_EOL;
sleep(1);
}

You cannot, you need to read a new value from somewhere ! You can use a database or a temporary file like this :
file1.php
<?php
file_put_contents('var.tmp','hello');
while(true) {
$var = file_get_contents('var.tmp');
print $var . PHP_EOL;
sleep(1);
}
file2.php
<?php
while(true){
$var = readline('$var > ');
file_put_content('var.tmp',$var);
}
Open 2 terminals, in the first one :
php -f file1.php
And the second one
php -f file2.php
Now you can write the value to the second terminal window and it's going to change in the first one.

Related

How do I check if a Python script is running in PHP?

I'm trying to check if a Python script is running in PHP, but I've no idea how.
I've tried using a database: I added an entry "request" with value response "0" and the Python script had to change that value to "1" if it was online. I couldn't get that to work so now I'm asking here
Assuming tasklist is available, this could potentially work: (this example using Windows 10)
I first launched a test2.py script:
The test2.py code is simply running:
from time import sleep
while True:
print('running');
sleep(3);
Then using this bit of php code: (I named procCheck.php)
<?php
$tasks = [];
// Use -v to include the window title info:
exec('tasklist -v 2>NUL', $tasks);
// Check the tasks array for the script we seek:
$entry = preg_grep('/(test2\.py)/', $tasks);
if (!empty($entry)) {
foreach($entry as $value) {
echo $value . PHP_EOL;
}
}
Gives this output: (one wrapped line in my console window)
Know that if there are other windows open with same script name within the window title will be found too. For example, I had the test2.py open as the active tab in Notepad++ and that entry was found as well:
Changing to some other file tab in Notepad++ only found the first entry.

PHP script stops before final echo

I am trainee, learning PHP. As a small project I wrote some code.
I am trying to make a (test) website about cars. I want to show that each car has several options. I have a database in MySQL.
I wrote (this is just a part of the code):
foreach ($key['options'] as $options) {
$contents = str_replace("[OPTION]",$options['text'], $contents);
}
$result= '';
foreach ($key['motor'] as $motor) {
$nm = $motor['name'];
$cnt = $motor['count'];
$result .= $cnt ." " .$nm. " ";
}
return $result;
$paginas .= $contents;
echo $paginas;
So far the code. The thing is, after the result code, the script stops (which is normal).
But I don't want that the script stops, the only thing I want is that the final echo also echo's all my return $result options PLUS the echo of '$paginas'.
It is a bit hard to explain maybe, but I hope you guys understand.
Have you read the documentation of the return statement?
return returns program control to the calling module. Execution resumes at the expression following the called module's invocation.
If called from within a function, the return statement immediately ends execution of the current function, and returns its argument as the value of the function call. return also ends the execution of an eval() statement or script file.
If called from the global scope, then execution of the current script file is ended. If the current script file was included or required, then control is passed back to the calling file.
No matter where it is used, it transfers the control to a different part of the code. The statement(s) following the return statement in the current context are not executed.
I edited the code to echo instead of return. That works.
I made blocks on the website where the information about the car is shown. 1 block per car
The thing is with the $result echo: Now I do not get a list of all different options in 1 block, but I get for every option a new 'block'. so for example:
Block: Steeringwheel. Block:Headlights. Block: Engine type
My goal is to get all these things into 1 block.

the proper way to run a binary in a separate process without a return value

How can I execute an external binary from within my php code, without the page waiting for a return value before it is sent?
Let me clarify. I have a web application that needs to do some fairly cpu intensive tasks, like a lot of file IO amongst other things. I want my user to be able to initiate their task from the GUI in their browser, but I then want my program to hand the task over to a separate file on my server so my user does not have to sit and wait for all the work to be done and risking timing out his/her connection etc.
Let me show you a simple example of what I have tried:
index.php
<?php
echo "This is a test run for an eternal program: <br><br>";
echo shell_exec("hello");
//ok so we can run executables from php script YAY .. but what about if they are long programs?
//If my script is waiting for a return value surely the connection will time out?
echo "<br><br>";
echo shell_exec("long_run"); //Waits for return value as expected. Further more it
//just does not do the file IO
?>
hello
#!/usr/bin/php5
<?php
echo "hello";
?>
long_run
#!/usr/bin/php5
<?php
$f = fopen("time.txt","a");
$i = 1;
while ($i < 10) {
sleep(2);
echo $i . "<br>";
fwrite($f, $i . " ");
$i++;
}
fclose($f);
?>
Note: I wrote the long_run example in PHP for consistency in reality my program is a binary and needs to interface with the PHP that my actual website is written with.
I have contemplated solving my problem by simply having the PHP save instructions to a file which my binary can scan on a regular basis and act upon. I think this kind of interface would be easy enough to implement it, but as someone with limited experience in PHP and indeed in web projects of this nature generally I would really like to get a better idea of the 'correct' approach to this problem. I'm sure there must be a standard way?
You can achieve it by running your command in background just append & to the command you wich to run.
It will run the binary in a seperate process without a return value
<?php
shell_exec("yourcommand &"); // It will run the 'yourcommand' in backgournd
.... // All further operations will be executed right after the shell exec without waiting for it return value

PHP Include file but only first few lines

I am using PHP Include:
<?php include 'file1.php'; ?>
i want to only include the first few lines of file1.php - is this possible?
If you really want to include (run as PHP), then just pull those lines out into a new file:
new.php:
<?php
// line 1
// line 2
And include it in both files:
existing.php and other.php:
<?php
include('new.php');
...
<?php
$return_from_inc = include('file1.php');
?>
file1.php
<?php
if ($x === 1) { return 'A'; }
else { return 'B'; }
//... return ("break") running script wherever you want to
?>
Depending on the content of those first lines, why don't you use PHP Functions?
file1.php
<?php
function what_i_want_to_include(){
//"First lines" content
}
}
existing.php
<?php
include('file1.php');
what_i_want_to_include();
?>
Using functions it's the simplest way to do it.
You can simply use return on the line of your choice and control will be sent back to the calling file.
If called from within a function, the return statement immediately ends execution of the current function, and returns its argument as the value of the function call. return will also end the execution of an eval() statement or script file.
If called from the global scope, then execution of the current script file is ended. If the current script file was included or required, then control is passed back to the calling file. Furthermore, if the current script file was included, then the value given to return will be returned as the value of the include call. If return is called from within the main script file, then script execution ends. If the current script file was named by the auto_prepend_file or auto_append_file configuration options in php.ini, then that script file's execution is ended.
Source: PHP Manual
There are a few options to achieve this, but let me stress out that if this is necessary for your application to work you should really consider reviewing the app design.
If you want it programatically you can either grab the first x lines and use eval() to parse them. Example:
$file_location = '/path/to/file.php';
$number_of_lines = 5; //
$file_array = file($file_location);
if(!$file) {
return false; // file could not be read for some reason
}
$first_lines = array_slice($file_array, 0, $number_of_lines);
$to_be_evaluated = implode('', $first_lines);
eval($to_be_evaluated);
But you should take not that eval expects a string without the php opening tag (<?php), at least, not at the start. So you should search for it and delete it in the first line (if present):
if(strpos($first_lines[0], '<?php') !== false) {
$first_lines[0] = substr(strpos($first_lines[0], '<?php') + 5);
}
Another, and better option, and as suggested above, just pull out the required lines, save them to another file, and include them in both. You could also do this programatically, you could even extract the needed lines and save them to a temporary file on the fly.
Edit it is a 'weird' question, in the sense that it should not be necessary. Could you explain what exactly you are trying to do? Most probably we can come up with a nice alternative.
Edit
As I understand it correctly you have in the file-to-be-included a lot of stuff, but only the database settings are needed. In that case, put them elsewhere! Example:
settings.php
$connection = new mysqli($host, $user, $pass, $db);
if($connection->connect_error) {
die('This failed...');
}
header.php
<?php require_once('settings.php'); ?>
<html>
<head>
<title>My awesome website</title>
... other stuff
</head>
other_file.php
<?php
require_once('settings.php');
$r = $connection->query('SELECT * FROM `my_table` WHERE `random_field`=`random_value`');
etc. etc.
In settings.php you could also put everything in functions to ensure pieces are only executed when needed. You could in example create a get_connection() function, which checks if a database connection exists, otherwise creates it and returns it for usage.
No need for fancy eval() functions at all!
Please bear in mind that it isn't a crime to divide your application in a thousand files. It really isn't!

php cron script not reading arguments from commend line

I have two file.
One is a simple text file that has all the real path link of my scron script with arguments
The other file is my cron script itself.
my contab text file is simply this:
#!/bin/sh
/usr/bin/php -f /home/path/reports/report.php arg1
/usr/bin/php -f /home/path/reports/report.php arg2
The cron script reads the argument in the crontab file and will run accordingly to what argument it is.
report.php --
php $args = $argv[1];
$count = 0;
switch($args){
case 'arg1':
code and create certain file ....
exit;
case 'arg2':
code and create certain file ...
exit;
} // <--- this script runs perfectly if I run script manually through putty commend line, meaning it will run exactly what I want depending on what $argv[1] I put in manual commend line, BUT doesn't run automatically from crontab script
This file does not run and have no idea why, it runs when I manually run report.php through commend line, it works.
One thing i have noticed and got it to kind of work is by changing the report.php to this:
report.php --
$args = $argv[1];
$count = 0;
switch($args){
case ($args ='arg1'): // <- just putting the equal sign makes it work
code and create certain file ....
exit;
case ($args = 'arg2'):
code and create certain file ...
exit;
} // <-- this script was a test to see if it had anything to do with the equal sign, surprisingly script actually worked but only for first case no what matter what argv[1] I had, this is not what I am looking for.
The problem was it only works for the first case, no matter what argument I put in the text file in crobtab it always run the first case. It's probably because I am stating $args = 'arg1', so it always see it as arg1.
So I tried to make it work by doing this instead:
report.php --
$args = $argv[1];
$count = 0;
switch($args){
case ($args =='arg1'): // <- == does not work at all....
code and create certain file ....
exit;
case ($args == 'arg2'):
code and create certain file ...
exit;
} // <--- this script runs perfectly if I run script manually through putty commend line, but not automatically from crontab script
and this runs nothing, it does not pick up my argument at all, just to note this report.php file with the comparison "==" runs perfectly if I run manually on commend line.
What is going on? Why doesn't the cron script read my argument correctly when I use the "==" to find out my arguments from the crontab file.
As for $argv -> "Note: This variable is not available when register_argc_argv is disabled.". I'd suggest to switch to $_SERVER['argv'] and $_SERVER['argc'] (yes, you read correctly) instead of $argv/$argc stuff.
And as for this
case ($args ='arg1'): // <- just putting the equal sign makes it work
man, you clearly do not understand what you doing and what's the difference between ($args=='arg1') and ($args='arg1')!
--[ code for comment bellow ]----
save this as test.php:
<?php
echo $_SERVER['argv'][1] ."\n";
and test it.
$ php test.php abd
abd
The reason the first works is because if you use = instead of == you are setting the variable within the if statement.
Try var_dump($argv) and see if anything is assigned to the variable.
As #arxanas mentions in the comments, your switch is AFU. Read the documentation here. case statements already do the equivalent of $x == [value], so you only need to use case [value]:.
switch($args) {
case ($args =='arg1'):
.
.
.
break;
.
.
.
}
should be
switch($args) {
case 'arg1':
.
.
.
break;
.
.
.
}

Categories